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