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