Coverage Report - org.seasar.cubby.internal.controller.impl.RequestParameterBinderImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
RequestParameterBinderImpl
82%
76/92
84%
37/44
8.2
 
 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.internal.controller.impl;
 18  
 
 19  
 import java.lang.reflect.Array;
 20  
 import java.util.ArrayList;
 21  
 import java.util.Collection;
 22  
 import java.util.LinkedHashSet;
 23  
 import java.util.List;
 24  
 import java.util.Map;
 25  
 import java.util.Set;
 26  
 
 27  
 import org.seasar.cubby.action.ActionContext;
 28  
 import org.seasar.cubby.action.FieldInfo;
 29  
 import org.seasar.cubby.action.MessageInfo;
 30  
 import org.seasar.cubby.action.RequestParameter;
 31  
 import org.seasar.cubby.converter.ConversionException;
 32  
 import org.seasar.cubby.converter.ConversionHelper;
 33  
 import org.seasar.cubby.converter.Converter;
 34  
 import org.seasar.cubby.converter.impl.ConversionHelperImpl;
 35  
 import org.seasar.cubby.internal.controller.ConversionFailure;
 36  
 import org.seasar.cubby.internal.controller.RequestParameterBinder;
 37  
 import org.seasar.cubby.internal.util.StringUtils;
 38  
 import org.seasar.cubby.spi.ConverterProvider;
 39  
 import org.seasar.cubby.spi.ProviderFactory;
 40  
 import org.seasar.cubby.spi.beans.Attribute;
 41  
 import org.seasar.cubby.spi.beans.BeanDesc;
 42  
 import org.seasar.cubby.spi.beans.BeanDescFactory;
 43  
 import org.seasar.cubby.spi.beans.ParameterizedClassDesc;
 44  
 
 45  
 /**
 46  
  * 要求パラメータをオブジェクトへバインドするクラスの実装です。
 47  
  * 
 48  
  * @author baba
 49  
  */
 50  12
 public class RequestParameterBinderImpl implements RequestParameterBinder {
 51  
 
 52  
         /** 変換のヘルパクラス。 */
 53  12
         private final ConversionHelper conversionHelper = new ConversionHelperImpl();
 54  
 
 55  
         /**
 56  
          * {@inheritDoc}
 57  
          */
 58  
         public List<ConversionFailure> bind(
 59  
                         final Map<String, Object[]> parameterMap, final Object dest,
 60  
                         final ActionContext actionContext) {
 61  10
                 final List<ConversionFailure> conversionFailures = new ArrayList<ConversionFailure>();
 62  10
                 if (parameterMap == null || parameterMap.isEmpty()) {
 63  1
                         return conversionFailures;
 64  
                 }
 65  
 
 66  9
                 final ConverterProvider converterProvider = ProviderFactory
 67  
                                 .get(ConverterProvider.class);
 68  9
                 final BeanDesc beanDesc = BeanDescFactory.getBeanDesc(dest.getClass());
 69  
                 final Collection<Attribute> attributes;
 70  9
                 if (actionContext.isBindRequestParameterToAllProperties()) {
 71  9
                         attributes = new ArrayList<Attribute>();
 72  9
                         attributes.addAll(beanDesc.findtPropertyAttributes());
 73  9
                         attributes.addAll(beanDesc
 74  
                                         .findAttributesAnnotatedWith(RequestParameter.class));
 75  
                 } else {
 76  0
                         attributes = beanDesc
 77  
                                         .findAttributesAnnotatedWith(RequestParameter.class);
 78  
                 }
 79  
 
 80  9
                 for (final Attribute attribute : attributes) {
 81  134
                         final RequestParameter requestParameter = attribute
 82  
                                         .getAnnotation(RequestParameter.class);
 83  
 
 84  
                         final String parameterName;
 85  134
                         if (requestParameter != null
 86  
                                         && !StringUtils.isEmpty(requestParameter.name())) {
 87  4
                                 parameterName = requestParameter.name();
 88  
                         } else {
 89  130
                                 parameterName = attribute.getName();
 90  
                         }
 91  
 
 92  134
                         if (!parameterMap.containsKey(parameterName)) {
 93  29
                                 continue;
 94  
                         }
 95  
 
 96  105
                         final Object[] parameterValue = parameterMap.get(parameterName);
 97  
 
 98  
                         final Class<? extends Converter> converterType;
 99  105
                         if (requestParameter != null) {
 100  8
                                 converterType = requestParameter.converter();
 101  
                         } else {
 102  97
                                 converterType = null;
 103  
                         }
 104  
 
 105  105
                         final Object value = convert(converterProvider, parameterValue,
 106  
                                         attribute.getType(), attribute.getParameterizedClassDesc(),
 107  
                                         converterType, parameterName, conversionFailures);
 108  
 
 109  105
                         attribute.setValue(dest, value);
 110  105
                 }
 111  
 
 112  9
                 return conversionFailures;
 113  
         }
 114  
 
 115  
         /**
 116  
          * 指定された要求パラメータの値を出力先のプロパティの型に変換します。
 117  
          * 
 118  
          * @param converterProvider
 119  
          *            コンバータプロバイダ
 120  
          * @param values
 121  
          *            要求パラメータの値
 122  
          * @param type
 123  
          *            変換する型
 124  
          * @param parameterizedClassDesc
 125  
          *            パラメタ化された型の情報
 126  
          * @param converterType
 127  
          *            コンバータの型
 128  
          * @param parameterName
 129  
          *            パラメータ名
 130  
          * @param 型変換失敗のリスト
 131  
          * @return 変換された値
 132  
          */
 133  
         private Object convert(final ConverterProvider converterProvider,
 134  
                         final Object[] values, final Class<?> destClass,
 135  
                         final ParameterizedClassDesc parameterizedClassDesc,
 136  
                         final Class<? extends Converter> converterType,
 137  
                         final String parameterName,
 138  
                         final List<ConversionFailure> conversionFailures) {
 139  
 
 140  
                 final Converter converter;
 141  105
                 if (converterType != null && !converterType.equals(Converter.class)) {
 142  4
                         converter = converterProvider.getConverter(converterType);
 143  
                 } else {
 144  101
                         final Class<?> componentType = values.getClass().getComponentType();
 145  101
                         converter = converterProvider
 146  
                                         .getConverter(componentType, destClass);
 147  
                 }
 148  105
                 if (converter != null) {
 149  
                         try {
 150  50
                                 return converter.convertToObject(values[0], destClass,
 151  
                                                 conversionHelper);
 152  19
                         } catch (final ConversionException e) {
 153  19
                                 final FieldInfo fieldInfo = new FieldInfo(parameterName);
 154  19
                                 final MessageInfo messageInfo = e.getMessageInfo();
 155  19
                                 final ConversionFailure conversionFaiure = new ConversionFailure(
 156  
                                                 parameterName, messageInfo, fieldInfo);
 157  19
                                 conversionFailures.add(conversionFaiure);
 158  19
                                 return null;
 159  
                         }
 160  
                 }
 161  
 
 162  55
                 if (destClass.isArray()) {
 163  46
                         return convertToArray(converterProvider, values, destClass
 164  
                                         .getComponentType(), parameterName, conversionFailures);
 165  
                 }
 166  9
                 if (List.class.isAssignableFrom(destClass)) {
 167  3
                         final List<Object> list = new ArrayList<Object>();
 168  3
                         convertToCollection(converterProvider, values, list, destClass,
 169  
                                         parameterizedClassDesc, parameterName, conversionFailures);
 170  3
                         return list;
 171  
                 }
 172  6
                 if (Set.class.isAssignableFrom(destClass)) {
 173  1
                         final Set<Object> set = new LinkedHashSet<Object>();
 174  1
                         convertToCollection(converterProvider, values, set, destClass,
 175  
                                         parameterizedClassDesc, parameterName, conversionFailures);
 176  1
                         return set;
 177  
                 }
 178  
 
 179  
                 try {
 180  5
                         return convertToScalar(converterProvider, values[0], destClass);
 181  0
                 } catch (final ConversionException e) {
 182  0
                         final FieldInfo fieldInfo = new FieldInfo(parameterName);
 183  0
                         final MessageInfo messageInfo = e.getMessageInfo();
 184  0
                         final ConversionFailure conversionFaiure = new ConversionFailure(
 185  
                                         parameterName, messageInfo, fieldInfo);
 186  0
                         conversionFailures.add(conversionFaiure);
 187  0
                         return null;
 188  
                 }
 189  
         }
 190  
 
 191  
         /**
 192  
          * 指定された値を指定された要素の型の配列に変換します。
 193  
          * 
 194  
          * @param converterFactory
 195  
          *            コンバータプロバイダ
 196  
          * @param values
 197  
          *            変換する値
 198  
          * @param componentType
 199  
          *            要素の型
 200  
          * @param parameterName
 201  
          *            パラメータ名
 202  
          * @param conversionFailures
 203  
          *            型変換失敗のリスト
 204  
          * @return 変換後の値
 205  
          */
 206  
         private Object convertToArray(final ConverterProvider converterProvider,
 207  
                         final Object[] values, final Class<?> componentType,
 208  
                         final String parameterName,
 209  
                         final List<ConversionFailure> conversionFailures) {
 210  46
                 final Object dest = Array.newInstance(componentType, values.length);
 211  139
                 for (int i = 0; i < values.length; i++) {
 212  
                         try {
 213  93
                                 final Object convertedValue = convertToScalar(
 214  
                                                 converterProvider, values[i], componentType);
 215  74
                                 Array.set(dest, i, convertedValue);
 216  19
                         } catch (final ConversionException e) {
 217  19
                                 final FieldInfo fieldInfo = new FieldInfo(parameterName, i);
 218  19
                                 final MessageInfo messageInfo = e.getMessageInfo();
 219  19
                                 final ConversionFailure conversionFaiure = new ConversionFailure(
 220  
                                                 parameterName, messageInfo, fieldInfo);
 221  19
                                 conversionFailures.add(conversionFaiure);
 222  74
                         }
 223  
                 }
 224  46
                 return dest;
 225  
         }
 226  
 
 227  
         /**
 228  
          * 指定された値を変換してコレクションに追加します。
 229  
          * 
 230  
          * @param converterProvider
 231  
          *            コンバータプロバイダ
 232  
          * @param values
 233  
          *            変換する値
 234  
          * @param collection
 235  
          *            コレクション
 236  
          * @param type
 237  
          *            変換する型
 238  
          * @param parameterizedClassDesc
 239  
          *            パラメタ化された型の情報
 240  
          * @param parameterName
 241  
          *            パラメータ名
 242  
          * @param conversionFailures
 243  
          *            型変換失敗のリスト
 244  
          */
 245  
         private void convertToCollection(final ConverterProvider converterProvider,
 246  
                         final Object[] values, final Collection<Object> collection,
 247  
                         final Class<?> type,
 248  
                         final ParameterizedClassDesc parameterizedClassDesc,
 249  
                         final String parameterName,
 250  
                         final List<ConversionFailure> conversionFailures) {
 251  4
                 if (parameterizedClassDesc != null
 252  
                                 && parameterizedClassDesc.isParameterizedClass()) {
 253  4
                         final Class<?> destElementType = parameterizedClassDesc
 254  
                                         .getArguments()[0].getRawClass();
 255  12
                         for (int i = 0; i < values.length; i++) {
 256  8
                                 final Object value = values[i];
 257  
                                 try {
 258  8
                                         final Object convertedValue = convertToScalar(
 259  
                                                         converterProvider, value, destElementType);
 260  8
                                         collection.add(convertedValue);
 261  0
                                 } catch (final ConversionException e) {
 262  0
                                         collection.add(null);
 263  0
                                         final FieldInfo fieldInfo = new FieldInfo(parameterName, i);
 264  0
                                         final MessageInfo messageInfo = e.getMessageInfo();
 265  0
                                         final ConversionFailure conversionFaiure = new ConversionFailure(
 266  
                                                         parameterName, messageInfo, fieldInfo);
 267  0
                                         conversionFailures.add(conversionFaiure);
 268  8
                                 }
 269  
                         }
 270  4
                 } else {
 271  0
                         for (final Object value : values) {
 272  0
                                 collection.add(value);
 273  
                         }
 274  
                 }
 275  4
         }
 276  
 
 277  
         /**
 278  
          * 指定された値を指定された型に変換します。
 279  
          * 
 280  
          * @param converterProvider
 281  
          *            コンバータプロバイダ
 282  
          * @param value
 283  
          *            変換する値
 284  
          * @param destClass
 285  
          *            変換する型
 286  
          * @return 変換後の値
 287  
          * @throws ConversionException
 288  
          *             型変換に失敗した場合
 289  
          */
 290  
         private Object convertToScalar(final ConverterProvider converterProvider,
 291  
                         final Object value, final Class<?> destClass)
 292  
                         throws ConversionException {
 293  106
                 if (value == null) {
 294  1
                         return null;
 295  
                 }
 296  105
                 if (destClass.isAssignableFrom(value.getClass())) {
 297  10
                         return value;
 298  
                 }
 299  95
                 final Converter converter = converterProvider.getConverter(value
 300  
                                 .getClass(), destClass);
 301  95
                 if (converter == null) {
 302  0
                         return null;
 303  
                 }
 304  95
                 return converter.convertToObject(value, destClass, conversionHelper);
 305  
         }
 306  
 
 307  
 }