jp.terasoluna.fw.web.struts.form.FieldChecksEx.java Source code

Java tutorial

Introduction

Here is the source code for jp.terasoluna.fw.web.struts.form.FieldChecksEx.java

Source

/*
 * 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.web.struts.form;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;

import jp.terasoluna.fw.beans.IndexedBeanWrapper;
import jp.terasoluna.fw.beans.JXPathIndexedBeanWrapperImpl;
import jp.terasoluna.fw.util.ClassLoadException;
import jp.terasoluna.fw.util.ClassUtil;
import jp.terasoluna.fw.util.PropertyUtil;

import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.validator.Arg;
import org.apache.commons.validator.Field;
import org.apache.commons.validator.GenericTypeValidator;
import org.apache.commons.validator.GenericValidator;
import org.apache.commons.validator.Validator;
import org.apache.commons.validator.ValidatorAction;
import org.apache.commons.validator.util.ValidatorUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.RequestUtils;
import org.apache.struts.validator.FieldChecks;
import org.apache.struts.validator.Resources;
import org.apache.struts.validator.validwhen.ValidWhen;

/**
 * <code>Validator</code> ?[NX?B
 * 
 * <p>
 * <code>Struts</code> {@link FieldChecks} g`FbNNX?B<br>
 * {@link FieldChecksEx} g?[?A?B
 * </p>
 * <table border="1">
 * <tr>
 * <td><center><b>?</b></center></td>
 * <td><center><b>NCAg`FbN</b></center></td>
 * <td><center><b>?\bh</b></center></td>
 * <td><center><b>(validation-rules.xmlL?q) ?[</b></center></td>
 * <td><center><b>Tv</b></center></td>
 * </tr>
 * <tr>
 * <td>p?`FbN</td>
 * <td><center>?</center></td>
 * <td>{@link #validateAlphaNumericString(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateAlphaNumericString()}</td>
 * <td><code>alphaNumericString</code></td>
 * <td>tB?[hlpp??\?`FbN?B</td>
 * </tr>
 * <tr>
 * <td>p?`FbN</td>
 * <td><center>?</center></td>
 * <td>{@link #validateCapAlphaNumericString(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest)
 * validateCapAlphaNumericString()}</td>
 * <td><code>capAlphaNumericString</code></td>
 * <td>lpp??\?`FbN?B </td>
 * </tr>
 * <tr>
 * <td>tB?[h?l`FbN</td>
 * <td><center>?</center></td>
 * <td>{@link #validateNumber(Object, ValidatorAction, Field, ActionMessages,
 * Validator, HttpServletRequest) validateNumber()}</td>
 * <td><code>number</code></td>
 * <td>tB?[hl?l`FbN?B</td>
 * </tr>
 * <tr>
 * <td>pJi`FbN</td>
 * <td><center>?</center></td>
 * <td>{@link #validateHankakuKanaString(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateHankakuKanaString()}</td>
 * <td><code>hankakuKanaString</code></td>
 * <td>tB?[hlpJi?\?`FbN?B</td>
 * </tr>
 * <tr>
 * <td>p`FbN</td>
 * <td><center>?</center></td>
 * <td>{@link #validateHankakuString(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateHankakuString()}</td>
 * <td><code>hankakuString</code></td>
 * <td>tB?[hlp?\?`FbN?B</td>
 * </tr>
 * <tr>
 * <td>Sp`FbN</td>
 * <td><center>?</center></td>
 * <td>{@link #validateZenkakuString(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateZenkakuString()}</td>
 * <td><code>zenkakuString</code></td>
 * <td>tB?[hlSp?\?`FbN?B</td>
 * </tr>
 * <tr>
 * <td>SpJi`FbN</td>
 * <td><center>?</center></td>
 * <td>{@link #validateZenkakuKanaString(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateZenkakuKanaString()}</td>
 * <td><code>zenkakuKanaString</code></td>
 * <td>tB?[hlSpJi?\?`FbN?B</td>
 * </tr>
 * <tr>
 * <td>~`FbN</td>
 * <td><center>?~</center></td>
 * <td>{@link #validateProhibited(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateProhibited()}</td>
 * <td><code>prohibited</code></td>
 * <td>tB?[hl~`FbN?B</td>
 * </tr>
 * <tr>
 * <td>v`FbN</td>
 * <td><center>?</center></td>
 * <td>{@link #validateStringLength(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateStringLength()}</td>
 * <td><code>stringLength</code></td>
 * <td>tB?[hlwv`FbN?B</td>
 * </tr>
 * <tr>
 * <td>?`FbN</td>
 * <td><center>?</center></td>
 * <td>{@link #validateNumericString(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateNumericString()}</td>
 * <td><code>numericString</code></td>
 * <td>tB?[hl??\?`FbN?B</td>
 * </tr>
 * <tr>
 * <td>oCg`FbN</td>
 * <td><center>?~</center></td>
 * <td>{@link #validateByteLength(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateByteLength()}</td>
 * <td><code>byteLength</code></td>
 * <td>tB?[hloCgwv`FbN?B</td>
 * </tr>
 * <tr>
 * <td>oCg`FbN</td>
 * <td><center>?~</center></td>
 * <td>{@link #validateByteRange(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateByteRange()}</td>
 * <td><code>byteRange</code></td>
 * <td>tB?[hloCgw`FbN?B</td>
 * </tr>
 * <tr>
 * <td>t`FbN</td>
 * <td><center>?</center></td>
 * <td>{@link #validateDateRange(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateDateRange()}</td>
 * <td><code>dateRange</code></td>
 * <td>tB?[hltw`FbN?B</td>
 * </tr>
 * <tr>
 * <td>?tB?[h`FbN</td>
 * <td><center>?~</center></td>
 * <td>{@link #validateMultiField(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateMultiField()}</td>
 * <td><code>multiField</code></td>
 * <td>?tB?[h`FbN?B</td>
 * </tr>
 * <tr>
 * <td>z?ERNV^tB?[hSvf`FbN</td>
 * <td><center>?~</center></td>
 * <td>{@link #validateArraysIndex(Object, ValidatorAction, Field,
 * ActionMessages, Validator, HttpServletRequest) validateArraysIndex()}</td>
 * <td>(<code>validation.xml</code> <code>&lt;depend&gt;</code>vf)</td>
 * <td>depends?w`FbNz?ERNV^tB?[hl Sl`FbN?s?B</td>
 * </tr>
 * </ul>
 * </table>
 * <p>
 * tB?[h`FbN???Ae?\bh?Q??B<br>
 * gValidatorp?AANV ?eL?q`t@C( <code>validation.xml</code> )
 * ??Kv?B
 * </p>
 * <p>K?{`FbNO`FbN?[?A
 * pXy?[Xln???AG?[?B
 * G?[??K?{`FbNg??A
 * pXy?[X`FbN?B</p>
 * 
 * <h5>PtB?[h?</h5>
 * <p>
 * <code>&lt;formset&gt;</code>^O <code>&lt;form&gt;</code> vf
 * <code>name</code> ??A <code>struts-config.xml</code>`
 * ANVpXL?q?B<br>
 * L?q???AYANVpX???s?B <code>&lt;field&gt;</code>vf
 * <code>property</code> ??A ?tB?[h?A<code>depends</code>?
 * <code>validation-rules.xml</code>` ??[L?q?B
 * tH?[???s???iK?{?A??j?A J}?L?q?B<br>
 * ?A?oG?[?bZ?[WPtB?[h?A P?B ?iK?{?A?`FbN???AP
 * G?[?o?j
 * </p>
 * <h5>validation.xmlL?q?iPtB?[h??j</h5>
 * <code><pre>
 *  &lt;formset&gt;
 *    ?E?E?E
 *    &lt;!-- PtB?[h? --&gt;
 *    &lt;form name=&quot;/logon&quot;&gt;
 *      &lt;field property=&quot;companyId&quot;
 *          depends=&quot;required,alphaNumericString,maxlength&quot;&gt;
 *        &lt;arg0 key=&quot;logon.companyId&quot;/&gt;
 *        &lt;arg1 key=&quot;${var:maxlength}&quot; resource=&quot;false&quot;/&gt;
 *        &lt;var&gt;
 *          &lt;var-name&gt;maxlength&lt;/var-name&gt;
 *          &lt;var-value&gt;10&lt;/var-value&gt;
 *        &lt;/var&gt;
 *      &lt;/field&gt;
 *    &lt;/form&gt;
 *    ?E?E?E
 *  &lt;/formset&gt;
 * </pre></code>
 * <h5>z?ERNV^?</h5>
 * <p>
 * z?ERNV^??AL_g?B
 * <ul>
 * <li>?tB?[hz?ERNVvf?ArG?[ p?vf??s</li>
 * <li>evfCfbNX?G?[?bZ?[Wf</li>
 * </ul>
 * {IPtB?[h?l<code>validation.xml</code> <code>&lt;form&gt;</code>
 * vf???A z?ERNV^??s?AL?Kv?B
 * <ol>
 * <li>z?ERNV^\?A<b>K <code>property</code> ?tH?[tB?[hw</b>?Bv?peB
 * JXPathIndexedBeanWrapperImpldl?]?AlXgv?peB w\?B</li>
 * <li><code>&lt;depends&gt;</code>w?[?A
 * <code>validation-rules.xml</code>  <code>Array</code> ?[p?B</li>
 * <li>?tH?[FormExC^tF?[X Kv?B</li>
 * </li>
 * </ol>
 * z?ERNV^??[?B
 * <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>byteLengthArray</code></li>
 * <li><code>byteRangeArray</code></li>
 * </ul>
 * </p>
 * <h5>validation.xmlL?q?iz?ERNV^\??j</h5>
 * <code><pre>
 *  &lt;formset&gt;
 *    ?E?E?E
 *    &lt;!-- z?ERNV^\?mF --&gt;
 *    &lt;form name=&quot;/isValid&quot;&gt;
 *      &lt;field property=&quot;codeArray&quot;
 *          depends=&quot;requiredArray,alphaNumericStringArray&quot;&gt;
 *        &lt;arg0 &lt;b&gt;key=&quot;##INDEX&quot; resource=&quot;false&quot;&lt;/b&gt;/&gt;
 *        &lt;arg1 key=&quot;sampleValidate.codeArray&quot;/&gt;
 *      &lt;/field&gt;
 *    &lt;/form&gt;
 *    ?E?E?E
 *  &lt;/formset&gt;
 * </pre></code>
 * <p>
 * z?ERNV^CfbNX?G?[?bZ?[W ??A<code>&lt;arg0?`3&gt;</code>vf
 * <code>key</code> <code>&quot;##INDEX&quot;</code> w?A<code>&lt;resource&gt;</code>
 * vf <code>&quot;false&quot;</code> ?B<br>
 * PtB?[h?l?A<code>&lt;depends&gt;</code>
 * ???s??J}????[w?B<br>
 * <code>Validator</code> t?[??[NptH?[?A <code>
 * {@link DynaValidatorActionFormEx}
 * </code>?A
 * <code>
 * {@link ValidatorActionFormEx}
 * </code> Q??B
 * </p>
 * 
 * @see jp.terasoluna.fw.web.struts.form.FormEx
 * @see jp.terasoluna.fw.web.struts.form.DynaValidatorActionFormEx
 * @see jp.terasoluna.fw.web.struts.form.ValidatorActionFormEx
 * @see jp.terasoluna.fw.beans.JXPathIndexedBeanWrapperImpl
 * 
 */
