View Javadoc

    1   /*
    2    * Copyright 2004-2009 the Seasar Foundation and the Others.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    13   * either express or implied. See the License for the specific language
    14   * governing permissions and limitations under the License.
    15   */
    16  package org.seasar.cubby.validator;
    17
    18  import java.util.ArrayList;
    19  import java.util.List;
    20  import java.util.Map;
    21
    22  import org.seasar.cubby.action.ActionErrors;
    23  import org.seasar.cubby.action.FieldInfo;
    24  import org.seasar.cubby.action.MessageInfo;
    25
    26  /**
    27   * 入力フォームのフィールドに対する入力検証のルールです。
    28   *
    29   * @author baba
    30   */
    31  public class FieldValidationRule implements ValidationRule {
    32
    33  	/** 空のオブジェクト配列。 */
    34  	private static final Object[] EMPTY_VALUES = new Object[] { "" };
    35
    36  	/** この入力検証ルールが対応する入力フォームのフィールド名。 */
    37  	private final String fieldName;
    38
    39  	/** リソースバンドルからフィールド名を取得するためのキー。 */
    40  	private final String fieldNameKey;
    41
    42  	/** 入力検証を実行するクラスのリスト。 */
    43  	private final List<ValidationInvoker> invokers = new ArrayList<ValidationInvoker>();
    44
    45  	/**
    46  	 * 指定されたフィールド名に対する入力検証ルールを生成します。
    47  	 *
    48  	 * @param fieldName
    49  	 *            フィールド名
    50  	 * @param validators
    51  	 *            入力検証
    52  	 */
    53  	public FieldValidationRule(final String fieldName,
    54  			final Validator... validators) {
    55  		this(fieldName, fieldName, validators);
    56  	}
    57
    58  	/**
    59  	 * 指定されたフィールド名に対する入力検証ルールを生成します。
    60  	 *
    61  	 * @param fieldName
    62  	 *            フィールド名
    63  	 * @param fieldNameKey
    64  	 *            リソースバンドルからフィールド名を取得するためのキー
    65  	 * @param validators
    66  	 *            入力検証
    67  	 */
    68  	public FieldValidationRule(final String fieldName,
    69  			final String fieldNameKey, final Validator... validators) {
    70  		this.fieldName = fieldName;
    71  		this.fieldNameKey = fieldNameKey;
    72  		for (final Validator validator : validators) {
    73  			final ValidationInvoker invoker = createInvoker(validator);
    74  			this.invokers.add(invoker);
    75  		}
    76  	}
    77
    78  	/**
    79  	 * {@inheritDoc}
    80  	 * <p>
    81  	 * 対応するフィールドに対してこのオブジェクトが保持する入力検証を順次実行します。
    82  	 * </p>
    83  	 */
    84  	public void apply(final Map<String, Object[]> params, final Object form,
    85  			final ActionErrors errors) {
    86  		final Object[] values = getValues(params, this.fieldName);
    87  		for (final ValidationInvoker invoker : this.invokers) {
    88  			invoker.invoke(this, values, errors);
    89  		}
    90  	}
    91
    92  	/**
    93  	 * 要求パラメータの{@link Map}から指定されたフィールド名に対する値を取得します。
    94  	 *
    95  	 * @param params
    96  	 *            要求パラメータの{@link Map}
    97  	 * @param fieldName
    98  	 *            フィールド名
    99  	 * @return フィールド名に対する値
    100 	 */
    101 	private Object[] getValues(final Map<String, Object[]> params,
    102 			final String fieldName) {
    103 		final Object[] values = params.get(fieldName);
    104 		if (values != null) {
    105 			return values;
    106 		}
    107 		return EMPTY_VALUES;
    108 	}
    109
    110 	/**
    111 	 * この入力検証ルールが対応する入力フォームのフィールド名を取得します。
    112 	 *
    113 	 * @return この入力検証ルールが対応する入力フォームのフィールド名
    114 	 */
    115 	public String getFieldName() {
    116 		return fieldName;
    117 	}
    118
    119 	/**
    120 	 * リソースバンドルからフィールド名を取得するためのキーを取得します。
    121 	 *
    122 	 * @return リソースバンドルからフィールド名を取得するためのキー
    123 	 */
    124 	public String getFieldNameKey() {
    125 		return fieldNameKey;
    126 	}
    127
    128 	/**
    129 	 * 入力検証を呼び出すクラスのインスタンスを生成します。
    130 	 *
    131 	 * @param validator
    132 	 *            入力検証
    133 	 * @return 入力検証を呼び出すクラスのインスタンス
    134 	 */
    135 	private ValidationInvoker createInvoker(final Validator validator) {
    136 		final ValidationInvoker invoker;
    137 		if (validator instanceof ArrayFieldValidator) {
    138 			invoker = new ArrayFieldValidationInvoker(
    139 					(ArrayFieldValidator) validator);
    140 		} else if (validator instanceof ScalarFieldValidator) {
    141 			invoker = new ScalarFieldValidationInvoker(
    142 					(ScalarFieldValidator) validator);
    143 		} else {
    144 			throw new UnsupportedOperationException();
    145 		}
    146 		return invoker;
    147 	}
    148
    149 	/**
    150 	 * 入力検証を呼び出すためのクラスです。
    151 	 *
    152 	 * @author baba
    153 	 */
    154 	private interface ValidationInvoker {
    155
    156 		/**
    157 		 * 入力検証を呼び出します。
    158 		 *
    159 		 * @param validationRule
    160 		 *            入力検証ルール
    161 		 * @param values
    162 		 *            入力検証を行う値
    163 		 * @param errors
    164 		 *            アクションで発生したエラー
    165 		 */
    166 		void invoke(FieldValidationRule validationRule, Object[] values,
    167 				ActionErrors errors);
    168
    169 	}
    170
    171 	/**
    172 	 * {@link ArrayFieldValidator}の入力検証を呼び出すためのクラスです。
    173 	 *
    174 	 * @author baba
    175 	 */
    176 	private static class ArrayFieldValidationInvoker implements
    177 			ValidationInvoker {
    178
    179 		/**
    180 		 * {@link #invoke(FieldValidationRule, Object[], ActionErrors)}
    181 		 * で呼び出す入力検証。
    182 		 */
    183 		private final ArrayFieldValidator validator;
    184
    185 		/**
    186 		 * インスタンス化します。
    187 		 *
    188 		 * @param validator
    189 		 *            入力検証
    190 		 */
    191 		public ArrayFieldValidationInvoker(final ArrayFieldValidator validator) {
    192 			this.validator = validator;
    193 		}
    194
    195 		/**
    196 		 * {@inheritDoc}
    197 		 */
    198 		public void invoke(final FieldValidationRule validationRule,
    199 				final Object[] values, final ActionErrors errors) {
    200 			final ValidationContext context = new ValidationContext();
    201 			final FieldInfo fieldInfo = new FieldInfo(validationRule
    202 					.getFieldName());
    203 			this.validator.validate(context, values);
    204 			for (final MessageInfo messageInfo : context.getMessageInfos()) {
    205 				final String message = messageInfo.toMessage(validationRule
    206 						.getFieldNameKey());
    207 				errors.add(message, fieldInfo);
    208 			}
    209 		}
    210
    211 	}
    212
    213 	/**
    214 	 * {@link ScalarFieldValidator}の入力検証を呼び出すためのクラスです。
    215 	 *
    216 	 * @author baba
    217 	 */
    218 	private static class ScalarFieldValidationInvoker implements
    219 			ValidationInvoker {
    220
    221 		/**
    222 		 * {@link #invoke(FieldValidationRule, Object[], ActionErrors)}
    223 		 * で呼び出す入力検証。
    224 		 */
    225 		private final ScalarFieldValidator validator;
    226
    227 		/**
    228 		 * インスタンス化します。
    229 		 *
    230 		 * @param validator
    231 		 *            入力検証
    232 		 */
    233 		public ScalarFieldValidationInvoker(final ScalarFieldValidator validator) {
    234 			this.validator = validator;
    235 		}
    236
    237 		/**
    238 		 * {@inheritDoc}
    239 		 */
    240 		public void invoke(final FieldValidationRule validationRule,
    241 				final Object[] values, final ActionErrors errors) {
    242 			for (int i = 0; i < values.length; i++) {
    243 				final ValidationContext context = new ValidationContext();
    244 				final FieldInfo fieldInfo = new FieldInfo(validationRule
    245 						.getFieldName(), i);
    246 				this.validator.validate(context, values[i]);
    247 				for (final MessageInfo messageInfo : context.getMessageInfos()) {
    248 					final String message = messageInfo.toMessage(validationRule
    249 							.getFieldNameKey());
    250 					errors.add(message, fieldInfo);
    251 				}
    252 			}
    253 		}
    254
    255 	}
    256
    257 }