Coverage Report - org.seasar.cubby.tags.TagUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
TagUtils
87%
80/92
75%
39/52
0
 
 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.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_ERRORS;
 21  
 import static org.seasar.cubby.CubbyConstants.ATTR_PARAMS;
 22  
 import static org.seasar.cubby.CubbyConstants.ATTR_VALIDATION_FAIL;
 23  
 import static org.seasar.cubby.internal.util.LogMessages.format;
 24  
 
 25  
 import java.util.Collection;
 26  
 import java.util.Map;
 27  
 import java.util.Map.Entry;
 28  
 
 29  
 import javax.servlet.jsp.JspContext;
 30  
 import javax.servlet.jsp.tagext.SimpleTag;
 31  
 import javax.servlet.jsp.tagext.SimpleTagSupport;
 32  
 
 33  
 import org.seasar.cubby.CubbyConstants;
 34  
 import org.seasar.cubby.action.ActionErrors;
 35  
 import org.seasar.cubby.internal.controller.FormWrapper;
 36  
 import org.seasar.cubby.internal.util.StringUtils;
 37  
 import org.slf4j.Logger;
 38  
 import org.slf4j.LoggerFactory;
 39  
 
 40  
 /**
 41  
  * カスタムタグで使用するユーティリティクラスです。
 42  
  * 
 43  
  * @author baba
 44  
  * @since 1.0.0
 45  
  */
 46  0
 class TagUtils {
 47  
 
 48  
         /** ロガー。 */
 49  1
         private static final Logger logger = LoggerFactory
 50  
                         .getLogger(TagUtils.class);
 51  
 
 52  
         /**
 53  
          * 指定されたJSPコンテキストから{@link ActionErrors}を取得します。
 54  
          * 
 55  
          * @param context
 56  
          *            JSPコンテキスト
 57  
          * @return アクションで発生したエラー
 58  
          */
 59  
         public static ActionErrors errors(final JspContext context) {
 60  37
                 return (ActionErrors) context.getAttribute(ATTR_ERRORS, REQUEST_SCOPE);
 61  
         }
 62  
 
 63  
         /**
 64  
          * 指定されたJSPコンテキストから指定されたパラメータ名に対応するリクエストパラメータを取得します。
 65  
          * 
 66  
          * @param context
 67  
          *            JSPコンテキスト
 68  
          * @param name
 69  
          *            パラメータ名
 70  
          * @return リクエストパラメータ
 71  
          */
 72  
         @SuppressWarnings("unchecked")
 73  
         private static Object[] paramValues(final JspContext context,
 74  
                         final String name) {
 75  7
                 final Map<String, Object[]> valuesMap = Map.class.cast(context
 76  
                                 .getAttribute(ATTR_PARAMS, REQUEST_SCOPE));
 77  
                 final Object[] values;
 78  7
                 if (valuesMap == null || !valuesMap.containsKey(name)) {
 79  0
                         values = new Object[0];
 80  
                 } else {
 81  7
                         values = valuesMap.get(name);
 82  
                 }
 83  7
                 return values;
 84  
         }
 85  
 
 86  
         /**
 87  
          * 指定されたフィールド名に対応するフォームのフィールドへの出力値を取得します。
 88  
          * 
 89  
          * @param context
 90  
          *            JSPコンテキスト
 91  
          * @param formWrapper
 92  
          *            フォームオブジェクトのラッパー
 93  
          * @param name
 94  
          *            フィールド名
 95  
          * @return フォームのフィールドへの出力値
 96  
          */
 97  
         public static Object[] multipleFormValues(final JspContext context,
 98  
                         final FormWrapper formWrapper, final String name) {
 99  16
                 return multipleFormValues(context, formWrapper, name, null);
 100  
         }
 101  
 
 102  
         /**
 103  
          * 指定されたフィールド名に対応するフォームのフィールドへの出力値を取得します。
 104  
          * 
 105  
          * @param context
 106  
          *            JSPコンテキスト
 107  
          * @param formWrapper
 108  
          *            フォームオブジェクトのラッパー
 109  
          * @param name
 110  
          *            フィールド名
 111  
          * @param checkedValue
 112  
          *            チェック済みにする値
 113  
          * @return フォームのフィールドへの出力値
 114  
          */
 115  
         public static Object[] multipleFormValues(final JspContext context,
 116  
                         final FormWrapper formWrapper, final String name,
 117  
                         final String checkedValue) {
 118  
                 final Object[] values;
 119  30
                 if (isValidationFail(context)) {
 120  5
                         values = paramValues(context, name);
 121  
                 } else {
 122  25
                         if (checkedValue != null) {
 123  5
                                 values = new Object[] { checkedValue };
 124  
                         } else {
 125  20
                                 if (!formWrapper.hasValues(name)) {
 126  0
                                         if (logger.isDebugEnabled()) {
 127  0
                                                 logger.debug(format("DCUB0023", name));
 128  
                                         }
 129  0
                                         return null;
 130  
                                 }
 131  20
                                 values = formWrapper.getValues(name);
 132  
                         }
 133  
                 }
 134  30
                 return values;
 135  
         }
 136  
 
 137  
         /**
 138  
          * 指定されたフィールド名に対応するフォームのフィールドへの出力値を取得します。
 139  
          * 
 140  
          * @param context
 141  
          *            JSPコンテキスト
 142  
          * @param formWrapper
 143  
          *            フォームオブジェクトのラッパー
 144  
          * @param name
 145  
          *            フィールド名
 146  
          * @param index
 147  
          *            インデックス
 148  
          * @param specifiedValue
 149  
          *            エラーがない場合に設定する値
 150  
          * @return フォームのフィールドへの出力値
 151  
          */
 152  
         public static Object formValue(final JspContext context,
 153  
                         final FormWrapper formWrapper, final String name,
 154  
                         final Integer index, final Object specifiedValue) {
 155  
                 final Object value;
 156  
 
 157  9
                 if (isValidationFail(context)) {
 158  2
                         if (specifiedValue == null) {
 159  1
                                 final Object[] values = paramValues(context, name);
 160  1
                                 value = value(values, index);
 161  1
                         } else {
 162  1
                                 final Object[] values = paramValues(context, name);
 163  1
                                 if (values.length == 0) {
 164  0
                                         value = specifiedValue;
 165  
                                 } else {
 166  1
                                         value = value(values, index);
 167  
                                 }
 168  1
                         }
 169  
                 } else {
 170  7
                         if (specifiedValue != null) {
 171  2
                                 value = specifiedValue;
 172  
                         } else {
 173  5
                                 if (!formWrapper.hasValues(name)) {
 174  1
                                         logger.debug(format("DCUB0023", name));
 175  1
                                         return null;
 176  
                                 }
 177  4
                                 value = value(formWrapper.getValues(name), index);
 178  
                         }
 179  
                 }
 180  
 
 181  8
                 return value;
 182  
         }
 183  
 
 184  
         /**
 185  
          * オブジェクトの配列から指定されたインデックスの値を取得します。
 186  
          * <p>
 187  
          * values が <code>null</code> の場合や index が要素数を越えていた場合は空文字を返します。index が
 188  
          * <code>null</code> の場合は配列の最初の要素を返します。
 189  
          * </p>
 190  
          * 
 191  
          * @param values
 192  
          *            オブジェクトの配列
 193  
          * @param index
 194  
          *            インデックス
 195  
          * @return 指定されたインデックスの要素
 196  
          */
 197  
         private static Object value(final Object[] values, final Integer index) {
 198  
                 final Object value;
 199  6
                 if (values == null) {
 200  0
                         value = "";
 201  
                 } else {
 202  6
                         if (index == null) {
 203  6
                                 value = getElement(values, 0);
 204  
                         } else {
 205  0
                                 value = getElement(values, index);
 206  
                         }
 207  
                 }
 208  6
                 return value;
 209  
         }
 210  
 
 211  
         /**
 212  
          * オブジェクトの配列から指定されたインデックスの要素を取得します。
 213  
          * <p>
 214  
          * index が要素数を越えていた場合は空文字を返します。
 215  
          * </p>
 216  
          * 
 217  
          * @param values
 218  
          *            オブジェクトの配列
 219  
          * @param index
 220  
          *            インデックス
 221  
          * @return 指定されたインデックスの要素
 222  
          */
 223  
         private static Object getElement(final Object[] values, final Integer index) {
 224  
                 final Object value;
 225  6
                 if (values.length <= index) {
 226  0
                         value = "";
 227  
                 } else {
 228  6
                         value = values[index];
 229  
                 }
 230  6
                 return value;
 231  
         }
 232  
 
 233  
         /**
 234  
          * 指定されたJSPコンテキストのアクションが入力検証に失敗したかどうかを示します。
 235  
          * 
 236  
          * @param context
 237  
          *            JSPコンテキスト
 238  
          * @return アクションが入力検証に失敗した場合は <code>true</code>、そうでない場合は <code>false</code>
 239  
          * @see CubbyConstants#ATTR_VALIDATION_FAIL
 240  
          */
 241  
         private static boolean isValidationFail(final JspContext context) {
 242  39
                 return TRUE.equals(context.getAttribute(ATTR_VALIDATION_FAIL,
 243  
                                 REQUEST_SCOPE));
 244  
         }
 245  
 
 246  1
         public static final Object REMOVE_ATTRIBUTE = new Object();
 247  
 
 248  
         /**
 249  
          * 指定された {@link Map} を HTML タグの属性へ変換します。
 250  
          * <p>
 251  
          * map 中の値が {@link #REMOVE_ATTRIBUTE} の場合、その属性は結果から除外します。
 252  
          * </p>
 253  
          * 
 254  
          * @param map
 255  
          *            属性のマップ
 256  
          * @return HTML タグの属性
 257  
          */
 258  
         public static String toAttr(final Map<String, Object> map) {
 259  47
                 final StringBuilder builder = new StringBuilder();
 260  47
                 for (final Entry<String, Object> entry : map.entrySet()) {
 261  19
                         final String key = entry.getKey();
 262  19
                         if (entry.getValue() == REMOVE_ATTRIBUTE) {
 263  0
                                 continue;
 264  
                         }
 265  19
                         builder.append(key);
 266  19
                         builder.append("=\"");
 267  19
                         builder.append(escapeHtml(entry.getValue()));
 268  19
                         builder.append("\" ");
 269  19
                 }
 270  46
                 return builder.toString();
 271  
         }
 272  
 
 273  
         /**
 274  
          * 指定されたオブジェクトが特定の文字列を含むかを示します。
 275  
          * <p>
 276  
          * 指定されたオブジェクトが配列や{@link Collection}の場合は、その要素の文字列表現が指定された文字列と同値かを示します。
 277  
          * 指定されたオブジェクトが配列や{@link Collection}でない場合は、そのオブジェクトの文字列表現が指定された文字列と同値かを示します。
 278  
          * </p>
 279  
          * 
 280  
          * @param obj
 281  
          *            オブジェクト
 282  
          * @param str
 283  
          *            文字列
 284  
          * @return 指定されたオブジェクトが特定の文字列を含む場合は <code>true</code>、そうでない場合は
 285  
          *         <code>false</code>
 286  
          */
 287  
         public static boolean contains(final Object obj, final String str) {
 288  60
                 if (obj instanceof Collection) {
 289  1
                         return ((Collection<?>) obj).contains(str);
 290  59
                 } else if (obj.getClass().isArray()) {
 291  95
                         for (final Object value : (Object[]) obj) {
 292  62
                                 if (equalsAsString(value, str)) {
 293  23
                                         return true;
 294  
                                 }
 295  
                         }
 296  32
                         return false;
 297  
                 } else {
 298  2
                         return equalsAsString(obj, str);
 299  
                 }
 300  
         }
 301  
 
 302  
         /**
 303  
          * 指定された値が文字列として同値かを示します。
 304  
          * 
 305  
          * @param obj1
 306  
          *            比較するオブジェクト1
 307  
          * @param obj2
 308  
          *            比較するオブジェクト2
 309  
          * @return obj1とobj2が文字列として同値の場合は <code>true</code>、そうでない場合は
 310  
          *         <code>false</code>
 311  
          */
 312  
         private static boolean equalsAsString(final Object obj1, final Object obj2) {
 313  64
                 if (obj1 == obj2) {
 314  10
                         return true;
 315  54
                 } else if (obj1 == null) {
 316  4
                         return false;
 317  
                 } else {
 318  50
                         return obj1.toString().equals(obj2.toString());
 319  
                 }
 320  
         }
 321  
 
 322  
         /**
 323  
          * 動的な属性の {@link Map} に、指定された <code>class</code> 属性を追加します。
 324  
          * 
 325  
          * @param dynamicAttributes
 326  
          *            動的な属性の {@link Map}
 327  
          * @param className
 328  
          *            <code>class</code> 属性の名前
 329  
          */
 330  
         public static void addCSSClassName(
 331  
                         final Map<String, Object> dynamicAttributes, final String className) {
 332  3
                 String classValue = (String) dynamicAttributes.get("class");
 333  2
                 if (StringUtils.isEmpty(classValue)) {
 334  1
                         classValue = className;
 335  
                 } else {
 336  1
                         classValue = classValue + " " + className;
 337  
                 }
 338  2
                 dynamicAttributes.put("class", classValue);
 339  2
         }
 340  
 
 341  
         /**
 342  
          * 指定されたタグの親の {@link FormTag} を検索し、そこからフォームオブジェクトのラッパーを取得します。
 343  
          * 
 344  
          * @param tag
 345  
          *            タグ
 346  
          * @return フォームオブジェクトのラッパー
 347  
          */
 348  
         public static FormWrapper getFormWrapper(final SimpleTag tag) {
 349  35
                 final FormTag formTag = (FormTag) SimpleTagSupport
 350  
                                 .findAncestorWithClass(tag, FormTag.class);
 351  35
                 if (formTag == null) {
 352  0
                         return null;
 353  
                 }
 354  35
                 return formTag.getFormWrapper();
 355  
         }
 356  
 
 357  
         /**
 358  
          * 指定された文字列をHTMLとしてエスケープします。
 359  
          * <p>
 360  
          * <table>
 361  
          * <thead>
 362  
          * <tr>
 363  
          * <th>変換前</th>
 364  
          * <th>変換後</th>
 365  
          * </tr>
 366  
          * </thead> <tbody>
 367  
          * <tr>
 368  
          * <td>&amp;</td>
 369  
          * <td>&amp;amp;</td>
 370  
          * </tr>
 371  
          * <tr>
 372  
          * <td>&lt;</td>
 373  
          * <td>&amp;lt;</td>
 374  
          * </tr>
 375  
          * <tr>
 376  
          * <td>&gt;</td>
 377  
          * <td>&amp;gt;</td>
 378  
          * </tr>
 379  
          * <tr>
 380  
          * <td>&quot;</td>
 381  
          * <td>&amp;quot;</td>
 382  
          * </tr>
 383  
          * <tr>
 384  
          * <td>&#39</td>
 385  
          * <td>&amp;#39</td>
 386  
          * </tr>
 387  
          * </tbody>
 388  
          * </table>
 389  
          * </p>
 390  
          * 
 391  
          * @param str
 392  
          * @return エスケープされた文字列
 393  
          */
 394  
         public static String escapeHtml(final Object str) {
 395  114
                 if (str == null) {
 396  0
                         return "";
 397  
                 }
 398  114
                 String text = str.toString();
 399  114
                 text = StringUtils.replace(text, "&", "&amp;");
 400  114
                 text = StringUtils.replace(text, "<", "&lt;");
 401  114
                 text = StringUtils.replace(text, ">", "&gt;");
 402  114
                 text = StringUtils.replace(text, "\"", "&quot;");
 403  114
                 text = StringUtils.replace(text, "'", "&#39;");
 404  114
                 return text;
 405  
         }
 406  
 
 407  
         /**
 408  
          * オブジェクトを文字列に変換します。 オブジェクトが<code>null</code>の場合、空文字を返します。
 409  
          * 
 410  
          * @param object
 411  
          *            対象のオブジェクト
 412  
          * @return オブジェクトのtoString結果。
 413  
          */
 414  
         public static String toString(final Object object) {
 415  88
                 return object == null ? "" : object.toString();
 416  
         }
 417  
 
 418  
 }