public class FieldChecksEx extends FieldChecks {

    /**
     * VAo?[WID
     */
    private static final long serialVersionUID = -5669122584668175380L;

    /**
     * ?ONX?B
     */
    private static Log log = LogFactory.getLog(FieldChecksEx.class);

    /**
     * zCfbNX^tB?[hIndexl?B
     */
    public static final String INDEX = "##INDEX";

    /**
     * pJi?B<code>ApplicationResources</code> t@C`?B
     */
    protected static String hankakuKanaList = "";

/**
 * SpJi?B<code>ApplicationResources</code> t@C`?B
 */
protected static String zenkakuKanaList = "ACEGI@BDFHJLNPRKMOQSTVXZ\"
        + "UWY[]^`ceg_adfhijklmnqtwz" + "orux{psvy|}~??"
        + "??b?[";

    /**
     * <code>ApplicationResources</code> t@C`pe?[uL?[?B
     */
    protected static final String HANKAKU_KANA_LIST_KEY = "validation.hankaku.kana.list";

    /**
     * <code>ApplicationResources</code> t@C`Spe?[uL?[?B
     */
    protected static final String ZENKAKU_KANA_LIST_KEY = "validation.zenkaku.kana.list";

    /**
     * UNICODER?[h'\u0000''\u00ff'? Sp?B
     */
    protected static final String ZENKAKU_BEGIN_U00_LIST = "?_????N???}?L??~?";

    static {
        String value = null;
        // pJie?[u
        value = PropertyUtil.getProperty(HANKAKU_KANA_LIST_KEY);
        if (value != null) {
            hankakuKanaList = value;
        }

        // SpJie?[u
        value = PropertyUtil.getProperty(ZENKAKU_KANA_LIST_KEY);
        if (value != null) {
            zenkakuKanaList = value;
        }
    }

