View Javadoc

1   /*
2    * Copyright 2004-2008 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.tags;
17  
18  import static java.lang.Boolean.TRUE;
19  import static javax.servlet.jsp.PageContext.REQUEST_SCOPE;
20  import static org.seasar.cubby.CubbyConstants.ATTR_OUTPUT_VALUES;
21  import static org.seasar.cubby.CubbyConstants.ATTR_PARAMS;
22  import static org.seasar.cubby.CubbyConstants.ATTR_VALIDATION_FAIL;
23  
24  import java.util.Collection;
25  import java.util.Map;
26  import java.util.Map.Entry;
27  
28  import javax.servlet.jsp.JspContext;
29  import javax.servlet.jsp.PageContext;
30  
31  import org.seasar.cubby.CubbyConstants;
32  import org.seasar.cubby.action.ActionErrors;
33  import org.seasar.cubby.util.CubbyUtils;
34  import org.seasar.framework.util.StringUtil;
35  
36  /**
37   * カスタムタグで使用するユーティリティクラスです。
38   * 
39   * @author baba
40   * @since 1.0.0
41   */
42  class TagUtils {
43  
44  	/** リクエストスコープから{@link ActionErrors}を取得するためのキー。 */
45  	private static final String ATTR_ERRORS = "errors";
46  
47  	/**
48  	 * 指定されたJSPコンテキストから{@link ActionErrors}を取得します。
49  	 * 
50  	 * @param context
51  	 *            JSPコンテキスト
52  	 * @return アクションで発生したエラー
53  	 */
54  	public static ActionErrors errors(final JspContext context) {
55  		return (ActionErrors) context.getAttribute(ATTR_ERRORS, REQUEST_SCOPE);
56  	}
57  
58  	/**
59  	 * 指定されたJSPコンテキストから指定されたパラメータ名に対応するリクエストパラメータを取得します。
60  	 * 
61  	 * @param context
62  	 *            JSPコンテキスト
63  	 * @param name
64  	 *            パラメータ名
65  	 * @return リクエストパラメータ
66  	 */
67  	@SuppressWarnings("unchecked")
68  	private static Object[] paramValues(final JspContext context,
69  			final String name) {
70  		final Map<String, Object[]> valuesMap = (Map<String, Object[]>) context
71  				.getAttribute(ATTR_PARAMS, REQUEST_SCOPE);
72  		final Object[] values;
73  		if (valuesMap == null || !valuesMap.containsKey(name)) {
74  			values = new Object[0];
75  		} else {
76  			values = valuesMap.get(name);
77  		}
78  		return values;
79  	}
80  
81  	/**
82  	 * フォーム値の{@link Map}から指定されたフィールドの値を取得します。
83  	 * 
84  	 * @param valuesMap
85  	 *            フォーム値の{@link Map}
86  	 * @param name
87  	 *            フィールド名
88  	 * @return フィールドの値
89  	 */
90  	private static Object[] formValues(final Map<String, String[]> valuesMap,
91  			final String name) {
92  		final Object[] values;
93  		if (valuesMap == null || !valuesMap.containsKey(name)) {
94  			values = new Object[0];
95  		} else {
96  			values = valuesMap.get(name);
97  		}
98  		return values;
99  	}
100 
101 	/**
102 	 * 指定されたフィールド名に対応するフォームのフィールドへの出力値を取得します。
103 	 * 
104 	 * @param context
105 	 *            JSPコンテキスト
106 	 * @param outputValuesMap
107 	 *            フォームへ出力する値の{@link Map}
108 	 * @param name
109 	 *            フィールド名
110 	 * @return フォームのフィールドへの出力値
111 	 */
112 	public static Object[] multipleFormValues(final JspContext context,
113 			final Map<String, String[]> outputValuesMap, final String name) {
114 		return multipleFormValues(context, outputValuesMap, name, null);
115 	}
116 
117 	/**
118 	 * 指定されたフィールド名に対応するフォームのフィールドへの出力値を取得します。
119 	 * 
120 	 * @param context
121 	 *            JSPコンテキスト
122 	 * @param outputValuesMap
123 	 *            フォームへ出力する値の{@link Map}
124 	 * @param name
125 	 *            フィールド名
126 	 * @param checkedValue
127 	 *            チェック済みにする値
128 	 * @return フォームのフィールドへの出力値
129 	 */
130 	public static Object[] multipleFormValues(final JspContext context,
131 			final Map<String, String[]> outputValuesMap, final String name,
132 			final String checkedValue) {
133 		final Object[] values;
134 		if (isValidationFail(context)) {
135 			values = paramValues(context, name);
136 		} else {
137 			if (checkedValue != null) {
138 				values = new Object[] { checkedValue };
139 			} else {
140 				values = formValues(outputValuesMap, name);
141 			}
142 		}
143 		return values;
144 	}
145 
146 	/**
147 	 * 指定されたフィールド名に対応するフォームのフィールドへの出力値を取得します。
148 	 * 
149 	 * @param context
150 	 *            JSPコンテキスト
151 	 * @param outputValuesMap
152 	 *            フォームへ出力する値の{@link Map}
153 	 * @param name
154 	 *            フィールド名
155 	 * @param index
156 	 *            インデックス
157 	 * @param specifiedValue
158 	 *            エラーがない場合に設定する値
159 	 * @return フォームのフィールドへの出力値
160 	 */
161 	public static Object formValue(final JspContext context,
162 			final Map<String, String[]> outputValuesMap, final String name,
163 			final Integer index, final Object specifiedValue) {
164 		final Object value;
165 
166 		if (isValidationFail(context)) {
167 			final Object[] values = paramValues(context, name);
168 			value = value(values, index);
169 		} else {
170 			if (specifiedValue == null) {
171 				final Object[] values = formValues(outputValuesMap, name);
172 				value = value(values, index);
173 			} else {
174 				value = specifiedValue;
175 			}
176 		}
177 
178 		return value;
179 	}
180 
181 	/**
182 	 * オブジェクトの配列から指定されたインデックスの値を取得します。
183 	 * <p>
184 	 * values が <code>null</code> の場合や index が要素数を越えていた場合は空文字を返します。index が
185 	 * <code>null</code> の場合は配列の最初の要素を返します。
186 	 * </p>
187 	 * 
188 	 * @param values
189 	 *            オブジェクトの配列
190 	 * @param index
191 	 *            インデックス
192 	 * @return 指定されたインデックスの要素
193 	 */
194 	private static Object value(final Object[] values, final Integer index) {
195 		final Object value;
196 		if (values == null) {
197 			value = "";
198 		} else {
199 			if (index == null) {
200 				value = getElement(values, 0);
201 			} else {
202 				value = getElement(values, index);
203 			}
204 		}
205 		return value;
206 	}
207 
208 	/**
209 	 * オブジェクトの配列から指定されたインデックスの要素を取得します。
210 	 * <p>
211 	 * index が要素数を越えていた場合は空文字を返します。
212 	 * </p>
213 	 * 
214 	 * @param values
215 	 *            オブジェクトの配列
216 	 * @param index
217 	 *            インデックス
218 	 * @return 指定されたインデックスの要素
219 	 */
220 	private static Object getElement(final Object[] values, final Integer index) {
221 		final Object value;
222 		if (values.length <= index) {
223 			value = "";
224 		} else {
225 			value = values[index];
226 		}
227 		return value;
228 	}
229 
230 	/**
231 	 * 指定されたJSPコンテキストのアクションが入力検証に失敗したかどうかを示します。
232 	 * 
233 	 * @param context
234 	 *            JSPコンテキスト
235 	 * @return アクションが入力検証に失敗した場合は <code>true</code>、そうでない場合は
236 	 *         <code>false</code>
237 	 * @see CubbyConstants#ATTR_VALIDATION_FAIL
238 	 */
239 	private static boolean isValidationFail(final JspContext context) {
240 		return TRUE.equals(context.getAttribute(ATTR_VALIDATION_FAIL,
241 				REQUEST_SCOPE));
242 	}
243 
244 	/**
245 	 * 指定されたJSPコンテキストから&lt;t:form&gt;タグによって設定されたフォームへの出力値の{@link Map}を取得します。
246 	 * 
247 	 * @param context
248 	 *            JSPコンテキスト
249 	 * @return フォームへの出力値の{@link Map}
250 	 */
251 	@SuppressWarnings("unchecked")
252 	public static Map<String, String[]> outputValues(final JspContext context) {
253 		final Map<String, String[]> outputValues = (Map<String, String[]>) context
254 				.getAttribute(ATTR_OUTPUT_VALUES, PageContext.PAGE_SCOPE);
255 		return outputValues;
256 	}
257 
258 	/**
259 	 * 指定された{@link Map}をHTMLタグの属性へ変換します。
260 	 * 
261 	 * @param map
262 	 *            属性のマップ
263 	 * @return HTMLタグの属性
264 	 */
265 	public static String toAttr(final Map<String, Object> map) {
266 		final StringBuilder builder = new StringBuilder();
267 		for (final Entry<String, Object> entry : map.entrySet()) {
268 			final String key = entry.getKey();
269 			if ("value".equals(key) || "checkedValue".equals(key)) {
270 				continue;
271 			}
272 			builder.append(key);
273 			builder.append("=\"");
274 			builder.append(CubbyUtils.escapeHtml(entry.getValue()));
275 			builder.append("\" ");
276 		}
277 		return builder.toString();
278 	}
279 
280 	/**
281 	 * 指定されたオブジェクトが特定の文字列を含むかを示します。
282 	 * <p>
283 	 * 指定されたオブジェクトが配列や{@link Collection}の場合は、その要素の文字列表現が指定された文字列と同値かを示します。
284 	 * 指定されたオブジェクトが配列や{@link Collection}でない場合は、そのオブジェクトの文字列表現が指定された文字列と同値かを示します。
285 	 * </p>
286 	 * 
287 	 * @param obj
288 	 *            オブジェクト
289 	 * @param str
290 	 *            文字列
291 	 * @return 指定されたオブジェクトが特定の文字列を含む場合は <code>true</code>、そうでない場合は
292 	 *         <code>false</code>
293 	 */
294 	public static boolean contains(final Object obj, final String str) {
295 		if (obj instanceof Collection) {
296 			return ((Collection<?>) obj).contains(str);
297 		} else if (obj.getClass().isArray()) {
298 			for (final Object value : (Object[]) obj) {
299 				if (equalsAsString(value, str)) {
300 					return true;
301 				}
302 			}
303 			return false;
304 		} else {
305 			return equalsAsString(obj, str);
306 		}
307 	}
308 
309 	/**
310 	 * 指定された値が文字列として同値かを示します。
311 	 * 
312 	 * @param obj1
313 	 *            比較するオブジェクト1
314 	 * @param obj2
315 	 *            比較するオブジェクト2
316 	 * @return obj1とobj2が文字列として同値の場合は <code>true</code>、そうでない場合は
317 	 *         <code>false</code>
318 	 */
319 	private static boolean equalsAsString(final Object obj1, final Object obj2) {
320 		if (obj1 == obj2) {
321 			return true;
322 		} else if (obj1 == null) {
323 			return false;
324 		} else {
325 			return obj1.toString().equals(obj2.toString());
326 		}
327 	}
328 
329 	/**
330 	 * Dynamic-Attributesに指定されたclass属性を追加します。
331 	 * 
332 	 * @param dyn
333 	 *            Dynamic-Attributes
334 	 * @param className
335 	 *            class属性の名前
336 	 */
337 	public static void addClassName(final Map<String, Object> dyn,
338 			final String className) {
339 		String classValue = (String) dyn.get("class");
340 		if (StringUtil.isEmpty(classValue)) {
341 			classValue = className;
342 		} else {
343 			classValue = classValue + " " + className;
344 		}
345 		dyn.put("class", classValue);
346 	}
347 
348 }