/* * Copyright (c) 2007 NTT DATA Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jp.terasoluna.fw.validation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import jp.terasoluna.fw.beans.IndexedBeanWrapper; import jp.terasoluna.fw.beans.JXPathIndexedBeanWrapperImpl; import jp.terasoluna.fw.util.BeanUtil; import jp.terasoluna.fw.util.ClassLoadException; import jp.terasoluna.fw.util.ClassUtil; import jp.terasoluna.fw.util.PropertyAccessException; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.validator.Field; import org.apache.commons.validator.GenericTypeValidator; import org.apache.commons.validator.GenericValidator; import org.apache.commons.validator.ValidatorAction; import org.apache.commons.validator.ValidatorException; import org.apache.commons.validator.util.ValidatorUtils; /** * TERASOLUNAの入力チェック機能で共通に使用される検証ルールクラス。 * * このクラスが提供する検証ルールとしては、以下のものがある。</p> * * <table border="1"> * <tr> * <td><center><b>検証名</b></center></td> * <td><center><b>メソッド名</b></center></td> * <td><center><b>バリデーション定義ファイル(validation.xml)に * 記述するルール名</b></center></td> * </tr> * <tr> * <td>必須チェック</td> * <td><code>{@link #validateRequired( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>requierd</code></td> * </tr> * <tr> * <td>正規表現チェック</td> * <td><code>{@link #validateMask( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>mask</code></td> * </tr> * <tr> * <td><code>byte</code>型チェック</td> * <td><code>{@link #validateByte( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>byte</code></td> * </tr> * <tr> * <td><code>short</code>型チェック</td> * <td><code>{@link #validateShort( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>short</code></td> * </tr> * <tr> * <td><code>integer</code>型チェック</td> * <td><code>{@link #validateInteger( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>integer</code></td> * </tr> * <tr> * <td><code>long</code>型チェック</td> * <td><code>{@link #validateLong( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>long</code></td> * </tr> * <tr> * <td><code>float</code>型チェック</td> * <td><code>{@link #validateFloat( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>float</code></td> * </tr> * <tr> * <td><code>double</code>型チェック</td> * <td><code>{@link #validateDouble( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>double</code></td> * </tr> * <tr> * <td>日付型チェック</td> * <td><code>{@link #validateDate( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>date</code></td> * </tr> * <tr> * <td>整数指定範囲チェック</td> * <td><code>{@link #validateIntRange( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>intRange</code></td> * </tr> * <tr> * <td>実数指定範囲チェック</td> * <td><code>{@link #validateDoubleRange( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>doubleRange</code></td> * </tr> * <tr> * <td>浮動小数点数指定範囲チェック</td> * <td><code>{@link #validateFloatRange( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>floatRange</code></td> * </tr> * <tr> * <td>最大文字数チェック</td> * <td><code>{@link #validateMaxLength( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>maxLength</code></td> * </tr> * <tr> * <td>最小文字数チェック</td> * <td><code>{@link #validateMinLength( * Object, ValidatorAction, Field, ValidationErrors)}</code></td> * <td><code>minLength</code></td> * </tr> * <tr> * <td>英数字チェック</td> * <td><code>{@link #validateAlphaNumericString(Object, ValidatorAction, * Field, ValidationErrors)}</code></td> * <td><code>alphaNumericString</code></td> * </tr> * <tr> * <td>大文字英数字チェック</td> * <td><code>{@link #validateCapAlphaNumericString(Object, ValidatorAction, * Field, ValidationErrors)}</code></td> * <td><code>capAlphaNumericString</code></td> * </tr> * <tr> * <td>数値チェック</td> * <td><code>{@link #validateNumber(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td><code>number</code></td> * </tr> * <tr> * <td>半角カナ文字チェック</td> * <td><code>{@link #validateHankakuKanaString(Object, ValidatorAction, * Field, ValidationErrors)}</code></td> * <td><code>hankakuKanaString</code></td> * </tr> * <tr> * <td>半角文字チェック</td> * <td><code>{@link #validateHankakuString(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td><code>hankakuString</code></td> * </tr> * <tr> * <td>全角カナ文字チェック</td> * <td><code>{@link #validateZenkakuKanaString(Object, ValidatorAction, * Field, ValidationErrors)}</code></td> * <td><code>zenkakuKanaString</code></td> * </tr> * <tr> * <td>全角文字チェック</td> * <td><code>{@link #validateZenkakuString(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td><code>zenkakuString</code></td> * </tr> * <tr> * <td>入力禁止文字チェック</td> * <td><code>{@link #validateProhibited(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td><code>prohibited</code></td> * </tr> * <tr> * <td>文字列長一致チェック</td> * <td><code>{@link #validateStringLength(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td><code>stringLength</code></td> * </tr> * <tr> * <td>数字文字列チェック</td> * <td><code>{@link #validateNumericString(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td><code>numericString</code></td> * </tr> * <tr> * <td>URLチェック</td> * <td><code>{@link #validateUrl(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td><code>url</code></td> * </tr> * <tr> * <td>配列長一致チェック</td> * <td><code>{@link #validateArrayRange(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td><code>arrayRange</code></td> * </tr> * <tr> * <td>バイト数指定範囲内チェック</td> * <td><code>{@link #validateByteRange(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td><code>byteRange</code></td> * </tr> * <tr> * <td>日付文字列指定範囲内チェック</td> * <td><code>{@link #validateDateRange(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td><code>dateRange</code></td> * </tr> * <tr> * <td>配列・コレクション型フィールド全要素チェック</td> * <td><code>{@link #validateArraysIndex(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td>他の単体フィールド検証ルール名+"Array"(配列長一致チェックは除く)</td> * </tr> * <tr> * <td>相関チェック</td> * <td><code>{@link #validateMultiField(Object, ValidatorAction, Field, * ValidationErrors)}</code></td> * <td>multiField</td> * </tr> * </table> * * <p>このクラスではStrutsのValidWhenを利用した入力チェックメソッドを * サポートしていない。相関チェックを行なう場合、各フレームワークで * 別途、相関チェックを行う仕組みを用意すること。</p> * * <p>必須チェック以外のチェックルールでは、 * 半角スペースのみの文字列が入力値として渡されてきた場合、エラーと判定されない。 * エラーとする場合は必須チェックと組み合わせるか、 * 半角スペースのチェックを追加すること。</p> * * <p>この検証ルールクラスを利用するためには、アクションごとに検証内容を記述した * バリデーション定義ファイル(validation.xml) を作成する必要がある。</p> * * <h5>validation.xmlの記述例(単体フィールド検証)</h5> * <code><pre> * <formset> * ・・・ * <!-- 単体のフィールド検証 --> * <form name="testBean"> * <field property="field" * depends="required,alphaNumericString,maxlength"> * <arg key="testBean.field" position="0"/> * <arg key="${var:maxlength}" position="1"/> * <var> * <var-name>maxlength</var-name> * <var-value>10</var-value> * </var> * </field> * </form> * ・・・ * </formset> * </pre></code> * * <h5>配列・コレクション型フィールドの入力チェック</h5> * * <p>このクラスの * {@link #validateArraysIndex( * Object, ValidatorAction, Field, ValidationErrors)} * メソッドを使用することにより、配列・コレクション型の入力チェックが * 可能になる。</p> * * <p>例えば、fieldsという配列のプロパティを持つbeanインスタンスに対して、 * fields要素に対する必須チェックを行なう場合、validation.xmlのプロパティ名に * fieldsと記述する。 * 実行時には、システム側でfieldsプロパティの配列を0番目から順に走査して、 * 全要素に対してチェックメソッドを実行する。 * 実行するルール(validation.xmlのdepends指定)は、ルール名に”Array”を * 加えた名前を指定する。</p> * * 配列・コレクション型の一覧検証に対応するルールは以下の通りである。 * <ul> * <li><code>requiredArray</code></li> * <li><code>minLengthArray</code></li> * <li><code>maxLengthArray</code></li> * <li><code>maskArray</code></li> * <li><code>byteArray</code></li> * <li><code>shortArray</code></li> * <li><code>integerArray</code></li> * <li><code>longArray</code></li> * <li><code>floatArray</code></li> * <li><code>doubleArray</code></li> * <li><code>dateArray</code></li> * <li><code>intRangeArray</code></li> * <li><code>doubleRangeArray</code></li> * <li><code>floatRangeArray</code></li> * <li><code>creditCardArray</code></li> * <li><code>emailArray</code></li> * <li><code>urlArray</code></li> * <li><code>alphaNumericStringArray</code></li> * <li><code>hankakuKanaStringArray</code></li> * <li><code>hankakuStringArray</code></li> * <li><code>zenkakuStringArray</code></li> * <li><code>zenkakuKanaStringArray</code></li> * <li><code>capAlphaNumericStringArray</code></li> * <li><code>numberArray</code></li> * <li><code>numericStringArray</code></li> * <li><code>prohibitedArray</code></li> * <li><code>stringLengthArray</code></li> * <li><code>dateRangeArray</code></li> * <li><code>byteRangeArray</code></li> * </ul> * * <p>ルールを追加した場合、配列・コレクション用のメソッドを別途作成する * 必要がある。</p> * * <p>入力チェックでエラーが検出された場合、以下の情報を返す。 * <ul> * <li>エラーコード</li> * <li>エラーが発生したプロパティ名</li> * <li>置換文字列</li> * </ul> * </p> * * @see jp.terasoluna.fw.beans.JXPathIndexedBeanWrapperImpl * @see jp.terasoluna.fw.beans.IndexedBeanWrapper */ public class FieldChecks { /** * 本クラスで利用するログ。 */ private static Log log = LogFactory.getLog(FieldChecks.class); /** * 入力値のNull検証と、スペースを除いた入力値の文字列長が0より大きいか * 検証する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 */ public boolean validateRequired( Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); // 検証 if (GenericValidator.isBlankOrNull(value)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値が指定された正規表現に適合するか検証する。 * * <p>以下は、文字列が半角英数字であるときのみtrueを返却する * 検証の設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="maskField" * depends="mask"> * <arg key="sample.escape" position="0"/> * <var> * <var-name>mask</var-name> * <var-value>^([0-9]|[a-z]|[A-Z])*$</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> mask </td> * <td>正規表現</td> * <td>true</td> * <td>入力文字列が指定された正規表現に合致するときは <code>true</code> * が返却される。指定されない場合はValidatorException * がスローされる。</td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 * @exception ValidatorException 設定ファイルからmask(正規表現)の値が * 取得できない場合にスローされる。 */ public boolean validateMask( Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 正規表現 String mask = field.getVarValue("mask"); // varからmaskが取得できない場合はValidatorException if (StringUtils.isEmpty(mask)) { log.error("var[mask] must be specified."); throw new ValidatorException("var[mask] must be specified."); } // 検証 if (!GenericValidator.matchRegexp(value, mask)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値がbyte型に変換可能か検証する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 */ public boolean validateByte( Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (GenericTypeValidator.formatByte(value) == null) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値がshort型に変換可能か検証する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 */ public boolean validateShort( Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (GenericTypeValidator.formatShort(value) == null) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値がint型に変換可能か検証する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 */ public boolean validateInteger( Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (GenericTypeValidator.formatInt(value) == null) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値がlong型に変換可能か検証する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 */ public boolean validateLong( Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (GenericTypeValidator.formatLong(value) == null) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値がfloat型に変換可能か検証する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 */ public boolean validateFloat( Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (GenericTypeValidator.formatFloat(value) == null) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値がdouble型に変換可能か検証する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 */ public boolean validateDouble( Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (GenericTypeValidator.formatDouble(value) == null) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値が有効な日付か検証する。 * * <p>fieldに「datePattern」変数が定義されている場合、 * <code>java.text.SimpleDateFormat</code>クラスを * 利用したフォーマットの検証が行われる。</p> * * <p>fieldに「datePatternStrict」変数が定義されている場合、 * <code>java.text.SimpleDateFormat</code>クラスを利用したフォーマットと * 桁数の検証が行われる。 * 例えば、'2/12/1999'は'MM/dd/yyyy'形式のフォーマットにすると * 月(Month)が2桁でないため、検証エラーとなる。</p> * * <p>「datePattern」変数と、「datePatternStrict」変数の両方が指定された * 場合、「datePattern」変数が優先して使用される。 * 「datePattern」変数と、「datePatternStrict」変数の両方が指定されていない * 場合、例外が発生する。また、日付パターンに無効な文字列が含まれている * 場合も例外が発生する</p> * * <p>フォーマット時には必ず「setLenient=false」が設定されるため、 * 2000/02/31のような存在しない日付は、いずれの場合も許容されない。</p> * * 以下は、文字列がyyyy/MM/dd型の日付パターンに合致することを検証 * する場合の設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="dateField" * depends="date"> * <arg key="sample.dateField" position="0"/> * <var> * <var-name>datePattern</var-name> * <var-value>yyyy/MM/dd</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> datePattern </td> * <td>日付パターン</td> * <td>false</td> * <td>日付パターンを指定する。入力値の桁数チェックは行わない。 * たとえば、日付パターンがyyyy/MM/ddの場合、2001/1/1はエラーにならない。 * datePatternとdatePatternStrictが両方指定されている場合は、 * datePatternが優先して使用される。 * </td> * </tr> * <tr> * <td> datePatternStrict </td> * <td>日付パターン</td> * <td>false</td> * <td>日付パターンを指定する。入力値の桁数が、 * 指定された日付パターンの桁数に合致するかのチェックを行う。 * たとえば、日付パターンがyyyy/MM/ddの場合、2001/1/1はエラーになる。 * datePatternとdatePatternStrictが両方指定されている場合は、 * datePatternが優先して使用される。 * </td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 * @throws ValidatorException validation定義ファイルの設定ミスがあった場合 * スローされる例外。 */ public boolean validateDate( Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // フォーマット用の日付パターン String datePattern = field.getVarValue("datePattern"); String datePatternStrict = field.getVarValue("datePatternStrict"); // 検証 Date result = null; try { result = ValidationUtil.toDate(value, datePattern, datePatternStrict); } catch (IllegalArgumentException e) { // 日付パターンが不正な場合 String message = "Mistake on validation definition file. " + "- datePattern or datePatternStrict is invalid. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } if (result == null) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値が指定されたint型に変換可能であり、 * かつ指定された範囲内か検証する。 * * <p>以下は、文字列が10から100までの範囲内の数値であるときのみ * trueを返却する検証の設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="intField" * depends="intRange"> * <arg key="sample.intField" position="0"/> * <var> * <var-name>intRangeMin</var-name> * <var-value>10</var-value> * </var> * <var> * <var-name>intRangeMax</var-name> * <var-value>100</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> intRangeMin </td> * <td>最小値</td> * <td>false</td> * <td>範囲指定の最小値を設定する。設定しない場合、Integerの最小値が * 指定される。 * 数値以外の文字列が入力された場合、例外がスローされる。</td> * </tr> * <tr> * <td> intRangeMax </td> * <td>最大値</td> * <td>false</td> * <td>範囲指定の最大値を設定する。設定しない場合、Integerの最大値が * 指定される。 * 数値以外の文字列が入力された場合、例外がスローされる。</td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 * @throws ValidatorException validation定義ファイルの設定ミスがあった場合 * スローされる例外。 */ public boolean validateIntRange( Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証値をintに変換 --- Integer型ではない場合、検証エラー。 int intValue = 0; try { intValue = Integer.parseInt(value); } catch (NumberFormatException e) { rejectValue(errors, field, va, bean); return false; } // 範囲指定値 --- 設定値がInteger型ではない場合、例外。 // 設定なしはデフォルト値を使用する。 String strMin = field.getVarValue("intRangeMin"); int min = Integer.MIN_VALUE; if (!GenericValidator.isBlankOrNull(strMin)) { try { min = Integer.parseInt(strMin); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- intRangeMin is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } String strMax = field.getVarValue("intRangeMax"); int max = Integer.MAX_VALUE; if (!GenericValidator.isBlankOrNull(strMax)) { try { max = Integer.parseInt(strMax); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- intRangeMax is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } // 検証 if (!GenericValidator.isInRange(intValue, min, max)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値が指定されたdouble型に変換可能であり、 * かつ指定された範囲内か検証する。 * * <p>以下は、文字列が10から100までの範囲内の数値であるときのみ * trueを返却する検証の設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="doubleField" * depends="doubleRange"> * <arg key="sample.doubleField" position="0"/> * <var> * <var-name>doubleRangeMin</var-name> * <var-value>10.0</var-value> * </var> * <var> * <var-name>doubleRangeMax</var-name> * <var-value>100.0</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> doubleRangeMin </td> * <td>最小値</td> * <td>false</td> * <td>範囲指定の最小値を設定する。設定しない場合、Doubleの最小値が * 指定される。 * 数値以外の文字列が入力された場合、例外がスローされる。</td> * </tr> * <tr> * <td> doubleRangeMax </td> * <td>最大値</td> * <td>false</td> * <td>範囲指定の最大値を設定する。設定しない場合、Doubleの最大値が * 指定される。 * 数値以外の文字列が入力された場合、例外がスローされる。</td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 * @throws ValidatorException validation定義ファイルの設定ミスがあった場合 * スローされる例外。 */ public boolean validateDoubleRange( Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証値をdoubleに変換 --- Double型ではない場合、検証エラー。 double dblValue = 0; try { dblValue = Double.parseDouble(value); } catch (NumberFormatException e) { rejectValue(errors, field, va, bean); return false; } // 範囲指定値 --- 設定値がDouble型ではない場合、例外。 // 設定なしはデフォルト値を使用する。 String strMin = field.getVarValue("doubleRangeMin"); double min = Double.MIN_VALUE; if (!GenericValidator.isBlankOrNull(strMin)) { try { min = Double.parseDouble(strMin); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- doubleRangeMin is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } String strMax = field.getVarValue("doubleRangeMax"); double max = Double.MAX_VALUE; if (!GenericValidator.isBlankOrNull(strMax)) { try { max = Double.parseDouble(strMax); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- doubleRangeMax is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } // 検証 if (!GenericValidator.isInRange(dblValue, min, max)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値が指定されたfloat型に変換可能であり、 * かつ指定された範囲内か検証する。 * * <p>以下は、文字列が10から100までの範囲内の数値であるときのみ * trueを返却する検証の設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="floatField" * depends="floatRange"> * <arg key="sample.floatField" position="0"/> * <var> * <var-name>floatRangeMin</var-name> * <var-value>10</var-value> * </var> * <var> * <var-name>floatRangeMax</var-name> * <var-value>100</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> floatRangeMin </td> * <td>最小値</td> * <td>false</td> * <td>範囲指定の最小値を設定する。設定しない場合、Floatの最小値が * 指定される。 * 数値以外の文字列が入力された場合、例外がスローされる。</td> * </tr> * <tr> * <td> floatRangeMax </td> * <td>最大値</td> * <td>false</td> * <td>範囲指定の最大値を設定する。設定しない場合、Floatの最大値が * 指定される。 * 数値以外の文字列が入力された場合、例外がスローされる。</td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 * @throws ValidatorException validation定義ファイルの設定ミスがあった場合 * スローされる例外。 */ public boolean validateFloatRange( Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証値をfloatに変換 --- Float型ではない場合、検証エラー。 float floatValue = 0; try { floatValue = Float.parseFloat(value); } catch (NumberFormatException e) { rejectValue(errors, field, va, bean); return false; } // 範囲指定値 --- 設定値がFloat型ではない場合、例外。 // 設定なしはデフォルト値を使用する。 String strMin = field.getVarValue("floatRangeMin"); float min = Float.MIN_VALUE; if (!GenericValidator.isBlankOrNull(strMin)) { try { min = Float.parseFloat(strMin); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- floatRangeMin is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } String strMax = field.getVarValue("floatRangeMax"); float max = Float.MAX_VALUE; if (!GenericValidator.isBlankOrNull(strMax)) { try { max = Float.parseFloat(strMax); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- floatRangeMax is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } // 検証 if (!GenericValidator.isInRange(floatValue, min, max)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値の文字数が指定された最大文字数以下か検証する。 * * <p>以下は、文字列が10文字以下であるときのみ * trueを返却する検証の設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="stringField" * depends="maxLength"> * <arg key="sample.stringField" position="0"/> * <var> * <var-name>maxlength</var-name> * <var-value>10</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> maxlength </td> * <td>最大文字数</td> * <td>true</td> * <td>文字列の最大文字数を設定する。 * 数値以外の文字列が入力された場合、例外がスローされる。</td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 * @throws ValidatorException validation定義ファイルの設定ミスがあった場合 * スローされる例外。 */ public boolean validateMaxLength( Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 最大桁数 int max = 0; try { max = Integer.parseInt(field.getVarValue("maxlength")); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- maxlength is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } // 検証 if (!GenericValidator.maxLength(value, max)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 入力値の文字数が指定された最小文字数以上か検証する。 * * <p>以下は、文字列が10文字以上であるときのみ * trueを返却する検証の設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="stringField" * depends="minLength"> * <arg key="sample.stringField" position="0"/> * <var> * <var-name>minlength</var-name> * <var-value>10</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> minlength </td> * <td>最小文字数</td> * <td>true</td> * <td>文字列の最小文字数を設定する。 * 数値以外の文字列が入力された場合、例外がスローされる。</td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va 検証中の<code>ValidatorAction</code>インスタンス。 * @param field 検証中の<code>Field</code>インスタンス。 * @param errors 検証エラーが発生した場合、 * エラー情報を格納するオブジェクト。 * @return 検証に成功した場合は<code>true</code>を返す。 * 検証エラーがある場合、<code>false</code>を返す。 * @throws ValidatorException validation定義ファイルの設定ミスがあった場合 * スローされる例外。 */ public boolean validateMinLength( Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 最小桁数 int min = 0; try { min = Integer.parseInt(field.getVarValue("minlength")); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- minlength is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } // 検証 if (!GenericValidator.minLength(value, min)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドが英数字であることをチェックする。 * 正規表現<code>^([0-9]|[a-z]|[A-Z])*$</code>を使用する。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true */ public boolean validateAlphaNumericString(Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (!ValidationUtil.isAlphaNumericString(value)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドが大文字英数字であることをチェックする。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true */ public boolean validateCapAlphaNumericString(Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (!ValidationUtil.isUpperAlphaNumericString(value)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドが数値であることをチェックする。 * 全角数字を使用すると検証に失敗する。 * チェックに引っかかった場合は、 * エラー情報をerrorsに追加し、falseを返却する。 * * <p>まず、入力された文字列を用い、BigDecimal 型を生成する * ここで生成不可能ならばエラー処理を行なう。 * * 次に整数部の桁数が指定されている場合に、桁数の確認を行う。 * validation.xml で isAccordedInteger() * が "true" 指定されている場合のみ * 整数桁数の同一チェックが行われる。 * チェックに引っかかった場合は、エラー処理を行なう。 * * 最後に小数部の桁数が指定されている場合に、桁数の確認を行う。 * validation.xmlでisAccordedScaleが"true"である場合のみ * 小数桁数の同一チェックが行われる。 * * <p> * 下記は、整数部3、小数部2である数値を検証する例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="numberField" * depends="number"> * <arg key="sample.numberField" position="0"/> * <var> * <var-name>integerLength</var-name> * <var-value>3</var-value> * </var> * <var> * <var-name>scale</var-name> * <var-value>2</var-value> * </var> * <var> * <var-name>isAccordedInteger</var-name> * <var-value>true</var-value> * </var> * <var> * <var-name>isAccordedScale</var-name> * <var-value>true</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> <code>integerLength</code> </td> * <td> 整数部桁数 </td> * <td> <code>false</code> </td> * <td>整数の桁数を設定する。<code>isAccordedInteger</code>指定が * 無いときは、指定桁数以内の検証を行う。 * 省略時は、<code>int</code>型の最大値が指定される。 * 非数値を設定した場合、例外がスローされる。</td> * </tr> * <tr> * <td> <code>scale</code> </td> * <td> 小数部桁数 </td> * <td> <code>false</code> </td> * <td>小数値の桁数を設定する、<code>isAccordedScale</code>指定が * 無いときは、指定桁数以内の検証を行う。 * 省略時は、<code>int</code>型の最大値が指定される。 * 非数値を設定した場合、例外がスローされる。</td> * </tr> * <tr> * <td> <code>isAccordedInteger</code> </td> * <td> 整数桁数一致チェック </td> * <td> <code>false</code> </td> * <td> <code>true</code>が指定されたとき、整数桁数の一致チェックが * 行なわれる。省略時、<code>true</code>以外の文字列が設定された時は * 桁数以内チェックとなる。</td> * </tr> * <tr> * <td> <code>isAccordedScale</code> </td> * <td> 小数桁数一致チェック </td> * <td> <code>false</code> </td> * <td> <code>true</code>が指定されたとき、小数桁数の一致チェックが * 行なわれる。省略時、<code>true</code>以外の文字列が設定された時は * 桁数以内チェックとなる。</td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true * @throws ValidatorException validation定義ファイルの設定ミスがあった場合 * スローされる例外。 */ public boolean validateNumber(Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証値が半角ではない場合エラー。 if (!ValidationUtil.isHankakuString(value)) { rejectValue(errors, field, va, bean); return false; } // 検証値をBigDecimalに変換 BigDecimal number = null; try { number = new BigDecimal(value); } catch (NumberFormatException e) { rejectValue(errors, field, va, bean); return false; } // 整数部桁数取得 int integerLength = Integer.MAX_VALUE; String integerLengthStr = field.getVarValue("integerLength"); if (!GenericValidator.isBlankOrNull(integerLengthStr)) { try { integerLength = Integer.parseInt(integerLengthStr); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- integerLength is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } // 小数部桁数取得 int scaleLength = Integer.MAX_VALUE; String scaleStr = field.getVarValue("scale"); if (!GenericValidator.isBlankOrNull(scaleStr)) { try { scaleLength = Integer.parseInt(scaleStr); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- scale is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } // 整数桁数一致チェックか boolean isAccordedInteger = "true".equals(field.getVarValue("isAccordedInteger")); // 小数桁数一致チェックか boolean isAccordedScale = "true".equals(field.getVarValue("isAccordedScale")); // 検証 if (!ValidationUtil.isNumber( number, integerLength, isAccordedInteger, scaleLength, isAccordedScale)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドが半角カナ文字列であることをチェックする。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true */ public boolean validateHankakuKanaString(Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (!ValidationUtil.isHankakuKanaString(value)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドが半角文字列であることをチェックする。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true */ public boolean validateHankakuString(Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (!ValidationUtil.isHankakuString(value)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドが全角文字列であることをチェックする。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true */ public boolean validateZenkakuString(Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (!ValidationUtil.isZenkakuString(value)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドが全角カタカナ文字列で あることをチェックする。<br> * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true */ public boolean validateZenkakuKanaString(Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (!ValidationUtil.isZenkakuKanaString(value)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドに入力禁止文字列が混入しているか * どうかをチェックする。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * <p>以下は、禁止文字列チェックの設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="stringField" * depends="prohibited"> * <arg key="sample.stringField" position="0"/> * <var> * <var-name>chars</var-name> * <var-value>!"#$%&'()<></var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> chars </td> * <td>入力禁止キャラクタ</td> * <td> true </td> * <td>入力を禁止する文字。設定されない場合は、ValidatorException * がスローされる。</td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true * @exception ValidatorException 設定ファイルからcharsの値が取得できない * 場合にスローされる。 */ public boolean validateProhibited(Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 入力禁止文字列 String prohibitedStr = field.getVarValue("chars"); // charsが取得できない場合はValidatorExceptionをスロー if (StringUtils.isEmpty(prohibitedStr)) { log.error("var[chars] must be specified."); throw new ValidatorException("var[chars] must be specified."); } // 検証 if (!ValidationUtil.hasNotProhibitedChar(value, prohibitedStr)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドが半角数字であることをチェックする。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true */ public boolean validateNumericString(Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 検証 if (!ValidationUtil.isNumericString(value)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドの文字列長が一致していることをチェックする。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * <p>以下は、文字列長が5であるときのみtrueを返却する * 検証の設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="stringField" * depends="stringLength"> * <arg key="sample.stringField" position="0"/> * <var> * <var-name>stringLength</var-name> * <var-value>5</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> stringLength </td> * <td>入力文字列長</td> * <td> false </td> * <td>入力文字列長を指定する。 * 省略時は、<code>int</code>型の最大値が指定される。</td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true * @throws ValidatorException validation定義ファイルの設定ミスがあった場合 * スローされる例外。 */ public boolean validateStringLength(Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 文字列長 int length = Integer.MAX_VALUE; String lengthStr = field.getVarValue("stringLength"); try { length = Integer.valueOf(lengthStr).intValue(); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- stringLength is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } // 検証 if (value.length() != length) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドの配列・コレクションの長さが、 * 指定数の範囲内であることをチェックする。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * <p>以下は、配列・コレクションの長さが4~7であるときのみtrueを返却する * 検証の設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="arrayField" * depends="arrayRange"> * <arg key="sample.arrayField" position="0"/> * <var> * <var-name>minArrayLength</var-name> * <var-value>4</var-value> * </var> * <var> * <var-name>maxArrayLength</var-name> * <var-value>7</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> minArrayLength </td> * <td>最小配列数</td> * <td>false</td> * <td>配列の最小配列数を指定する。 * 最小配列数の指定がない場合、0が指定される。</td> * </tr> * <tr> * <td> maxArrayLength </td> * <td>最大配列数</td> * <td>false</td> * <td>配列の最大配列数を指定する。 * 最大配列数の指定がない場合、 * <code>int</code>型の最大値が指定される。</td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true * @throws ValidatorException validation定義ファイルの設定ミスがあった場合 * スローされる例外。 */ public boolean validateArrayRange(Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // チェック対象のbeanがnullの場合はValidatorExceptionをスロー if (bean == null) { String message = "target of validateArrayRange must be not null."; log.error(message); throw new ValidatorException(message); } try { Class<?> type = BeanUtil.getBeanPropertyType(bean, field.getProperty()); if (type == null) { String message = "Cannot get property type[" + bean.getClass().getName() + "." + field.getProperty() + "]"; log.error(message); throw new ValidatorException(message); } else if (!type.isArray() && !Collection.class.isAssignableFrom(type)) { String message = "property [" + bean.getClass().getName() + "." + field.getProperty() + "] must be instance of Array or Collection."; log.error(message); throw new ValidatorException(message); } } catch (PropertyAccessException e) { String message = "Cannot get property type[" + bean.getClass().getName() + "." + field.getProperty() + "]"; log.error(message, e); throw new ValidatorException(message); } // 検証値 Object obj = null; try { obj = BeanUtil.getBeanProperty(bean, field.getProperty()); } catch (PropertyAccessException e) { String message = "Cannot get property [" + bean.getClass().getName() + "." + field.getProperty() + "]"; log.error(message, e); throw new ValidatorException(message); } // 指定する配列の最小サイズ int min = 0; String minStr = field.getVarValue("minArrayLength"); if (!GenericValidator.isBlankOrNull(minStr)) { try { min = Integer.parseInt(minStr); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- minArrayLength is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } // 指定する配列の最大サイズ int max = Integer.MAX_VALUE; String maxStr = field.getVarValue("maxArrayLength"); if (!GenericValidator.isBlankOrNull(maxStr)) { try { max = Integer.parseInt(maxStr); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- maxArrayLength is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } // 検証 try { if (!ValidationUtil.isArrayInRange(obj, min, max)) { rejectValue(errors, field, va, bean); return false; } } catch (IllegalArgumentException e) { log.error(e.getMessage()); throw new ValidatorException(e.getMessage()); } return true; } /** * 指定されたフィールドがURL形式かどうかチェックする。<br> * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * <p>以下は、HTTP、FTPプロトコル指定可能、ダブルスラッシュ指定可能、 * URLの分割可能である検証の設定例である。 * </p> * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="date" * depends="url"> * <arg key="label.date" position="0"/> * <var> * <var-name>allowallschemes</var-name> * <var-value>false</var-value> * </var> * <var> * <var-name>allow2slashes</var-name> * <var-value>true</var-value> * </var> * <var> * <var-name>nofragments</var-name> * <var-value>false</var-value> * </var> * <var> * <var-name>schemes</var-name> * <var-value>http,ftp</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> allowallschemes </td> * <td>true(or false)</td> * <td>false</td> * <td>全てのスキームを許可するか判断するフラグ。デフォルトfalse。</td> * </tr> * <tr> * <td> allow2slashes </td> * <td>true(or false)</td> * <td>false</td> * <td>ダブルスラッシュを許可するか判断するフラグ。デフォルトfalse。</td> * </tr> * <tr> * <td> nofragments </td> * <td>true(or false)</td> * <td>false</td> * <td>URL分割禁止か判断するフラグ。デフォルトfalse。</td> * </tr> * <tr> * <td> schemes </td> * <td>プロトコル</td> * <td>false</td> * <td>許可するスキーム。複数ある場合はカンマ区切りで指定。 * デフォルトはhttp, https, ftp。</td> * </tr> * </table> * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 入力値が正しければ true */ public boolean validateUrl(Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // オプションの変数を取得する boolean allowallschemes = "true".equals(field.getVarValue("allowallschemes")); boolean allow2slashes = "true".equals(field.getVarValue("allow2slashes")); boolean nofragments = "true".equals(field.getVarValue("nofragments")); String schemesVar = allowallschemes ? null : field .getVarValue("schemes"); // 検証 if (!ValidationUtil.isUrl( value, allowallschemes, allow2slashes, nofragments, schemesVar)) { rejectValue(errors, field, va, bean); return false; } return true; } /** * 指定されたフィールドのバイト列長が指定した範囲内であることを * チェックする。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * <p>以下は、バイト列長が5以上、10以下であるときのみ true * を返却する検証の設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="stringField" * depends="byteRange"> * <arg key="sample.stringField" position="0"/> * <var> * <var-name>maxByteLength</var-name> * <var-value>10</var-value> * </var> * <var> * <var-name>minByteLength</var-name> * <var-value>5</var-value> * </var> * <var> * <var-name>encoding</var-name> * <var-value>Windows-31J</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> maxByteLength </td> * <td>最大バイト数</td> * <td>false</td> * <td>入力文字列バイト長を検証するための最大バイト長。 * 省略時は、<code>int</code>型の最大値が指定される。</td> * </tr> * <tr> * <td> minByteLength </td> * <td>最小バイト数</td> * <td>false</td> * <td>入力文字列バイト長を検証するための最小バイト長。 * 省略時は、0が指定される。</td> * </tr> * <tr> * <td> encoding </td> * <td>文字エンコーディング</td> * <td>false</td> * <td>入力文字をバイト列に変換する際に使用する文字エンコーディング。 * 省略された場合はVMのデフォルトエンコーディングが使用される。</td> * </tr> * </table> * * @param bean 検査対象のオブジェクト * @param va Validatorにより用意されたValidatorAction * @param field フィールドオブジェクト * @param errors エラー * @return 入力値が正しければ true * @throws ValidatorException validation定義ファイルの設定ミスがあった場合 * スローされる例外。 */ public boolean validateByteRange(Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // エンコーディング String encoding = field.getVarValue("encoding"); // 最小バイト列長 int min = 0; String minStr = field.getVarValue("minByteLength"); if (!GenericValidator.isBlankOrNull(minStr)) { try { min = Integer.parseInt(minStr); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- minByteLength is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } // 最大バイト列長 int max = Integer.MAX_VALUE; String maxStr = field.getVarValue("maxByteLength"); if (!GenericValidator.isBlankOrNull(maxStr)) { try { max = Integer.parseInt(maxStr); } catch (NumberFormatException e) { String message = "Mistake on validation definition file. " + "- maxByteLength is not number. " + "You'll have to check it over. "; log.error(message, e); throw new ValidatorException(message); } } // 検証 try { if (!ValidationUtil.isByteInRange(value, encoding, min, max)) { rejectValue(errors, field, va, bean); return false; } } catch (IllegalArgumentException e) { log.error("encoding[" + encoding + "] is not supported."); throw new ValidatorException("encoding[" + encoding + "] is not supported."); } return true; } /** * 日付が指定した範囲内であるかどうかチェックする。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * <p>以下は、日付が2000/01/01から2010/12/31の範囲内であるかどうかの * 検証の設定例である。 * * <h5>validation.xmlの記述例</h5> * <code><pre> * <form name="sample"> * ・・・ * <field property="date" * depends="dateRange"> * <arg key="date" position="0"/> * <var> * <var-name>startDate</var-name> * <var-value>2000/01/01</var-value> * </var> * <var> * <var-name>endDate</var-name> * <var-value>2010/12/31</var-value> * </var> * </field> * ・・・ * </form> * </pre></code> * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> startDate </td> * <td>開始日付</td> * <td>false</td> * <td>日付範囲の開始の閾値となる日付。 * 日付パターンで指定した形式で設定すること。</td> * </tr> * <tr> * <td> endDate </td> * <td>終了日付</td> * <td>false</td> * <td>日付範囲の終了の閾値となる日付。 * 日付パターンで指定した形式で設定すること。</td> * </tr> * <tr> * <td> datePattern </td> * <td>日付パターン</td> * <td>false</td> * <td>日付パターンを指定する。入力値の桁数チェックは行わない。 * たとえば、日付パターンがyyyy/MM/ddの場合、2001/1/1はエラーにならない。 * datePatternとdatePatternStrictが両方指定されている場合は、 * datePatternが優先して使用される。 * </td> * </tr> * <tr> * <td> datePatternStrict </td> * <td>日付パターン</td> * <td>false</td> * <td>日付パターンを指定する。入力値の桁数が、 * 指定された日付パターンの桁数に合致するかのチェックを行う。 * たとえば、日付パターンがyyyy/MM/ddの場合、2001/1/1はエラーになる。 * datePatternとdatePatternStrictが両方指定されている場合は、 * datePatternが優先して使用される。 * </td> * </tr> * </table> * * @param bean 検査対象のオブジェクト * @param va Validatorにより用意されたValidatorAction * @param field フィールドオブジェクト * @param errors エラー * @return 入力値が正しければ true * @throws ValidatorException datePatternまたはdatePatternStrictに不正な * パターン文字が含まれる場合、startDateまたはendDateが日付に変換できない * 場合にスローされる */ public boolean validateDateRange(Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { // 検証値 String value = extractValue(bean, field); if (StringUtils.isEmpty(value)) { return true; } // 日付入力パターン String datePattern = field.getVarValue("datePattern"); String datePatternStrict = field.getVarValue("datePatternStrict"); // 範囲指定する日付 String startDateStr = field.getVarValue("startDate"); String endDateStr = field.getVarValue("endDate"); // 検証 try { if (!ValidationUtil.isDateInRange(value, startDateStr, endDateStr, datePattern, datePatternStrict)) { rejectValue(errors, field, va, bean); return false; } } catch (IllegalArgumentException e) { log.error(e.getMessage()); throw new ValidatorException(e.getMessage()); } return true; } /** * 指定されたフィールドに一致する全てのプロパティ値をチェックする。 * チェックに引っかかった場合は、エラー情報をerrorsに追加し、 * falseを返却する。 * * <p>配列・コレクション型に対してのフィールドチェックが可能である。 * 配列・コレクションの全ての要素に対して、validation.xmlで * 定義したdepends名から”Array”を取ったチェックルールを呼び出す。 * depends="requiredArray" ⇒ "required" (必須チェック) * * @param bean 検査対象のJavaBeanインスタンス * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param errors エラー * @return 要素すべての入力値が正しければ true * @throws ValidatorException validation定義ファイルの設定ミスがあった場合 * 、チェック対象のbeanがnullである場合にスローされる例外。 */ public boolean validateArraysIndex(Object bean, ValidatorAction va, Field field, ValidationErrors errors) throws ValidatorException { if (bean == null) { log.error("validation target bean is null."); throw new ValidatorException("validation target bean is null."); } @SuppressWarnings("rawtypes") Class[] paramClass = null; // 検証メソッドの引数の型 Method method = null; // 検証メソッド try { paramClass = getParamClass(va); if (paramClass == null || paramClass.length == 0) { String message = "Mistake on validation rule file. " + "- Can not get argument class. " + "You'll have to check it over. "; log.error(message); throw new ValidatorException(message); } method = getMethod(va, paramClass); if (method == null) { String message = "Mistake on validation rule file. " + "- Can not get validateMethod. " + "You'll have to check it over. "; log.error(message); throw new ValidatorException(message); } } catch (RuntimeException e) { log.error(e.getMessage(), e); throw new ValidatorException(e.getMessage()); } try { // 配列のインデックスが変わっても、値が変化しないパラメータ Object[] argParams = new Object[paramClass.length]; argParams[0] = bean; argParams[1] = va; argParams[3] = errors; // 検証値(配列要素)の取り出し IndexedBeanWrapper bw = getIndexedBeanWrapper(bean); Map<String, Object> propertyMap = bw.getIndexedPropertyValues(field.getKey()); boolean isValid = true; // 検証フラグ for (String key : propertyMap.keySet()) { // インデックス付きのプロパティ名でフィールドを書き換える Field indexedField = (Field) field.clone(); indexedField.setKey(key); indexedField.setProperty(key); argParams[2] = indexedField; // フィールド // 入力チェックメソッドの呼び出し boolean bool = (Boolean) method.invoke( this, argParams); if (!bool) { isValid = false; } } return isValid; } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof ValidatorException) { throw (ValidatorException) t; } log.error(t.getMessage(), t); throw new ValidatorException(t.getMessage()); } catch (Exception e) { log.error(e.getMessage(), e); throw new ValidatorException(e.getMessage()); } } /** * IndexedBeanWrapper実装クラスを取得する。 * @param bean ターゲットのBean * @return IndexedBeanWrapperの実装 */ protected IndexedBeanWrapper getIndexedBeanWrapper(Object bean) { return new JXPathIndexedBeanWrapperImpl(bean); } /** * 検証ルールに渡される引数クラス配列を取得する。 * * @param va Validatorにより用意されたValidatorAction * @return 引数クラス配列 */ @SuppressWarnings("rawtypes") protected Class[] getParamClass(ValidatorAction va) { StringTokenizer st = new StringTokenizer(va.getMethodParams(), ","); Class[] paramClass = new Class[st.countTokens()]; for (int i = 0; st.hasMoreTokens(); i++) { try { String key = st.nextToken().trim(); paramClass[i] = ClassUtils.getClass(key); } catch (ClassNotFoundException e) { return null; } } return paramClass; } /** * 配列・コレクションの要素を検証するメソッドを取得する。 * * @param va ValidatorAction * @param paramClass 引数クラス配列 * @return 検証メソッド */ protected Method getMethod( ValidatorAction va, @SuppressWarnings("rawtypes") Class[] paramClass) { String methodNameSource = va.getName(); if (methodNameSource == null || "".equals(methodNameSource)) { // メソッド名指定がnullまたは空文字のときnull返却。 return null; } // name属性から"Array"を除去したメソッド名を生成する // xxxxArray→validateXxxx char[] chars = methodNameSource.toCharArray(); chars[0] = Character.toUpperCase(chars[0]); String validate = "validate" + new String(chars); String methodName = validate.substring(0, validate.length() - "Array".length()); Method method = null; try { method = FieldChecks.class.getMethod(methodName, paramClass); } catch (NoSuchMethodException e) { return null; } return method; } /** * 複数フィールドの相関チェックを行う。 * * この検証ルールの実行には{@link MultiFieldValidator} の実装クラスが必要。<br> * 実装したクラスは <code>validation.xml</code> に設定を行う。<br> * エラーとなった場合には、エラー情報を生成し、 * 指定されたエラー情報リストに追加する。 * この検証ルールにはデフォルトのエラーメッセージがないため、 * メッセージは <code>validation.xml</code> に必ず記述すること。<br> * valueフィールドの値が、value1フィールドの値以上、 * value2フィールドの値以下であることを検証する場合、以下のように実装、 * 設定を行う。 * <h5>{@link MultiFieldValidator} の実装例</h5> * <code><pre> * public boolean validate(Object value, Object[] depends) { * int value0 = Integer.parseInt(value); * int value1 = Integer.parseInt(depends[0]); * int value2 = Integer.parseInt(depends[1]); * return (value1 <= value0 && value2 >= value0); * } * </pre></code> * <h5>validation.xmlの設定例</h5> * <code><pre> * <form name="/validateMultiField"> * <field property="value" depends="multiField"> * <msg key="errors.multiField" * name="multiField"/> * <arg key="label.value" position="0" /> * <arg key="label.value1" position="1" /> * <arg key="label.value2" position="2" /> * <var> * <var-name>fields</var-name> * <var-value>value1,value2</var-value> * </var> * <var> * <var-name>multiFieldValidator</var-name> * <var-value>sample.SampleMultiFieldValidator</var-value> * </var> * </field> * </form> * </pre></code> * <h5>メッセージリソースファイルの設定例</h5> * <code> * errors.multiField={0}は{1}から{2}の間の値を入力してください。 * </code> * * <h5>validation.xmlに設定を要する<var>要素</h5> * <table border="1"> * <tr> * <td><center><b><code>var-name</code></b></center></td> * <td><center><b><code>var-value</code></b></center></td> * <td><center><b>必須性</b></center></td> * <td><center><b>概要</b></center></td> * </tr> * <tr> * <td> fields </td> * <td>検証に必要な他のフィールド名</td> * <td>false</td> * <td>複数のフィールドを指定する場合はフィールド名をカンマ区切りで * 指定する。</td> * </tr> * <tr> * <td> multiFieldValidator </td> * <td>{@link MultiFieldValidator} 実装クラス名</td> * <td>true</td> * <td>複数フィールドの相関チェックを行う {@link MultiFieldValidator} * 実装クラス名。</td> * </tr> * </table> * * @param bean 検査対象のオブジェクト * @param va Validatorにより用意されたValidatorAction * @param field フィールドオブジェクト * @param errors エラー * @return 入力値が正しければ <code>true</code> */ public boolean validateMultiField(Object bean, ValidatorAction va, Field field, ValidationErrors errors) { // beanがnullの時、エラーログを出力し、trueを返却する。 if (bean == null) { log.error("bean is null."); return true; } // 検証対象の値を取得 Object value = null; if (bean instanceof String) { value = bean; } else { try { value = PropertyUtils.getProperty(bean, field.getProperty()); } catch (IllegalAccessException e) { log.error(e.getMessage(), e); } catch (InvocationTargetException e) { log.error(e.getMessage(), e); } catch (NoSuchMethodException e) { log.error(e.getMessage(), e); } } // 他のフィールドに依存した必須入力チェックを考慮し、 // 検証値がnullまたは空文字の場合でも複数フィールドチェックは実行する。 // MultiFieldValidator実装クラス名を取得 String multiFieldValidatorClass = field.getVarValue("multiFieldValidator"); if (multiFieldValidatorClass == null || "".equals(multiFieldValidatorClass)) { log.error("var value[multiFieldValidator] is required."); throw new IllegalArgumentException( "var value[multiFieldValidator] is required."); } MultiFieldValidator mfv = null; try { mfv = (MultiFieldValidator) ClassUtil.create( multiFieldValidatorClass); } catch (ClassLoadException e) { log.error("var value[multiFieldValidator] is invalid.", e); throw new IllegalArgumentException( "var value[multiFieldValidator] is invalid.", e); } catch (ClassCastException e) { log.error("var value[multiFieldValidator] is invalid.", e); throw new IllegalArgumentException( "var value[multiFieldValidator] is invalid.", e); } // 検証の依存フィールドの値を取得 String fields = field.getVarValue("fields"); List<Object> valueList = new ArrayList<Object>(); if (fields != null) { StringTokenizer st = new StringTokenizer(fields, ","); while (st.hasMoreTokens()) { String f = st.nextToken(); f = f.trim(); try { valueList.add(PropertyUtils.getProperty(bean, f)); } catch (IllegalAccessException e) { log.error(e.getMessage(), e); } catch (InvocationTargetException e) { log.error(e.getMessage(), e); } catch (NoSuchMethodException e) { log.error(e.getMessage(), e); } } } if (log.isDebugEnabled()) { log.debug("dependent fields:" + valueList); } Object[] values = new Object[valueList.size()]; valueList.toArray(values); boolean result = mfv.validate(value, values); if (!result) { rejectValue(errors, field, va, bean); return false; } return true; } /** * オブジェクトから検証値を取り出す。beanがNullの場合はNullを返す。 * beanがString型の場合、beanを返す。 * beanがNumber型とBoolean型とCharacter型の場合、bean.toString()を返す。 * それ以外の場合、beanと<code>Field</code>オブジェクトの値から、 * <code>ValidatorUtils</code>クラスのメソッドを利用して値を取得する。 * * @param bean 検証対象のオブジェクト。 * @param field <code>Field</code>オブジェクト。 * @return 検証値。 * @see ValidatorUtils#getValueAsString(Object, String) */ protected String extractValue(Object bean, Field field) { String value = null; if (bean == null) { return null; } else if (bean instanceof String) { value = (String) bean; } else if (bean instanceof Number || bean instanceof Boolean || bean instanceof Character) { value = bean.toString(); } else { value = ValidatorUtils.getValueAsString(bean, field.getProperty()); } return value; } /** * 入力チェックエラーが生じた場合に、エラー情報を、 * TERASOLUNA共通のエラーインタフェースに引き渡す。 * * @param errors エラー * @param va Validatorにより用意されたValidatorAction * @param field フィールドインスタンス * @param bean 入力エラーが生じたJavaBeanインスタンス */ protected void rejectValue(ValidationErrors errors, Field field, ValidatorAction va, Object bean) { errors.addError(bean, field, va); } }