    /**
     * wpJi`FbN?B
     * 
     * @param c
     *            
     * @return pJi <code>true</code>
     */
    protected static boolean isHankakuKana(char c) {
        return hankakuKanaList.indexOf(c) >= 0;
    }

    /**
     * wp`FbN?B
     * 
     * @param c
     *            
     * @return p <code>true</code>
     */
    protected static boolean isHankaku(char c) {
        return (c <= '\u00ff' && ZENKAKU_BEGIN_U00_LIST.indexOf(c) < 0) || isHankakuKana(c);
    }

    /**
     * wSp`FbN?B
     * 
     * @param c
     *            
     * @return Sp <code>true</code>
     */
    protected static boolean isZenkaku(char c) {
        return !isHankaku(c);
    }

    /**
     * wSpJi`FbN?B
     * 
     * @param c
     *            
     * @return SpJi <code>true</code>
     */
    protected static boolean isZenkakuKana(char c) {
        return zenkakuKanaList.indexOf(c) >= 0;
    }

    /**
     * wtB?[hp?`FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?B G?[?bZ?[WtH?[}bg?A<code>validation-rules.xml</code>
     * L?q?B
     * </p>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            StrutspValidatorAction
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ActionMessages ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateAlphaNumericString(Object bean, ValidatorAction va, Field field,
            ActionMessages errors, Validator validator, HttpServletRequest request) {
        // tB?[hN??[??
        Field fieldClone = (Field) field.clone();
        fieldClone.addVar("mask", "^[0-9a-zA-Z]*$", "false");
        // p?l`FbN?s
        return validateMask(bean, va, fieldClone, errors, validator, request);
    }

    /**
     * wtB?[hp?`FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?B G?[?bZ?[WtH?[}bg?A<code>validation-rules.xml</code>
     * L?q?B
     * </p>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            StrutspValidatorAction
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ActionMessages ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateCapAlphaNumericString(Object bean, ValidatorAction va, Field field,
            ActionMessages errors, Validator validator, HttpServletRequest request) {

        // tB?[hN??[??
        Field fieldClone = (Field) field.clone();
        fieldClone.addVar("mask", "^[0-9A-Z]*$", "false");
        // p?l`FbN?s
        return validateMask(bean, va, fieldClone, errors, validator, request);
    }

    /**
     * wtB?[h?l`FbN?B
     * 
     * ?Ap?A<code>BigDecimal</code> ^??
     * ??s\G?[pActionMessage???A<code>false</code> p?B
     * 
     * ???w???A?mF?s?B <code>validation.xml</code> 
     * <code>isAccordedInteger()</code>  <code>"true"</code> w??
     * ???`FbN?s?B `FbN???AG?[pActionMessage???Afalsep?B
     * 
     * ????w???A?mF?s?B
     * validation.xmlisAccordedScale"true"?? ???`FbN?s?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?B G?[?bZ?[WtH?[}bg?A<code>validation-rules.xml</code>
     * L?q?B<br>
     * L?A??3?A??2?l??B
     * </p>
     * 
     * <h5>validation.xmlL?q</h5>
     * <code><pre>
     * &lt;form name=&quot;/sample&quot;&gt;
     *  ?E?E?E
     *  &lt;field property=&quot;escape&quot;
     *      depends=&quot;number&quot;&gt;
     *    &lt;arg0 key=&quot;sample.escape&quot;/&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;integerLength&lt;/var-name&gt;
     *      &lt;var-value&gt;3&lt;/var-value&gt;
     *    &lt;/var&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;scale&lt;/var-name&gt;
     *      &lt;var-value&gt;2&lt;/var-value&gt;
     *    &lt;/var&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;isAccordedInteger&lt;/var-name&gt;
     *      &lt;var-value&gt;true&lt;/var-value&gt;
     *    &lt;/var&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;isAccordedScale&lt;/var-name&gt;
     *      &lt;var-value&gt;true&lt;/var-value&gt;
     *    &lt;/var&gt;
     *  &lt;/field&gt;
     *  ?E?E?E
     * &lt;/form&gt;
     * </pre></code>
     * <h5>validation.xml?v&lt;var&gt;vf</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>K?{?</b></center></td>
     * <td><center><b>Tv</b></center></td>
     * </tr>
     * <tr>
     * <td> <code>integerLength</code> </td>
     * <td> ??? </td>
     * <td> <code>false</code> </td>
     * <td>?????A<code>isAccordedInteger</code>w
     * ?Aw???s?B??A?l ??A??s?B</td>
     * </tr>
     * <tr>
     * <td> <code>scale</code> </td>
     * <td> ??? </td>
     * <td> <code>false</code> </td>
     * <td>??l???A<code>isAccordedScale</code>w
     * ?Aw???s?B??A?l ??A??s?B</td>
     * </tr>
     * <tr>
     * <td> <code>isAccordedInteger</code> </td>
     * <td> ???v`FbN </td>
     * <td> <code>false</code> </td>
     * <td> <code>true</code>w?A???v`FbN ?s?B??A<code>true</code>O?
     * ?`FbN?B</td>
     * </tr>
     * <tr>
     * <td> <code>isAccordedScale</code> </td>
     * <td> ???v`FbN </td>
     * <td> <code>false</code> </td>
     * <td> <code>true</code>w?A???v`FbN ?s?B??A<code>true</code>O?
     * ?`FbN?B</td>
     * </tr>
     * </table>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            StrutspValidatorAction
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ActionMessages ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateNumber(Object bean, ValidatorAction va, Field field, ActionMessages errors,
            Validator validator, HttpServletRequest request) {

        // beannull?AG?[?O?o?Atruep?B
        if (bean == null) {
            log.error("bean is null.");
            return true;
        }
        // ???
        String integerLength = field.getVarValue("integerLength");
        // ???
        String scaleStr = field.getVarValue("scale");
        // ???v`FbN
        String isAccordedInteger = field.getVarValue("isAccordedInteger");
        // ???v`FbN
        String isAccordedScale = field.getVarValue("isAccordedScale");

        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        }
        // ?lnull?Atruep
        if (GenericValidator.isBlankOrNull(value)) {
            return true;
        }
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (!isHankaku(chars[i])) {
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
        }
        // ???w???A??`FbN?s
        if (GenericValidator.isInt(integerLength)) {
            try {
                BigDecimal bd = new BigDecimal(value);
                // ???l?o
                BigInteger bi = bd.toBigInteger().abs();
                // ???
                int length = bi.toString().length();
                // validation.xmlw?
                int checkLength = Integer.valueOf(integerLength).intValue();
                // ?I?[o?Afalsep
                if (length > checkLength) {
                    errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                    return false;
                }
                // vw
                if (isAccordedInteger != null && "true".equals(isAccordedInteger)) {
                    // ?sv?Afalsep
                    if (length != checkLength) {
                        errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                        return false;
                    }
                }
            } catch (NumberFormatException nfe) {
                // ?l^?Afalsep
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
        }

        // ???w???A??`FbN?s
        if (GenericValidator.isInt(scaleStr)) {
            int scale = 0;
            int checkScale = 0;
            try {
                BigDecimal bd = new BigDecimal(value);
                scale = bd.scale();
                // validation.xmlw?
                checkScale = Integer.valueOf(scaleStr).intValue();
            } catch (NumberFormatException e) {
                // ?l^?Afalsep
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
            // ?I?[o?Afalsep
            if (scale > checkScale) {
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
            // vw
            if (isAccordedScale != null && "true".equals(isAccordedScale)) {
                // ?sv?Afalsep
                if (scale != checkScale) {
                    errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * wtB?[hpJi`FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?B G?[?bZ?[WtH?[}bg?A<code>validation-rules.xml</code>
     * L?q?B
     * </p>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            <code>Validator</code>p <code>ValidatorAction</code>
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ActionMessages ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateHankakuKanaString(Object bean, ValidatorAction va, Field field,
            ActionMessages errors, Validator validator, HttpServletRequest request) {

        // beannull?AG?[?O?o?Atruep?B
        if (bean == null) {
            log.error("bean is null.");
            return true;
        }
        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        }
        // ?lnull?Atruep
        if (GenericValidator.isBlankOrNull(value)) {
            return true;
        }
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (!isHankakuKana(chars[i])) {
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
        }
        return true;
    }

    /**
     * wtB?[hp`FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?BG?[?bZ?[WtH?[}bg?A
     * <code>validation-rules.xml</code>L?q?B
     * </p>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            <code>Validator</code>p <code>ValidatorAction</code>
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateHankakuString(Object bean, ValidatorAction va, Field field, ActionMessages errors,
            Validator validator, HttpServletRequest request) {

        // beannull?AG?[?O?o?Atruep?B
        if (bean == null) {
            log.error("bean is null.");
            return true;
        }
        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        }
        // ?lnull?Atruep
        if (GenericValidator.isBlankOrNull(value)) {
            return true;
        }
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (!isHankaku(chars[i])) {
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
        }
        return true;
    }

    /**
     * wtB?[hSp`FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?BG?[?bZ?[WtH?[}bg?A
     * <code>validation-rules.xml</code>L?q?B
     * </p>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            <code>Validator</code>p <code>ValidatorAction</code>
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateZenkakuString(Object bean, ValidatorAction va, Field field, ActionMessages errors,
            Validator validator, HttpServletRequest request) {

        // beannull?AG?[?O?o?Atruep?B
        if (bean == null) {
            log.error("bean is null.");
            return true;
        }
        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        }
        // ?lnull?Atruep
        if (GenericValidator.isBlankOrNull(value)) {
            return true;
        }
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (!isZenkaku(chars[i])) {
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
        }
        return true;
    }

    /**
     * wtB?[hSpJ^Ji`FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?BG?[?bZ?[WtH?[}bg?A
     * <code>validation-rules.xml</code>L?q?B
     * </p>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            <code>Validator</code>p <code>ValidatorAction</code>
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateZenkakuKanaString(Object bean, ValidatorAction va, Field field,
            ActionMessages errors, Validator validator, HttpServletRequest request) {

        // beannull?AG?[?O?o?Atruep?B
        if (bean == null) {
            log.error("bean is null.");
            return true;
        }
        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        }
        // ?lnull?Atruep
        if (GenericValidator.isBlankOrNull(value)) {
            return true;
        }
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (!isZenkakuKana(chars[i])) {
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
        }
        return true;
    }

    /**
     * wtB?[h~? `FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?B G?[?bZ?[WtH?[}bg?A
     * <code>validation-rules.xml</code>L?q?B<br>
     * ?A~`FbN??B
     * </p>
     * <h5>validation.xmlL?q</h5>
     * <code><pre>
     * &lt;form name=&quot;/sample&quot;&gt;
     *  ?E?E?E
     *  &lt;field property=&quot;escape&quot;
     *      depends=&quot;prohibited&quot;&gt;
     *    &lt;arg0 key=&quot;sample.escape&quot;/&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;chars&lt;/var-name&gt;
     *      &lt;var-value&gt;!&quot;#$%&amp;'()&lt;/var-value&gt;
     *    &lt;/var&gt;
     *  &lt;/field&gt;
     *  ?E?E?E
     * &lt;/form&gt;
     * </pre></code>
     * <h5>validation.xml?v&lt;var&gt;vf</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>K?{?</b></center></td>
     * <td><center><b>Tv</b></center></td>
     * </tr>
     * <tr>
     * <td> chars </td>
     * <td>~LN^</td>
     * <td>false</td>
     * <td>?A~LN^?A <code>false</code>p?B?<code>true</code></td>
     * </tr>
     * </table>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            <code>Validator</code>p <code>ValidatorAction</code>
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateProhibited(Object bean, ValidatorAction va, Field field, ActionMessages errors,
            Validator validator, HttpServletRequest request) {

        // beannull?AG?[?O?o?Atruep?B
        if (bean == null) {
            log.error("bean is null.");
            return true;
        }

        // ~
        String prohibitedStr = field.getVarValue("chars");
        if (prohibitedStr == null || "".equals(prohibitedStr)) {
            // ~null?Atruep
            return true;
        }

        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        }

        // ?lnull?Atruep
        if (StringUtils.isEmpty(value)) {
            return true;
        }

        char[] chars = value.toCharArray();

        // ~????A`FbN?s
        for (int i = 0; i < chars.length; i++) {
            if (prohibitedStr.indexOf(chars[i]) >= 0) {
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
        }
        return true;
    }

    /**
     * wtB?[h? `FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?B G?[?bZ?[WtH?[}bg?A
     * <code>validation-rules.xml</code>L?q?B
     * </p>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            <code>Validator</code>p <code>ValidatorAction</code>
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateNumericString(Object bean, ValidatorAction va, Field field, ActionMessages errors,
            Validator validator, HttpServletRequest request) {
        // tB?[hN??[??
        Field fieldClone = (Field) field.clone();
        fieldClone.addVar("mask", "^[0-9]*$", "false");
        // ?l`FbN?s
        return validateMask(bean, va, fieldClone, errors, validator, request);
    }

    /**
     * wtB?[hv`FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?B G?[?bZ?[WtH?[}bg?A
     * <code>validation-rules.xml</code>L?q?B<br>
     * ?A5<code>true</code>p ???B
     * </p>
     * <h5>validation.xmlL?q</h5>
     * <code><pre>
     * &lt;form name=&quot;/sample&quot;&gt;
     *  ?E?E?E
     *  &lt;field property=&quot;escape&quot;
     *      depends=&quot;stringLength&quot;&gt;
     *    &lt;arg0 key=&quot;sample.escape&quot;/&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;length&lt;/var-name&gt;
     *      &lt;var-value&gt;5&lt;/var-value&gt;
     *    &lt;/var&gt;
     *  &lt;/field&gt;
     *  ?E?E?E
     * &lt;/form&gt;
     * </pre></code>
     * <h5>validation.xml?v&lt;var&gt;vf</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>K?{?</b></center></td>
     * <td><center><b>Tv</b></center></td>
     * </tr>
     * <tr>
     * <td> stringLength </td>
     * <td>?</td>
     * <td>false</td>
     * <td>w? <code>true</code> ?<code>true</code>p?B</td>
     * </tr>
     * </table>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            ValidatorpValidatorAction
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateStringLength(Object bean, ValidatorAction va, Field field, ActionMessages errors,
            Validator validator, HttpServletRequest request) {

        // beannull?AG?[?O?o?Atruep?B
        if (bean == null) {
            log.error("bean is null.");
            return true;
        }

        // 
        String lengthStr = field.getVarValue("stringLength");
        // w??A`FbN?s
        if (lengthStr == null || "".equals(lengthStr)) {
            return true;
        }
        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        }
        // ?lnull?Atruep
        if (GenericValidator.isBlankOrNull(value)) {
            return true;
        }

        int checkLength = 0;
        try {
            checkLength = Integer.valueOf(lengthStr).intValue();
        } catch (NumberFormatException e) {
            // wints\??
            log.error("stringLength is not numeric(integer).", e);
            return true;
        }
        // length?Afalsep
        if (value.length() != checkLength) {
            errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
            return false;
        }

        return true;
    }

    /**
     * wtB?[hoCgv`FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?B G?[?bZ?[WtH?[}bg?A
     * <code>validation-rules.xml</code>L?q?B<br>
     * ?AoCg5<code>true</code>p ???B
     * </p>
     * <h5>validation.xmlL?q</h5>
     * <code><pre>
     * &lt;form name=&quot;/sample&quot;&gt;
     *  ?E?E?E
     *  &lt;field property=&quot;escape&quot;
     *      depends=&quot;byteLength&quot;&gt;
     *    &lt;arg0 key=&quot;sample.escape&quot;/&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;byteLength&lt;/var-name&gt;
     *      &lt;var-value&gt;5&lt;/var-value&gt;
     *    &lt;/var&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;encoding&lt;/var-name&gt;
     *      &lt;var-value&gt;Windows-31J&lt;/var-value&gt;
     *    &lt;/var&gt;
     *  &lt;/field&gt;
     *  ?E?E?E
     * &lt;/form&gt;
     * </pre></code>
     * <h5>validation.xml?v&lt;var&gt;vf</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>K?{?</b></center></td>
     * <td><center><b>Tv</b></center></td>
     * </tr>
     * <tr>
     * <td> byteLength </td>
     * <td>oCg?</td>
     * <td>false</td>
     * <td>oCg?oCg?B</td>
     * </tr>
     * <tr>
     * <td> encoding </td>
     * <td>GR?[fBO</td>
     * <td>false</td>
     * <td>oCg?gpGR?[fBO?B ???VMftHgGR?[fBOgp?B</td>
     * </tr>
     * </table>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            ValidatorpValidatorAction
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateByteLength(Object bean, ValidatorAction va, Field field, ActionMessages errors,
            Validator validator, HttpServletRequest request) {

        // beannull?AG?[?O?o?Atruep?B
        if (bean == null) {
            log.error("bean is null.");
            return true;
        }

        // l
        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        }
        // ?lnull?Atruep
        if (GenericValidator.isBlankOrNull(value)) {
            return true;
        }

        // oCg
        String lengthStr = field.getVarValue("byteLength");
        // oCgw??A`FbN?s
        if (lengthStr == null || "".equals(lengthStr)) {
            if (log.isInfoEnabled()) {
                log.info("length is not specified.");
            }
            return true;
        }
        int checkLength = 0;
        try {
            checkLength = Integer.valueOf(lengthStr).intValue();
        } catch (NumberFormatException e) {
            // wints\??
            log.error("byteLength is not numeric(integer).", e);
            return true;
        }

        // GR?[fBO
        String encoding = field.getVarValue("encoding");

        int bytesLength = getByteLength(value, encoding);

        // oCg?length?Afalsep
        if (bytesLength != checkLength) {
            errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
            return false;
        }

        return true;
    }

    /**
     * wtB?[hoCg w`FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?B G?[?bZ?[WtH?[}bg?A
     * <code>validation-rules.xml</code>L?q?B<br>
     * ?AoCg5??A10 <code>true</code> p???B
     * </p>
     * <h5>validation.xmlL?q</h5>
     * <code><pre>
     * &lt;form name=&quot;/sample&quot;&gt;
     *  ?E?E?E
     *  &lt;field property=&quot;escape&quot;
     *      depends=&quot;byteRange&quot;&gt;
     *    &lt;arg0 key=&quot;sample.escape&quot;/&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;maxByte&lt;/var-name&gt;
     *      &lt;var-value&gt;10&lt;/var-value&gt;
     *    &lt;/var&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;minByte&lt;/var-name&gt;
     *      &lt;var-value&gt;5&lt;/var-value&gt;
     *    &lt;/var&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;encoding&lt;/var-name&gt;
     *      &lt;var-value&gt;Windows-31J&lt;/var-value&gt;
     *    &lt;/var&gt;
     *  &lt;/field&gt;
     *  ?E?E?E
     * &lt;/form&gt;
     * </pre></code>
     * <h5>validation.xml?v&lt;var&gt;vf</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>K?{?</b></center></td>
     * <td><center><b>Tv</b></center></td>
     * </tr>
     * <tr>
     * <td> maxByte </td>
     * <td>?oCg?</td>
     * <td>false</td>
     * <td>oCg??oCg?B ???int^?l?B</td>
     * </tr>
     * <tr>
     * <td> minByte </td>
     * <td>?oCg?</td>
     * <td>false</td>
     * <td>oCg???oCg?B ???0?B</td>
     * </tr>
     * <tr>
     * <td> encoding </td>
     * <td>GR?[fBO</td>
     * <td>false</td>
     * <td>oCg?gpGR?[fBO?B ???VMftHgGR?[fBOgp?B</td>
     * </tr>
     * </table>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            ValidatorpValidatorAction
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateByteRange(Object bean, ValidatorAction va, Field field, ActionMessages errors,
            Validator validator, HttpServletRequest request) {

        // beannull?AG?[?O?o?Atruep?B
        if (bean == null) {
            log.error("bean is null.");
            return true;
        }

        // l
        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        }

        // ?lnull?Atruep
        if (GenericValidator.isBlankOrNull(value)) {
            return true;
        }

        // GR?[fBO
        String encoding = field.getVarValue("encoding");

        // oCg
        int bytesLength = getByteLength(value, encoding);

        int min = 0;
        String minStr = field.getVarValue("minByte");
        if (!GenericValidator.isBlankOrNull(minStr)) {
            try {
                min = Integer.parseInt(minStr);
            } catch (NumberFormatException e) {
                log.error("", e);
            }
        }

        int max = Integer.MAX_VALUE;
        String maxStr = field.getVarValue("maxByte");
        if (!GenericValidator.isBlankOrNull(maxStr)) {
            try {
                max = Integer.parseInt(maxStr);
            } catch (NumberFormatException e) {
                log.error("", e);
            }
        }

        if (!GenericValidator.isInRange(bytesLength, min, max)) {
            errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
            return false;
        }
        return true;
    }

    /**
     * tw`FbN?B
     * 
     * <p>
     * G?[???AG?[????A wG?[?Xg?B G?[?bZ?[WtH?[}bg?A
     * <code>validation-rules.xml</code>L?q?B<br>
     * ?At2000/01/012010/12/31 ???B
     * </p>
     * <h5>validation.xmlL?q</h5>
     * <code><pre>
     * &lt;form name=&quot;/sample&quot;&gt;
     *  ?E?E?E
     *  &lt;field property=&quot;date&quot;
     *      depends=&quot;dateRange&quot;&gt;
     *    &lt;arg key=&quot;label.date&quot; position=&quot;0&quot;/&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;startDate&lt;/var-name&gt;
     *      &lt;var-value&gt;2000/01/01&lt;/var-value&gt;
     *    &lt;/var&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;endDate&lt;/var-name&gt;
     *      &lt;var-value&gt;2010/12/31&lt;/var-value&gt;
     *    &lt;/var&gt;
     *    &lt;var&gt;
     *      &lt;var-name&gt;datePattern&lt;/var-name&gt;
     *      &lt;var-value&gt;yyyy/MM/dd&lt;/var-value&gt;
     *    &lt;/var&gt;
     *  &lt;/field&gt;
     *  ?E?E?E
     * &lt;/form&gt;
     * </pre></code>
     * <h5>validation.xml?v&lt;var&gt;vf</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>K?{?</b></center></td>
     * <td><center><b>Tv</b></center></td>
     * </tr>
     * <tr>
     * <td> startDate </td>
     * <td>Jnt</td>
     * <td>false</td>
     * <td>tJnlt?B
     * datePatterndatePatternStrictwttH?[}bgv?B</td>
     * </tr>
     * <tr>
     * <td> endDate </td>
     * <td>?It</td>
     * <td>false</td>
     * <td>t?Ilt?B
     * datePatterndatePatternStrictwttH?[}bgv?B</td>
     * </tr>
     * <tr>
     * <td> datePattern </td>
     * <td>tp^?[</td>
     * <td>false</td>
     * <td>tp^?[?BDate^tH?[}bg?[?]?B</td>
     * </tr>
     * <tr>
     * <td> datePatternStrict </td>
     * <td>tp^?[?BDate^tH?[}bg?[?]?B</td>
     * <td>false</td>
     * <td>tp^?[`FbN?s?B tp^?[yyyy/MM/dd???A2001/1/1G?[?B
     * datePatternw???AdatePatternwtH?[}bg D??B</td>
     * </tr>
     * </table>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            ValidatorpValidatorAction
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateDateRange(Object bean, ValidatorAction va, Field field, ActionMessages errors,
            Validator validator, HttpServletRequest request) {

        // beannull?AG?[?O?o?Atruep?B
        if (bean == null) {
            log.error("bean is null.");
            return true;
        }

        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        }
        // ?lnull?Atruep
        if (GenericValidator.isBlankOrNull(value)) {
            return true;
        }

        // t?`FbN
        String datePattern = field.getVarValue("datePattern");
        String datePatternStrict = field.getVarValue("datePatternStrict");
        Locale locale = RequestUtils.getUserLocale(request, null);
        Date result = null;
        try {
            if (datePattern != null && datePattern.length() > 0) {
                result = GenericTypeValidator.formatDate(value, datePattern, false);
            } else if (datePatternStrict != null && datePatternStrict.length() > 0) {
                result = GenericTypeValidator.formatDate(value, datePatternStrict, true);
            } else {
                result = GenericTypeValidator.formatDate(value, locale);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        if (result == null) {
            errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
            return false;
        }

        // t`FbN
        // Jn
        String startDateStr = field.getVarValue("startDate");
        // ?I
        String endDateStr = field.getVarValue("endDate");

        if (startDateStr == null && endDateStr == null) {
            // tw????
            return true;
        }

        // Jnt?~`FbN
        if (startDateStr != null && startDateStr.length() > 0) {
            Date startDate = null;

            if (datePattern != null && datePattern.length() > 0) {
                startDate = GenericTypeValidator.formatDate(startDateStr, datePattern, false);
            } else if (datePatternStrict != null && datePatternStrict.length() > 0) {
                startDate = GenericTypeValidator.formatDate(startDateStr, datePatternStrict, true);
            } else {
                startDate = GenericTypeValidator.formatDate(startDateStr, locale);
            }

            if (startDate == null) {
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
            if (result.before(startDate)) {
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
        }

        // ?ItO`FbN
        if (endDateStr != null && endDateStr.length() > 0) {
            Date endDate = null;

            if (datePattern != null && datePattern.length() > 0) {
                endDate = GenericTypeValidator.formatDate(endDateStr, datePattern, false);
            } else if (datePatternStrict != null && datePatternStrict.length() > 0) {
                endDate = GenericTypeValidator.formatDate(endDateStr, datePatternStrict, true);
            } else {
                endDate = GenericTypeValidator.formatDate(endDateStr, locale);
            }

            if (endDate == null) {
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
            if (result.after(endDate)) {
                errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
                return false;
            }
        }

        return true;
    }

    /**
     * ?tB?[h`FbN?s?B
     * 
     * ??[?s{@link MultiFieldValidator} NX Kv?BNX
     * <code>validation.xml</code> ??s?B<br>
     * G?[???AG?[????A wG?[?Xg?B ??[ftHgG?[?bZ?[W?A
     * ?bZ?[W <code>validation.xml</code> KL?q?B<br>
     * ANVtH?[valuetB?[hl?Avalue1tB?[hl??A
     * value2tB?[hl????A?A ??s?B
     * <h5>{@link MultiFieldValidator} </h5>
     * <code><pre>
     * public boolean validate(String value, String[] depends) {
     *  int value0 = Integer.parseInt(value);
     *  int value1 = Integer.parseInt(depends[0]);
     *  int value2 = Integer.parseInt(depends[1]);
     *  return (value1 &lt;= value0 &amp;&amp; value2 &gt;= value0);
     * }
     * </pre></code>
     * <h5>validation.xml?</h5>
     * <code><pre>
     * &lt;form name=&quot;/validateMultiField&quot;&gt;
     *   &lt;field property=&quot;value&quot; depends=&quot;multiField&quot;&gt;
     *     &lt;msg key=&quot;errors.multiField&quot;
     *             name=&quot;multiField&quot;/&gt;
     *     &lt;arg key=&quot;label.value&quot; position=&quot;0&quot; /&gt;
     *     &lt;arg key=&quot;label.value1&quot; position=&quot;1&quot; /&gt;
     *     &lt;arg key=&quot;label.value2&quot; position=&quot;2&quot; /&gt;
     *     &lt;var&gt;
     *       &lt;var-name&gt;fields&lt;/var-name&gt;
     *       &lt;var-value&gt;value1,value2&lt;/var-value&gt;
     *     &lt;/var&gt;
     *     &lt;var&gt;
     *       &lt;var-name&gt;multiFieldValidator&lt;/var-name&gt;
     *       &lt;var-value&gt;sample.SampleMultiFieldValidator&lt;/var-value&gt;
     *     &lt;/var&gt;
     *   &lt;/field&gt;
     * &lt;/form&gt;
     * </pre></code>
     * <h5>?bZ?[W\?[Xt@C?</h5>
     * <code>
     * errors.multiField={0}{1}{2}l?B
     * </code>
     * 
     * <h5>validation.xml?v&lt;var&gt;vf</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>K?{?</b></center></td>
     * <td><center><b>Tv</b></center></td>
     * </tr>
     * <tr>
     * <td> fields </td>
     * <td>?KvtB?[h</td>
     * <td>false</td>
     * <td>?tB?[hw??tB?[hJ}? w?B</td>
     * </tr>
     * <tr>
     * <td> multiFieldValidator </td>
     * <td>{@link MultiFieldValidator} NX</td>
     * <td>false</td>
     * <td>?tB?[h`FbN?s {@link MultiFieldValidator} NX?B</td>
     * </tr>
     * </table>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            ValidatorpValidatorAction
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return l? <code>true</code>
     */
    public static boolean validateMultiField(Object bean, ValidatorAction va, Field field, ActionMessages errors,
            Validator validator, HttpServletRequest request) {

        // beannull?AG?[?O?o?Atruep?B
        if (bean == null) {
            log.error("bean is null.");
            return true;
        }

        // ??l
        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtils.getValueAsString(bean, field.getProperty());
        }
        // tB?[hK?{`FbN?l?A
        // ?lnull???tB?[h`FbN?s?B

