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.Collection;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.NoSuchElementException;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29
30 import javax.el.ValueExpression;
31 import javax.faces.application.ProjectStage;
32 import javax.faces.context.FacesContext;
33 import javax.faces.model.SelectItem;
34
35
36
37
38
39
40
41
42
43
44 class _SelectItemsIterator implements Iterator<SelectItem>
45 {
46
47 private static final Logger log = Logger.getLogger(_SelectItemsIterator.class.getName());
48
49 private static final Iterator<UIComponent> _EMPTY_UICOMPONENT_ITERATOR = new _EmptyIterator<UIComponent>();
50
51
52 private static final String VAR_ATTR = "var";
53 private static final String ITEM_VALUE_ATTR = "itemValue";
54 private static final String ITEM_LABEL_ATTR = "itemLabel";
55 private static final String ITEM_DESCRIPTION_ATTR = "itemDescription";
56 private static final String ITEM_DISABLED_ATTR = "itemDisabled";
57 private static final String ITEM_LABEL_ESCAPED_ATTR = "itemLabelEscaped";
58 private static final String NO_SELECTION_VALUE_ATTR = "noSelectionValue";
59
60 private final Iterator<UIComponent> _children;
61 private Iterator<? extends Object> _nestedItems;
62 private SelectItem _nextItem;
63 private UISelectItems _currentUISelectItems;
64 private FacesContext _facesContext;
65
66 public _SelectItemsIterator(UIComponent selectItemsParent, FacesContext facesContext)
67 {
68 _children = selectItemsParent.getChildCount() > 0 ? selectItemsParent.getChildren().iterator() : _EMPTY_UICOMPONENT_ITERATOR;
69 _facesContext = facesContext;
70 }
71
72 @SuppressWarnings("unchecked")
73 public boolean hasNext()
74 {
75 if (_nextItem != null)
76 {
77 return true;
78 }
79 if (_nestedItems != null)
80 {
81 if (_nestedItems.hasNext())
82 {
83 return true;
84 }
85 _nestedItems = null;
86 }
87 if (_children.hasNext())
88 {
89 UIComponent child = _children.next();
90
91
92
93
94
95
96 while (!(child instanceof UISelectItem) && !(child instanceof UISelectItems))
97 {
98
99 if (_children.hasNext())
100 {
101
102 child = _children.next();
103 }
104 else
105 {
106
107
108 return false;
109 }
110 }
111 if (child instanceof UISelectItem)
112 {
113 UISelectItem uiSelectItem = (UISelectItem) child;
114 Object item = uiSelectItem.getValue();
115 if (item == null)
116 {
117
118 Object itemValue = uiSelectItem.getItemValue();
119 String label = uiSelectItem.getItemLabel();
120 String description = uiSelectItem.getItemDescription();
121 boolean disabled = uiSelectItem.isItemDisabled();
122 boolean escape = uiSelectItem.isItemEscaped();
123 boolean noSelectionOption = uiSelectItem.isNoSelectionOption();
124 if (label == null)
125 {
126 label = itemValue.toString();
127 }
128 item = new SelectItem(itemValue, label, description, disabled, escape, noSelectionOption);
129 }
130 else if (!(item instanceof SelectItem))
131 {
132 ValueExpression expression = uiSelectItem.getValueExpression("value");
133 throw new IllegalArgumentException("ValueExpression '"
134 + (expression == null ? null : expression.getExpressionString()) + "' of UISelectItem : "
135 + getPathToComponent(child) + " does not reference an Object of type SelectItem");
136 }
137 _nextItem = (SelectItem) item;
138 return true;
139 }
140 else if (child instanceof UISelectItems)
141 {
142 _currentUISelectItems = ((UISelectItems) child);
143 Object value = _currentUISelectItems.getValue();
144
145 if (value instanceof SelectItem)
146 {
147 _nextItem = (SelectItem) value;
148 return true;
149 }
150 else if (value != null && value.getClass().isArray())
151 {
152
153
154 final int length = Array.getLength(value);
155 Collection<Object> items = new ArrayList<Object>(length);
156 for (int i = 0; i < length; i++)
157 {
158 items.add(Array.get(value, i));
159 }
160 _nestedItems = items.iterator();
161 return hasNext();
162 }
163 else if (value instanceof Iterable)
164 {
165
166 _nestedItems = ((Iterable<?>) value).iterator();
167 return hasNext();
168 }
169 else if (value instanceof Map)
170 {
171 Map<Object, Object> map = ((Map<Object, Object>) value);
172 Collection<SelectItem> items = new ArrayList<SelectItem>(map.size());
173 for (Map.Entry<Object, Object> entry : map.entrySet())
174 {
175 items.add(new SelectItem(entry.getValue(), entry.getKey().toString()));
176 }
177
178 _nestedItems = items.iterator();
179 return hasNext();
180 }
181 else
182 {
183 Level level = Level.FINE;
184 if (!_facesContext.isProjectStage(ProjectStage.Production))
185 {
186 level = Level.WARNING;
187 }
188
189 if (log.isLoggable(level))
190 {
191 ValueExpression expression = _currentUISelectItems.getValueExpression("value");
192 log.log(level, "ValueExpression {0} of UISelectItems with component-path {1}"
193 + " does not reference an Object of type SelectItem,"
194 + " array, Iterable or Map, but of type: {2}",
195 new Object[] {
196 (expression == null ? null : expression.getExpressionString()),
197 getPathToComponent(child),
198 (value == null ? null : value.getClass().getName())
199 });
200 }
201 }
202 }
203 }
204 return false;
205 }
206
207 public SelectItem next()
208 {
209 if (!hasNext())
210 {
211 throw new NoSuchElementException();
212 }
213 if (_nextItem != null)
214 {
215 SelectItem value = _nextItem;
216 _nextItem = null;
217 return value;
218 }
219 if (_nestedItems != null)
220 {
221 Object item = _nestedItems.next();
222
223 if (!(item instanceof SelectItem))
224 {
225
226
227
228 Map<String, Object> attributeMap = _currentUISelectItems.getAttributes();
229
230
231 boolean wroteRequestMapVarValue = false;
232 Object oldRequestMapVarValue = null;
233 final String var = (String) attributeMap.get(VAR_ATTR);
234 if(var != null && !"".equals(var))
235 {
236
237 oldRequestMapVarValue = _facesContext.getExternalContext().getRequestMap().put(var, item);
238 wroteRequestMapVarValue = true;
239 }
240
241
242 Object itemValue = attributeMap.get(ITEM_VALUE_ATTR);
243 if (itemValue == null)
244 {
245
246
247 itemValue = item;
248 }
249
250
251
252 Object itemLabel = attributeMap.get(ITEM_LABEL_ATTR);
253 if (itemLabel == null)
254 {
255 itemLabel = itemValue.toString();
256 }
257 else
258 {
259 itemLabel = itemLabel.toString();
260 }
261 Object itemDescription = attributeMap.get(ITEM_DESCRIPTION_ATTR);
262 if (itemDescription != null)
263 {
264 itemDescription = itemDescription.toString();
265 }
266 Boolean itemDisabled = getBooleanAttribute(_currentUISelectItems, ITEM_DISABLED_ATTR, false);
267 Boolean itemLabelEscaped = getBooleanAttribute(_currentUISelectItems, ITEM_LABEL_ESCAPED_ATTR, true);
268 Object noSelectionValue = attributeMap.get(NO_SELECTION_VALUE_ATTR);
269 item = new SelectItem(itemValue,
270 (String) itemLabel,
271 (String) itemDescription,
272 itemDisabled,
273 itemLabelEscaped,
274 itemValue.equals(noSelectionValue));
275
276
277 if(wroteRequestMapVarValue)
278 {
279
280 if (oldRequestMapVarValue != null)
281 {
282 _facesContext.getExternalContext()
283 .getRequestMap().put(var, oldRequestMapVarValue);
284 }
285 else
286 {
287 _facesContext.getExternalContext()
288 .getRequestMap().remove(var);
289 }
290 }
291 }
292 return (SelectItem) item;
293 }
294 throw new NoSuchElementException();
295 }
296
297 public void remove()
298 {
299 throw new UnsupportedOperationException();
300 }
301
302 private boolean getBooleanAttribute(UIComponent component, String attrName, boolean defaultValue)
303 {
304 Object value = component.getAttributes().get(attrName);
305 if (value == null)
306 {
307 return defaultValue;
308 }
309 else if (value instanceof Boolean)
310 {
311 return (Boolean) value;
312 }
313 else
314 {
315
316
317
318 return Boolean.valueOf(value.toString());
319 }
320 }
321
322 private String getPathToComponent(UIComponent component)
323 {
324 StringBuffer buf = new StringBuffer();
325
326 if (component == null)
327 {
328 buf.append("{Component-Path : ");
329 buf.append("[null]}");
330 return buf.toString();
331 }
332
333 getPathToComponent(component, buf);
334
335 buf.insert(0, "{Component-Path : ");
336 buf.append("}");
337
338 return buf.toString();
339 }
340
341 private void getPathToComponent(UIComponent component, StringBuffer buf)
342 {
343 if (component == null)
344 {
345 return;
346 }
347
348 StringBuffer intBuf = new StringBuffer();
349
350 intBuf.append("[Class: ");
351 intBuf.append(component.getClass().getName());
352 if (component instanceof UIViewRoot)
353 {
354 intBuf.append(",ViewId: ");
355 intBuf.append(((UIViewRoot) component).getViewId());
356 }
357 else
358 {
359 intBuf.append(",Id: ");
360 intBuf.append(component.getId());
361 }
362 intBuf.append("]");
363
364 buf.insert(0, intBuf);
365
366 getPathToComponent(component.getParent(), buf);
367 }
368 }