1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package javax.faces.component;
20
21 import java.lang.reflect.Array;
22 import java.lang.reflect.Method;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.LinkedList;
29 import java.util.Queue;
30 import java.util.Set;
31 import java.util.SortedSet;
32 import java.util.TreeSet;
33
34 import javax.el.ValueExpression;
35 import javax.faces.FacesException;
36 import javax.faces.context.FacesContext;
37 import javax.faces.convert.Converter;
38 import javax.faces.convert.ConverterException;
39 import javax.faces.model.SelectItem;
40 import javax.faces.model.SelectItemGroup;
41
42
43
44
45
46
47 class _SharedRendererUtils
48 {
49 static final String COLLECTION_TYPE_KEY = "collectionType";
50 static final String VALUE_TYPE_KEY = "valueType";
51
52 static Converter findUIOutputConverter(FacesContext facesContext,
53 UIOutput component)
54 {
55
56
57
58
59 Converter converter = component.getConverter();
60 if (converter != null)
61 {
62 return converter;
63 }
64
65
66 ValueExpression expression = component.getValueExpression("value");
67 if (expression == null)
68 {
69 return null;
70 }
71
72 Class<?> valueType = expression.getType(facesContext.getELContext());
73 if (valueType == null)
74 {
75 return null;
76 }
77
78 if (Object.class.equals(valueType))
79 {
80 return null;
81 }
82
83 try
84 {
85 return facesContext.getApplication().createConverter(valueType);
86 }
87 catch (FacesException e)
88 {
89 log(facesContext, "No Converter for type " + valueType.getName()
90 + " found", e);
91 return null;
92 }
93 }
94
95 static Object getConvertedUISelectManyValue(FacesContext facesContext, UISelectMany component,
96 String[] submittedValue) throws ConverterException
97 {
98 return getConvertedUISelectManyValue(facesContext, component,
99 submittedValue, false);
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114 static Object getConvertedUISelectManyValue(FacesContext facesContext, UISelectMany component,
115 String[] submittedValue, boolean considerValueType) throws ConverterException
116 {
117
118
119
120
121 if (submittedValue == null)
122 {
123 throw new NullPointerException("submittedValue");
124 }
125
126 ValueExpression expression = component.getValueExpression("value");
127 Object targetForConvertedValues = null;
128
129
130 Converter converter = component.getConverter();
131
132 if (converter == null && considerValueType)
133 {
134
135 converter = getValueTypeConverter(facesContext, component);
136 }
137
138 if (expression != null)
139 {
140 Class<?> modelType = expression
141 .getType(facesContext.getELContext());
142 if (modelType == null)
143 {
144
145 return submittedValue;
146 }
147 else if (modelType.isArray())
148 {
149
150 Class<?> componentType = modelType.getComponentType();
151
152
153 if (String.class.equals(componentType))
154 {
155 return submittedValue;
156 }
157 if (converter == null)
158 {
159
160
161 converter = facesContext.getApplication().createConverter(
162 componentType);
163
164 if (converter == null && !Object.class.equals(componentType))
165 {
166
167
168
169
170
171
172 throw new ConverterException(
173 "Could not obtain a Converter for "
174 + componentType.getName());
175 }
176 }
177
178 targetForConvertedValues = Array.newInstance(componentType,
179 submittedValue.length);
180 }
181 else if (Collection.class.isAssignableFrom(modelType) || Object.class.equals(modelType))
182 {
183 if (converter == null)
184 {
185
186 _SelectItemsIterator iterator = new _SelectItemsIterator(component, facesContext);
187 converter = getSelectItemsValueConverter(iterator, facesContext);
188 }
189
190 Object collectionTypeAttr = component.getAttributes().get(
191 COLLECTION_TYPE_KEY);
192 if (collectionTypeAttr != null)
193 {
194 Class<?> collectionType = getClassFromAttribute(facesContext, collectionTypeAttr);
195 if (collectionType == null)
196 {
197 throw new FacesException(
198 "The attribute "
199 + COLLECTION_TYPE_KEY
200 + " of component "
201 + component.getClientId(facesContext)
202 + " does not evaluate to a "
203 + "String, a Class object or a ValueExpression pointing "
204 + "to a String or a Class object.");
205 }
206
207 if (!Collection.class.isAssignableFrom(collectionType))
208 {
209 throw new FacesException("The attribute "
210 + COLLECTION_TYPE_KEY + " of component "
211 + component.getClientId(facesContext)
212 + " does not point to a valid type of Collection.");
213 }
214
215 try
216 {
217 targetForConvertedValues = collectionType.newInstance();
218 }
219 catch (Exception e)
220 {
221 throw new FacesException("The Collection "
222 + collectionType.getName()
223 + "can not be instantiated.", e);
224 }
225 }
226 else if (Collection.class.isAssignableFrom(modelType))
227 {
228
229 Collection<?> componentValue = (Collection<?>) component
230 .getValue();
231
232 if (componentValue instanceof Cloneable)
233 {
234
235 try
236 {
237 Method cloneMethod = componentValue.getClass()
238 .getMethod("clone");
239 Collection<?> clone = (Collection<?>) cloneMethod
240 .invoke(componentValue);
241 clone.clear();
242 targetForConvertedValues = clone;
243 }
244 catch (Exception e)
245 {
246 log(facesContext, "Could not clone "
247 + componentValue.getClass().getName(), e);
248 }
249 }
250
251
252 if (targetForConvertedValues == null)
253 {
254
255
256 try
257 {
258 targetForConvertedValues = (componentValue != null
259 ? componentValue.getClass()
260 : modelType).newInstance();
261 }
262 catch (Exception e)
263 {
264
265
266 if (SortedSet.class.isAssignableFrom(modelType))
267 {
268 targetForConvertedValues = new TreeSet();
269 }
270 else if (Queue.class.isAssignableFrom(modelType))
271 {
272 targetForConvertedValues = new LinkedList();
273 }
274 else if (Set.class.isAssignableFrom(modelType))
275 {
276 targetForConvertedValues = new HashSet(
277 submittedValue.length);
278 }
279 else
280 {
281 targetForConvertedValues = new ArrayList(
282 submittedValue.length);
283 }
284 }
285 }
286 }
287 else
288 {
289
290
291
292
293 if (converter == null)
294 {
295 return submittedValue;
296 }
297
298 targetForConvertedValues = new Object[submittedValue.length];
299 }
300 }
301 else
302 {
303
304 throw new ConverterException(
305 "ValueExpression for UISelectMany must be of type Collection or Array.");
306 }
307 }
308 else
309 {
310 targetForConvertedValues = new Object[submittedValue.length];
311 }
312
313
314
315 boolean isArray = (targetForConvertedValues.getClass().isArray());
316 for (int i = 0; i < submittedValue.length; i++)
317 {
318
319 Object value;
320 if (converter != null)
321 {
322 value = converter.getAsObject(facesContext, component,
323 submittedValue[i]);
324 }
325 else
326 {
327 value = submittedValue[i];
328 }
329
330 if (isArray)
331 {
332 Array.set(targetForConvertedValues, i, value);
333 }
334 else
335 {
336 ((Collection) targetForConvertedValues).add(value);
337 }
338 }
339
340 return targetForConvertedValues;
341 }
342
343
344
345
346
347
348
349
350
351
352
353
354 static Class<?> getClassFromAttribute(FacesContext facesContext,
355 Object attribute) throws FacesException
356 {
357
358
359
360
361 Class<?> type = null;
362
363
364
365 if (attribute instanceof ValueExpression)
366 {
367
368 attribute = ((ValueExpression) attribute)
369 .getValue(facesContext.getELContext());
370 }
371
372 if (attribute instanceof String)
373 {
374 try
375 {
376 type = Class.forName((String) attribute);
377 }
378 catch (ClassNotFoundException cnfe)
379 {
380 throw new FacesException(
381 "Unable to find class "
382 + attribute
383 + " on the classpath.", cnfe);
384 }
385
386 }
387
388 else if (attribute instanceof Class)
389 {
390 type = (Class<?>) attribute;
391 }
392
393 return type;
394 }
395
396
397
398
399
400
401
402
403
404 static Converter getValueTypeConverter(FacesContext facesContext, UISelectMany component)
405 {
406 Converter converter = null;
407
408 Object valueTypeAttr = component.getAttributes().get(VALUE_TYPE_KEY);
409 if (valueTypeAttr != null)
410 {
411
412 Class<?> valueType = getClassFromAttribute(facesContext, valueTypeAttr);
413 if (valueType == null)
414 {
415 throw new FacesException(
416 "The attribute "
417 + VALUE_TYPE_KEY
418 + " of component "
419 + component.getClientId(facesContext)
420 + " does not evaluate to a "
421 + "String, a Class object or a ValueExpression pointing "
422 + "to a String or a Class object.");
423 }
424
425
426 converter = facesContext.getApplication().createConverter(valueType);
427
428 if (converter == null)
429 {
430 facesContext.getExternalContext().log("Found attribute valueType on component " +
431 _ComponentUtils.getPathToComponent(component) +
432 ", but could not get a by-type converter for type " +
433 valueType.getName());
434 }
435 }
436
437 return converter;
438 }
439
440
441
442
443
444
445
446
447 static Converter getSelectItemsValueConverter(Iterator<SelectItem> iterator, FacesContext facesContext)
448 {
449
450
451
452
453 Converter converter = null;
454 while (converter == null && iterator.hasNext())
455 {
456 SelectItem item = iterator.next();
457 if (item instanceof SelectItemGroup)
458 {
459 Iterator<SelectItem> groupIterator = Arrays.asList(
460 ((SelectItemGroup) item).getSelectItems()).iterator();
461 converter = getSelectItemsValueConverter(groupIterator, facesContext);
462 }
463 else
464 {
465 Class<?> selectItemsType = item.getValue().getClass();
466
467
468 if (String.class.equals(selectItemsType))
469 {
470 return null;
471 }
472
473 try
474 {
475 converter = facesContext.getApplication().createConverter(selectItemsType);
476 }
477 catch (FacesException e)
478 {
479
480 }
481 }
482 }
483 return converter;
484 }
485
486
487
488
489 private static void log(FacesContext context, String msg, Exception e)
490 {
491 context.getExternalContext().log(msg, e);
492 }
493 }