        // MultiFieldValidatorNX
        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);
        }

        // ?tB?[hl
        String fields = field.getVarValue("fields");
        List<String> valueList = new ArrayList<String>();
        if (fields != null) {
            StringTokenizer st = new StringTokenizer(fields, ",");
            while (st.hasMoreTokens()) {
                String f = st.nextToken();
                f = f.trim();
                valueList.add(ValidatorUtils.getValueAsString(bean, f));
            }
        }

        if (log.isDebugEnabled()) {
            log.debug("dependent fields:" + valueList);
        }

        String[] values = new String[valueList.size()];

        valueList.toArray(values);

        boolean result = mfv.validate(value, values);

        if (!result) {
            errors.add(field.getKey(), Resources.getActionMessage(validator, request, va, field));
            return false;
        }

        return true;
    }

    /**
     * z?ERNV^tB?[hlSvf`FbN?B
     * <p>
     * z?ERNV^tH?[vf??A? CfbNX? <code>ActionMessage</code>?B
     * ?sTu?\bh?^?A???A?\bh vKv?B
     * Fieldproperty?JXPathIndexedBeanWrapperImpldl?]?A
     * lXgv?peB?\?B
     * </p>
     * 
     * @param bean
     *            ??IuWFNg
     * @param va
     *            Strutsp<code>ValidatorAction</code>
     * @param field
     *            tB?[hIuWFNg
     * @param errors
     *            ANVG?[
     * @param validator
     *            ValidatorCX^X
     * @param request
     *            HTTPNGXg
     * @return vfl? <code>true</code>
     */
    public static boolean validateArraysIndex(@SuppressWarnings("unused") Object bean, ValidatorAction va,
            Field field, ActionMessages errors, Validator validator, HttpServletRequest request) {

        // ??
        int methodArgCount = 6;

        // z?ERNV???ifalsep???Afalse?j
        boolean totalResult = true;
        try {
            // RXgN^?NXp^?[
            Class[] paramClass = getParamClass(va);
            if (paramClass == null) {
                log.error("Can not get class pattern.");
                return true;
            }
            // paramClassvf?=0?AG?[?O?o?Atruep
            if (paramClass.length == 0) {
                log.error("Class pattern length is zero.");
                return true;
            }

            // evf??s?\bh
            Method method = getMethod(va, paramClass);
            if (method == null) {
                log.error("Can not get validateMethod.");
                return true;
            }

            // tH?[IuWFNg
            ActionForm form = getActionForm(request);
            if (form == null) {
                log.error("Can not get ActionForm.");
                return true;
            }

            // vfof?[V?[?A
            // O?svIuWFNg
            Object[] argParams = new Object[methodArgCount];
            argParams[0] = form;
            argParams[1] = va;
            argParams[3] = errors;
            argParams[4] = validator;
            argParams[5] = request;

            IndexedBeanWrapper wrapper = new JXPathIndexedBeanWrapperImpl(form);
            Map<String, Object> propertyMap = wrapper.getIndexedPropertyValues(field.getKey());

            int index = 0;

            for (String key : propertyMap.keySet()) {
                // CfbNXtv?peBtB?[h?
                Field indexedField = (Field) field.clone();
                indexedField.setIndexedListProperty(null);
                indexedField = getArrayIndexField(indexedField, index);
                indexedField.setKey(key);
                indexedField.setProperty(key);

                argParams[2] = indexedField; // tB?[h

                // `FbN?\bh?o
                Object resultObj = method.invoke(FieldChecksEx.class, argParams);
                // ?
                if (!isValid(resultObj)) {
                    totalResult = false;
                }
                index++;
            }

        } catch (IllegalArgumentException e) {
            log.error("", e);
            return true;
        } catch (IllegalAccessException e) {
            log.error("", e);
            return true;
        } catch (InvocationTargetException e) {
            log.error("", e);
            return true;
        }
        return totalResult;
    }

    /**
     * tH?[IuWFNg?B
     * 
     * <b>?\bhANVtH?[? tH?[O?Ap?s???B</b>
     * 
     * @param request
     *            HTTPNGXg
     * @return tH?[IuWFNg
     */
    protected static ActionForm getActionForm(HttpServletRequest request) {

        // NGXg??ANVtH?[
        String formName = ActionFormUtil.getActionFormName(request);
        // tH?[??nullp
        if (formName == null) {
            return null;
        }

        // ZbVtH?[
        Object obj = request.getSession(true).getAttribute(formName);
        ActionForm form = null;
        if (obj instanceof ActionForm) {
            form = (ActionForm) obj;
        }

        // ZbV??ANGXg
        if (form == null) {
            obj = request.getAttribute(formName);
            if (obj instanceof ActionForm) {
                form = (ActionForm) obj;
            }
        }
        return form;
    }

    /**
     * ??[?\bhn?NXz?B
     * 
     * <b>?\bhANVtH?[? tH?[O?Ap?s???B</b>
     * 
     * @param va
     *            Strutsp<code>ValidatorAction</code>
     * @return ?NXz
     */
    protected static Class[] getParamClass(ValidatorAction va) {

        String methodParams = va.getMethodParams();
        if (methodParams == null) {
            return null;
        }

        StringTokenizer st = new StringTokenizer(methodParams, ",");
        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) {
                log.error("", e);
                return null;
            }
        }
        return paramClass;
    }

    /**
     * z?ERNVvf??\bh?B
     * 
     * <b>?\bhANVtH?[? tH?[O?Ap?s???B</b>
     * 
     * @param va
     *            Strutsp<code>ValidatorAction</code>
     * @param paramClass
     *            ?NXz
     * @return ??\bhIuWFNg
     */
    protected static Method getMethod(ValidatorAction va, Class[] paramClass) {

        String methodNameSource = va.getName();
        if (methodNameSource == null || "".equals(methodNameSource)) {
            // ?\bhwnullnullp?B
            return null;
        }

        // name?"Array"??\bh??
        // 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 = FieldChecksEx.class.getMethod(methodName, paramClass);
        } catch (NoSuchMethodException e) {
            try {
                method = ValidWhen.class.getMethod(methodName, paramClass);
            } catch (NoSuchMethodException e1) {
                log.error("", e);
                log.error("", e1);
                return null;
            }
        }
        return method;
    }

    /**
     * tNVp?s?\bh IuWFNg?A??`FbN?B
     * 
     * <b>?\bhANVtH?[? tH?[O?Ap?s???B</b>
     * 
     * @param result
     *            IuWFNg
     * @return ?? <code>true</code>
     */
    protected static boolean isValid(Object result) {
        boolean isValid = false;

        if (result instanceof Boolean) {
            Boolean valid = (Boolean) result;
            isValid = valid.booleanValue();
        } else {
            // Boolean^?Atruep?B
            return true;
        }

        return isValid;
    }

    /**
     * wIndextB?[h?B
     * 
     * <b>?\bhANVtH?[? tH?[O?Ap?s???B</b>
     * 
     * @param field
     *            utB?[hIuWFNg
     * @param pos
     *            ?CfbNX
     * @return u?tB?[hIuWFNg
     */
    protected static Field getArrayIndexField(Field field, int pos) {
        Field cloneField = (Field) field.clone();

        // ##index?A?vf??
        Arg argParam = null;
        String argStr = null;

        argParam = cloneField.getArg(0);
        if (argParam != null) {
            argStr = argParam.getKey();
            cloneField.getArg(0).setKey(replaceIndexString(argStr, pos + 1));
        }

        argParam = cloneField.getArg(1);
        if (argParam != null) {
            argStr = argParam.getKey();
            cloneField.getArg(1).setKey(replaceIndexString(argStr, pos + 1));
        }

        argParam = cloneField.getArg(2);
        if (argParam != null) {
            argStr = argParam.getKey();
            cloneField.getArg(2).setKey(replaceIndexString(argStr, pos + 1));
        }

        argParam = cloneField.getArg(3);
        if (argParam != null) {
            argStr = argParam.getKey();
            cloneField.getArg(3).setKey(replaceIndexString(argStr, pos + 1));
        }

        return cloneField;
    }

    /**
     * <code>arg</code>l##INDEX?A?CfbNXl u
     * 
     * <b>?\bhANVtH?[? tH?[O?Ap?s???B</b>
     * 
     * @param arg
     *            <code>ActionMessage</code>uL?[?
     * @param pos
     *            ?CfbNX
     * @return L?[##INDEX?A?CfbNXp
     */
    protected static String replaceIndexString(String arg, int pos) {
        if (arg == null) {
            return null;
        }
        if (INDEX.equalsIgnoreCase(arg)) {
            return Integer.toString(pos);
        }
        return arg;
    }

    /**
     * woCg?B<br>
     * ?GR?[fBOoCg?Aw ?AGR?[hs??ftHgGR?[fBO
     * oCg?s?B
     * 
     * @param value
     *            oCg?
     * @param encoding
     *            GR?[fBO
     * @return oCg
     */
    protected static int getByteLength(String value, String encoding) {
        if (value == null || "".equals(value)) {
            return 0;
        }
        byte[] bytes = null;
        if (encoding == null || "".equals(encoding)) {
            bytes = value.getBytes();
        } else {
            try {
                bytes = value.getBytes(encoding);
            } catch (UnsupportedEncodingException e) {
                if (log.isWarnEnabled()) {
                    log.warn(encoding + " is not supported.");
                }
                bytes = value.getBytes();
            }
        }
        return bytes == null ? 0 : bytes.length;
    }

    /**
     * pJiXg?B
     * 
     * @return pJiXg
     */
    public static String getHankakuKanaList() {
        return hankakuKanaList;
    }

    /**
     * SpJiXg?B
     * 
     * @return SpJiXg
     */
    public static String getZenkakuKanaList() {
        return zenkakuKanaList;
    }

}