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