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 class _SelectItemsIterator implements Iterator<SelectItem>
40 {
41
42 private static final Logger log = Logger.getLogger(_SelectItemsIterator.class.getName());
43
44 private static final Iterator<UIComponent> _EMPTY_UICOMPONENT_ITERATOR = new _EmptyIterator<UIComponent>();
45
46
47 private static final String VAR_ATTR = "var";
48 private static final String ITEM_VALUE_ATTR = "itemValue";
49 private static final String ITEM_LABEL_ATTR = "itemLabel";
50 private static final String ITEM_DESCRIPTION_ATTR = "itemDescription";
51 private static final String ITEM_DISABLED_ATTR = "itemDisabled";
52 private static final String ITEM_LABEL_ESCAPED_ATTR = "itemLabelEscaped";
53 private static final String NO_SELECTION_VALUE_ATTR = "noSelectionValue";
54
55 private final Iterator<UIComponent> _children;
56 private Iterator<?> _nestedItems;
57 private SelectItem _nextItem;
58 private UIComponent _currentComponent;
59 private UISelectItems _currentUISelectItems;
60 private FacesContext _facesContext;
61
62 public _SelectItemsIterator(UIComponent selectItemsParent, FacesContext facesContext)
63 {
64 _children = selectItemsParent.getChildCount() > 0
65 ? selectItemsParent.getChildren().iterator()
66 : _EMPTY_UICOMPONENT_ITERATOR;
67 _facesContext = facesContext;
68 }
69
70 @Override
71 @SuppressWarnings("unchecked")
72 public boolean hasNext()
73 {
74 if (_nextItem != null)
75 {
76 return true;
77 }
78 if (_nestedItems != null)
79 {
80 if (_nestedItems.hasNext())
81 {
82 return true;
83 }
84 _nestedItems = null;
85 _currentComponent = 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 && itemValue != 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 _currentComponent = child;
139 return true;
140 }
141 else if (child instanceof UISelectItems)
142 {
143 _currentUISelectItems = ((UISelectItems) child);
144 Object value = _currentUISelectItems.getValue();
145 _currentComponent = child;
146
147 if (value instanceof SelectItem)
148 {
149 _nextItem = (SelectItem) value;
150 return true;
151 }
152 else if (value != null && value.getClass().isArray())
153 {
154
155
156 int length = Array.getLength(value);
157 Collection<Object> items = new ArrayList<Object>(length);
158 for (int i = 0; i < length; i++)
159 {
160 items.add(Array.get(value, i));
161 }
162 _nestedItems = items.iterator();
163 return hasNext();
164 }
165 else if (value instanceof Iterable)
166 {
167
168 _nestedItems = ((Iterable<?>) value).iterator();
169 return hasNext();
170 }
171 else if (value instanceof Map)
172 {
173 Map<Object, Object> map = ((Map<Object, Object>) value);
174 Collection<SelectItem> items = new ArrayList<SelectItem>(map.size());
175 for (Map.Entry<Object, Object> entry : map.entrySet())
176 {
177 items.add(new SelectItem(entry.getValue(), entry.getKey().toString()));
178 }
179
180 _nestedItems = items.iterator();
181 return hasNext();
182 }
183 else
184 {
185 Level level = Level.FINE;
186 if (!_facesContext.isProjectStage(ProjectStage.Production))
187 {
188 level = Level.WARNING;
189 }
190
191 if (log.isLoggable(level))
192 {
193 ValueExpression expression = _currentUISelectItems.getValueExpression("value");
194 log.log(level, "ValueExpression {0} of UISelectItems with component-path {1}"
195 + " does not reference an Object of type SelectItem,"
196 + " array, Iterable or Map, but of type: {2}",
197 new Object[] {
198 (expression == null ? null : expression.getExpressionString()),
199 getPathToComponent(child),
200 (value == null ? null : value.getClass().getName())
201 });
202 }
203 }
204 }
205 else
206 {
207 _currentComponent = null;
208 }
209 }
210 return false;
211 }
212
213 @Override
214 public SelectItem next()
215 {
216 if (!hasNext())
217 {
218 throw new NoSuchElementException();
219 }
220 if (_nextItem != null)
221 {
222 SelectItem value = _nextItem;
223 _nextItem = null;
224 return value;
225 }
226 if (_nestedItems != null)
227 {
228 Object item = _nestedItems.next();
229
230 if (!(item instanceof SelectItem))
231 {
232
233
234
235 Map<String, Object> attributeMap = _currentUISelectItems.getAttributes();
236
237
238 boolean wroteRequestMapVarValue = false;
239 Object oldRequestMapVarValue = null;
240 String var = (String) attributeMap.get(VAR_ATTR);
241 if(var != null && !"".equals(var))
242 {
243
244 oldRequestMapVarValue = _facesContext.getExternalContext().getRequestMap().put(var, item);
245 wroteRequestMapVarValue = true;
246 }
247
248
249 Object itemValue = attributeMap.get(ITEM_VALUE_ATTR);
250 if (itemValue == null)
251 {
252
253
254 itemValue = item;
255 }
256
257
258
259 Object itemLabel = attributeMap.get(ITEM_LABEL_ATTR);
260 if (itemLabel == null)
261 {
262 if (itemValue != null)
263 {
264 itemLabel = itemValue.toString();
265 }
266 }
267 else
268 {
269 itemLabel = itemLabel.toString();
270 }
271 Object itemDescription = attributeMap.get(ITEM_DESCRIPTION_ATTR);
272 if (itemDescription != null)
273 {
274 itemDescription = itemDescription.toString();
275 }
276 Boolean itemDisabled = getBooleanAttribute(_currentUISelectItems, ITEM_DISABLED_ATTR, false);
277 Boolean itemLabelEscaped = getBooleanAttribute(_currentUISelectItems, ITEM_LABEL_ESCAPED_ATTR, true);
278 Object noSelectionValue = attributeMap.get(NO_SELECTION_VALUE_ATTR);
279 item = new SelectItem(itemValue,
280 (String) itemLabel,
281 (String) itemDescription,
282 itemDisabled,
283 itemLabelEscaped,
284 itemValue.equals(noSelectionValue));
285
286
287 if(wroteRequestMapVarValue)
288 {
289
290 if (oldRequestMapVarValue != null)
291 {
292 _facesContext.getExternalContext()
293 .getRequestMap().put(var, oldRequestMapVarValue);
294 }
295 else
296 {
297 _facesContext.getExternalContext()
298 .getRequestMap().remove(var);
299 }
300 }
301 }
302 return (SelectItem) item;
303 }
304 throw new NoSuchElementException();
305 }
306
307 @Override
308 public void remove()
309 {
310 throw new UnsupportedOperationException();
311 }
312
313 public UIComponent getCurrentComponent()
314 {
315 return _currentComponent;
316 }
317
318 private boolean getBooleanAttribute(UIComponent component, String attrName, boolean defaultValue)
319 {
320 Object value = component.getAttributes().get(attrName);
321 if (value == null)
322 {
323 return defaultValue;
324 }
325 else if (value instanceof Boolean)
326 {
327 return (Boolean) value;
328 }
329 else
330 {
331
332
333
334 return Boolean.valueOf(value.toString());
335 }
336 }
337
338 private String getPathToComponent(UIComponent component)
339 {
340 StringBuffer buf = new StringBuffer();
341
342 if (component == null)
343 {
344 buf.append("{Component-Path : ");
345 buf.append("[null]}");
346 return buf.toString();
347 }
348
349 getPathToComponent(component, buf);
350
351 buf.insert(0, "{Component-Path : ");
352 buf.append("}");
353
354 return buf.toString();
355 }
356
357 private void getPathToComponent(UIComponent component, StringBuffer buf)
358 {
359 if (component == null)
360 {
361 return;
362 }
363
364 StringBuffer intBuf = new StringBuffer();
365
366 intBuf.append("[Class: ");
367 intBuf.append(component.getClass().getName());
368 if (component instanceof UIViewRoot)
369 {
370 intBuf.append(",ViewId: ");
371 intBuf.append(((UIViewRoot) component).getViewId());
372 }
373 else
374 {
375 intBuf.append(",Id: ");
376 intBuf.append(component.getId());
377 }
378 intBuf.append("]");
379
380 buf.insert(0, intBuf);
381
382 getPathToComponent(component.getParent(), buf);
383 }
384 }