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.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.Iterator;
27
28 import javax.el.ValueExpression;
29 import javax.faces.application.FacesMessage;
30 import javax.faces.context.ExternalContext;
31 import javax.faces.context.FacesContext;
32 import javax.faces.convert.Converter;
33 import javax.faces.convert.ConverterException;
34 import javax.faces.el.ValueBinding;
35 import javax.faces.model.SelectItem;
36 import javax.faces.render.Renderer;
37
38 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
39 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperties;
40 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 @JSFComponent(defaultRendererType = "javax.faces.Listbox")
56 @JSFJspProperties
57 (properties={
58 @JSFJspProperty(name="hideNoSelectionOption", returnType="boolean"),
59 @JSFJspProperty(name="collectionType", returnType="java.lang.String")
60 }
61 )
62 public class UISelectMany extends UIInput
63 {
64 public static final String COMPONENT_TYPE = "javax.faces.SelectMany";
65 public static final String COMPONENT_FAMILY = "javax.faces.SelectMany";
66
67 public static final String INVALID_MESSAGE_ID = "javax.faces.component.UISelectMany.INVALID";
68
69 public UISelectMany()
70 {
71 setRendererType("javax.faces.Listbox");
72 }
73
74 @Override
75 public String getFamily()
76 {
77 return COMPONENT_FAMILY;
78 }
79
80 public Object[] getSelectedValues()
81 {
82 return (Object[]) getValue();
83 }
84
85 public void setSelectedValues(Object[] selectedValues)
86 {
87 setValue(selectedValues);
88 }
89
90
91
92
93 @Override
94 public ValueBinding getValueBinding(String name)
95 {
96 if (name == null)
97 {
98 throw new NullPointerException("name");
99 }
100 if (name.equals("selectedValues"))
101 {
102 return super.getValueBinding("value");
103 }
104 else
105 {
106 return super.getValueBinding(name);
107 }
108 }
109
110
111
112
113 @Override
114 public void setValueBinding(String name, ValueBinding binding)
115 {
116 if (name == null)
117 {
118 throw new NullPointerException("name");
119 }
120 if (name.equals("selectedValues"))
121 {
122 super.setValueBinding("value", binding);
123 }
124 else
125 {
126 super.setValueBinding(name, binding);
127 }
128 }
129
130 @Override
131 public ValueExpression getValueExpression(String name)
132 {
133 if (name == null)
134 {
135 throw new NullPointerException("name");
136 }
137 if (name.equals("selectedValues"))
138 {
139 return super.getValueExpression("value");
140 }
141 else
142 {
143 return super.getValueExpression(name);
144 }
145 }
146
147 @Override
148 public void setValueExpression(String name, ValueExpression binding)
149 {
150 if (name == null)
151 {
152 throw new NullPointerException("name");
153 }
154 if (name.equals("selectedValues"))
155 {
156 super.setValueExpression("value", binding);
157 }
158 else
159 {
160 super.setValueExpression(name, binding);
161 }
162 }
163
164
165
166
167 @Override
168 protected boolean compareValues(Object previous, Object value)
169 {
170 if (previous == null)
171 {
172
173 return value != null;
174 }
175 else if (value == null)
176 {
177
178 return true;
179 }
180 else
181 {
182 if (previous instanceof Object[] && value instanceof Object[])
183 {
184 return compareObjectArrays((Object[]) previous, (Object[]) value);
185 }
186 else if (previous instanceof Collection && value instanceof Collection)
187 {
188 return compareCollections((Collection<?>) previous, (Collection<?>) value);
189 }
190 else if (previous.getClass().isArray() && value.getClass().isArray())
191 {
192 return comparePrimitiveArrays(previous, value);
193 }
194 else
195 {
196
197 return true;
198 }
199 }
200 }
201
202 private boolean compareObjectArrays(Object[] previous, Object[] value)
203 {
204 int length = value.length;
205 if (previous.length != length)
206 {
207
208 return true;
209 }
210
211 boolean[] scoreBoard = new boolean[length];
212 for (int i = 0; i < length; i++)
213 {
214 Object p = previous[i];
215 boolean found = false;
216 for (int j = 0; j < length; j++)
217 {
218 if (scoreBoard[j] == false)
219 {
220 Object v = value[j];
221 if ((p == null && v == null) || (p != null && v != null && p.equals(v)))
222 {
223 scoreBoard[j] = true;
224 found = true;
225 break;
226 }
227 }
228 }
229 if (!found)
230 {
231 return true;
232 }
233 }
234
235 return false;
236 }
237
238 private boolean compareCollections(Collection<?> previous, Collection<?> value)
239 {
240 int length = value.size();
241 if (previous.size() != length)
242 {
243
244 return true;
245 }
246
247 boolean[] scoreBoard = new boolean[length];
248 for (Iterator<?> itPrevious = previous.iterator(); itPrevious.hasNext();)
249 {
250 Object p = itPrevious.next();
251 boolean found = false;
252 int j = 0;
253 for (Iterator<?> itValue = value.iterator(); itValue.hasNext(); j++)
254 {
255 Object v = itValue.next();
256 if (scoreBoard[j] == false)
257 {
258 if ((p == null && v == null) || (p != null && v != null && p.equals(v)))
259 {
260 scoreBoard[j] = true;
261 found = true;
262 break;
263 }
264 }
265 }
266 if (!found)
267 {
268 return true;
269 }
270 }
271
272 return false;
273 }
274
275 private boolean comparePrimitiveArrays(Object previous, Object value)
276 {
277 int length = Array.getLength(value);
278 if (Array.getLength(previous) != length)
279 {
280
281 return true;
282 }
283
284 boolean[] scoreBoard = new boolean[length];
285 for (int i = 0; i < length; i++)
286 {
287 Object p = Array.get(previous, i);
288 boolean found = false;
289 for (int j = 0; j < length; j++)
290 {
291 if (scoreBoard[j] == false)
292 {
293 Object v = Array.get(value, j);
294 if ((p == null && v == null) || (p != null && v != null && p.equals(v)))
295 {
296 scoreBoard[j] = true;
297 found = true;
298 break;
299 }
300 }
301 }
302 if (!found)
303 {
304 return true;
305 }
306 }
307
308 return false;
309 }
310
311 @Override
312 protected void validateValue(FacesContext context, Object convertedValue)
313 {
314 Iterator<?> itemValues = _createItemValuesIterator(convertedValue);
315
316
317 if (itemValues == null)
318 {
319 _MessageUtils.addErrorMessage(context, this, INVALID_MESSAGE_ID, new Object[] { _MessageUtils.getLabel(
320 context, this) });
321 setValid(false);
322 return;
323 }
324
325 boolean hasValues = itemValues.hasNext();
326
327
328 if (isRequired() && !hasValues)
329 {
330 if (getRequiredMessage() != null)
331 {
332 String requiredMessage = getRequiredMessage();
333 context.addMessage(this.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR,
334 requiredMessage, requiredMessage));
335 }
336 else
337 {
338 _MessageUtils.addErrorMessage(context, this, REQUIRED_MESSAGE_ID,
339 new Object[] { _MessageUtils.getLabel(context, this) });
340 }
341 setValid(false);
342 return;
343 }
344
345
346
347 if (hasValues || shouldValidateEmptyFields(context))
348 {
349 _ComponentUtils.callValidators(context, this, convertedValue);
350 }
351
352 if (isValid() && hasValues)
353 {
354
355
356 Collection<SelectItem> items = new ArrayList<SelectItem>();
357 for (Iterator<SelectItem> iter = new _SelectItemsIterator(this, context); iter.hasNext();)
358 {
359 items.add(iter.next());
360 }
361 Converter converter = getConverter();
362 while (itemValues.hasNext())
363 {
364 Object itemValue = itemValues.next();
365
366
367
368 if (!_SelectItemsUtil.matchValue(context, this, itemValue, items.iterator(), converter)
369 || (
370 this.isRequired()
371 && _SelectItemsUtil.isNoSelectionOption(context, this, itemValue,
372 items.iterator(), converter)
373 ))
374 {
375 _MessageUtils.addErrorMessage(context, this, INVALID_MESSAGE_ID,
376 new Object[] { _MessageUtils.getLabel(context, this) });
377 setValid(false);
378 return;
379 }
380 }
381 }
382 }
383
384 @Override
385 protected Object getConvertedValue(FacesContext context, Object submittedValue) throws ConverterException
386 {
387 Renderer renderer = getRenderer(context);
388 if (renderer != null)
389 {
390 return renderer.getConvertedValue(context, this, submittedValue);
391 }
392 else if (submittedValue == null)
393 {
394 return null;
395 }
396 else if (submittedValue instanceof String[])
397 {
398 return _SharedRendererUtils.getConvertedUISelectManyValue(context, this, (String[]) submittedValue);
399 }
400 return submittedValue;
401 }
402
403 private Iterator<?> _createItemValuesIterator(Object convertedValue)
404 {
405 if (convertedValue == null)
406 {
407 return Collections.emptyList().iterator();
408 }
409 else
410 {
411 Class<?> valueClass = convertedValue.getClass();
412 if (valueClass.isArray())
413 {
414 return new _PrimitiveArrayIterator(convertedValue);
415 }
416 else if (convertedValue instanceof Object[])
417 {
418 Object[] values = (Object[]) convertedValue;
419 return Arrays.asList(values).iterator();
420 }
421 else if (convertedValue instanceof Collection)
422 {
423 Collection<?> values = (Collection<?>) convertedValue;
424 return values.iterator();
425 }
426 else
427 {
428
429 return null;
430 }
431 }
432 }
433
434
435 private boolean shouldValidateEmptyFields(FacesContext context)
436 {
437 ExternalContext ec = context.getExternalContext();
438 Boolean validateEmptyFields = (Boolean) ec.getApplicationMap().get(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
439
440 if (validateEmptyFields == null)
441 {
442 String param = ec.getInitParameter(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
443
444
445 if (param == null)
446 {
447 param = "auto";
448 }
449 else
450 {
451
452 param = param.toLowerCase();
453 }
454
455 if (param.equals("auto") && _ExternalSpecifications.isBeanValidationAvailable())
456 {
457 validateEmptyFields = true;
458 }
459 else if (param.equals("true"))
460 {
461 validateEmptyFields = true;
462 }
463 else
464 {
465 validateEmptyFields = false;
466 }
467
468
469 ec.getApplicationMap().put(VALIDATE_EMPTY_FIELDS_PARAM_NAME, validateEmptyFields);
470 }
471
472 return validateEmptyFields;
473 }
474 }