1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.cubby.controller.impl;
17
18 import java.lang.reflect.Array;
19 import java.lang.reflect.Field;
20 import java.lang.reflect.Method;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.LinkedHashSet;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.Map.Entry;
28
29 import org.seasar.cubby.action.Action;
30 import org.seasar.cubby.action.Form;
31 import org.seasar.cubby.action.RequestParameter;
32 import org.seasar.cubby.action.RequestParameterBindingType;
33 import org.seasar.cubby.controller.RequestParameterBinder;
34 import org.seasar.cubby.converter.ConversionHelper;
35 import org.seasar.cubby.converter.Converter;
36 import org.seasar.cubby.converter.ConverterFactory;
37 import org.seasar.cubby.util.CubbyUtils;
38 import org.seasar.framework.beans.BeanDesc;
39 import org.seasar.framework.beans.ParameterizedClassDesc;
40 import org.seasar.framework.beans.PropertyDesc;
41 import org.seasar.framework.beans.factory.BeanDescFactory;
42
43
44
45
46
47
48
49 public class RequestParameterBinderImpl implements RequestParameterBinder {
50
51
52 private ConverterFactory converterFactory;
53
54
55 private ConversionHelper conversionHelper;
56
57
58
59
60
61
62
63 public void setConverterFactory(final ConverterFactory converterFactory) {
64 this.converterFactory = converterFactory;
65 }
66
67
68
69
70
71
72
73 public void setConversionHelper(final ConversionHelper conversionHelper) {
74 this.conversionHelper = conversionHelper;
75 }
76
77
78
79
80 public void bind(final Map<String, Object[]> parameterMap,
81 final Object dest, final Class<? extends Action> actionClass,
82 final Method method) {
83 if (parameterMap == null) {
84 return;
85 }
86 final BeanDesc destBeanDesc = BeanDescFactory.getBeanDesc(dest
87 .getClass());
88 for (final Entry<String, Object[]> entry : parameterMap.entrySet()) {
89 final String sourceName = entry.getKey();
90 if (destBeanDesc.hasPropertyDesc(sourceName)) {
91 final PropertyDesc destPropertyDesc = destBeanDesc
92 .getPropertyDesc(sourceName);
93 if (destPropertyDesc.isReadable()
94 && destPropertyDesc.isWritable()) {
95 if (!isBindToAllProperties(actionClass, method)) {
96 final RequestParameter requestParameter = getRequestParameterAnnotation(destPropertyDesc);
97 if (requestParameter == null) {
98 continue;
99 }
100 }
101
102 try {
103 final Object value = convert(entry.getValue(),
104 destPropertyDesc);
105 destPropertyDesc.setValue(dest, value);
106 } catch (Exception e) {
107 destPropertyDesc.setValue(dest, null);
108 }
109 }
110 }
111 }
112 }
113
114
115
116
117
118
119
120
121
122
123 private Object convert(final Object[] values,
124 final PropertyDesc destPropertyDesc) {
125 final Class<?> destClass = destPropertyDesc.getPropertyType();
126
127 final Converter converter = converterFactory.getConverter(values[0]
128 .getClass(), destClass);
129 if (converter != null) {
130 return converter.convertToObject(values[0], destClass,
131 conversionHelper);
132 }
133
134 if (destClass.isArray()) {
135 return convertToArray(values, destClass.getComponentType());
136 }
137 if (List.class.isAssignableFrom(destClass)) {
138 final List<Object> list = new ArrayList<Object>();
139 convertToCollection(values, list, destPropertyDesc
140 .getParameterizedClassDesc());
141 return list;
142 }
143 if (Set.class.isAssignableFrom(destClass)) {
144 final Set<Object> set = new LinkedHashSet<Object>();
145 convertToCollection(values, set, destPropertyDesc
146 .getParameterizedClassDesc());
147 return set;
148 }
149 return convertToScalar(values[0], destClass);
150 }
151
152
153
154
155
156
157
158
159
160
161 private Object convertToArray(final Object[] values,
162 final Class<?> componentType) {
163 final Object dest = Array.newInstance(componentType, values.length);
164 for (int i = 0; i < values.length; i++) {
165 final Object convertedValue = convertToScalar(values[i],
166 componentType);
167 Array.set(dest, i, convertedValue);
168 }
169 return dest;
170 }
171
172
173
174
175
176
177
178
179
180
181
182 private void convertToCollection(final Object[] values,
183 final Collection<Object> collection,
184 final ParameterizedClassDesc parameterizedClassDesc) {
185 if (parameterizedClassDesc == null) {
186 for (final Object value : values) {
187 collection.add(value);
188 }
189 } else {
190 final Class<?> destElementType = parameterizedClassDesc
191 .getArguments()[0].getRawClass();
192 for (final Object value : values) {
193 final Object convertedValue = convertToScalar(value,
194 destElementType);
195 collection.add(convertedValue);
196 }
197 }
198 }
199
200
201
202
203
204
205
206
207
208
209 private Object convertToScalar(final Object value, final Class<?> destClass) {
210 if (value == null) {
211 return null;
212 }
213 if (destClass.isAssignableFrom(value.getClass())) {
214 return value;
215 }
216 final Converter converter = converterFactory.getConverter(value
217 .getClass(), destClass);
218 if (converter == null) {
219 return null;
220 }
221 return converter.convertToObject(value, destClass, conversionHelper);
222 }
223
224
225
226
227
228
229
230
231
232 private static boolean isBindToAllProperties(
233 final Class<? extends Action> actionClass, final Method method) {
234 final Form form = CubbyUtils.getForm(actionClass, method);
235 if (form == null) {
236 return false;
237 }
238
239 final RequestParameterBindingType type = form.bindingType();
240 switch (type) {
241 case ALL_PROPERTIES:
242 return true;
243 case ONLY_SPECIFIED_PROPERTIES:
244 return false;
245 default:
246 throw new IllegalStateException(type.toString());
247 }
248 }
249
250
251
252
253
254
255
256
257
258 private static RequestParameter getRequestParameterAnnotation(
259 final PropertyDesc propertyDesc) {
260 final RequestParameter request;
261 if (propertyDesc.hasWriteMethod()) {
262 final Method method = propertyDesc.getWriteMethod();
263 if (method.isAnnotationPresent(RequestParameter.class)) {
264 request = method.getAnnotation(RequestParameter.class);
265 } else {
266 final Field field = propertyDesc.getField();
267 request = field.getAnnotation(RequestParameter.class);
268 }
269 } else {
270 final Field field = propertyDesc.getField();
271 request = field.getAnnotation(RequestParameter.class);
272 }
273 return request;
274 }
275
276 }