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<?> _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
69 ? selectItemsParent.getChildren().iterator()
70 : _EMPTY_UICOMPONENT_ITERATOR;
71 _facesContext = facesContext;
72 }
73
74 @SuppressWarnings("unchecked")
75 public boolean hasNext()
76 {
77 if (_nextItem != null)
78 {
79 return true;
80 }
81 if (_nestedItems != null)
82 {
83 if (_nestedItems.hasNext())
84 {
85 return true;
86 }
87 _nestedItems = null;
88 }
89 if (_children.hasNext())
90 {
91 UIComponent child = _children.next();
92
93
94
95
96
97
98 while (!(child instanceof UISelectItem) && !(child instanceof UISelectItems))
99 {
100
101 if (_children.hasNext())
102 {
103
104 child = _children.next();
105 }
106 else
107 {
108
109
110 return false;
111 }
112 }
113 if (child instanceof UISelectItem)
114 {
115 UISelectItem uiSelectItem = (UISelectItem) child;
116 Object item = uiSelectItem.getValue();
117 if (item == null)
118 {
119
120 Object itemValue = uiSelectItem.getItemValue();
121 String label = uiSelectItem.getItemLabel();
122 String description = uiSelectItem.getItemDescription();
123 boolean disabled = uiSelectItem.isItemDisabled();
124 boolean escape = uiSelectItem.isItemEscaped();
125 boolean noSelectionOption = uiSelectItem.isNoSelectionOption();
126 if (label == null)
127 {
128 label = itemValue.toString();
129 }
130 item = new SelectItem(itemValue, label, description, disabled, escape, noSelectionOption);
131 }
132 else if (!(item instanceof SelectItem))
133 {
134 ValueExpression expression = uiSelectItem.getValueExpression("value");
135 throw new IllegalArgumentException("ValueExpression '"
136 + (expression == null ? null : expression.getExpressionString()) + "' of UISelectItem : "
137 + getPathToComponent(child) + " does not reference an Object of type SelectItem");
138 }
139 _nextItem = (SelectItem) item;
140 return true;
141 }
142 else if (child instanceof UISelectItems)
143 {
144 _currentUISelectItems = ((UISelectItems) child);
145 Object value = _currentUISelectItems.getValue();
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 }
206 return false;
207 }
208
209 public SelectItem next()
210 {
211 if (!hasNext())
212 {
213 throw new NoSuchElementException();
214 }
215 if (_nextItem != null)
216 {
217 SelectItem value = _nextItem;
218 _nextItem = null;
219 return value;
220 }
221 if (_nestedItems != null)
222 {
223 Object item = _nestedItems.next();
224
225 if (!(item instanceof SelectItem))
226 {
227
228
229
230 Map<String, Object> attributeMap = _currentUISelectItems.getAttributes();
231
232
233 boolean wroteRequestMapVarValue = false;
234 Object oldRequestMapVarValue = null;
235 String var = (String) attributeMap.get(VAR_ATTR);
236 if(var != null && !"".equals(var))
237 {
238
239 oldRequestMapVarValue = _facesContext.getExternalContext().getRequestMap().put(var, item);
240 wroteRequestMapVarValue = true;
241 }
242
243
244 Object itemValue = attributeMap.get(ITEM_VALUE_ATTR);
245 if (itemValue == null)
246 {
247
248
249 itemValue = item;
250 }
251
252
253
254 Object itemLabel = attributeMap.get(ITEM_LABEL_ATTR);
255 if (itemLabel == null)
256 {
257 itemLabel = itemValue.toString();
258 }
259 else
260 {
261 itemLabel = itemLabel.toString();
262 }
263 Object itemDescription = attributeMap.get(ITEM_DESCRIPTION_ATTR);
264 if (itemDescription != null)
265 {
266 itemDescription = itemDescription.toString();
267 }
268 Boolean itemDisabled = getBooleanAttribute(_currentUISelectItems, ITEM_DISABLED_ATTR, false);
269 Boolean itemLabelEscaped = getBooleanAttribute(_currentUISelectItems, ITEM_LABEL_ESCAPED_ATTR, true);
270 Object noSelectionValue = attributeMap.get(NO_SELECTION_VALUE_ATTR);
271 item = new SelectItem(itemValue,
272 (String) itemLabel,
273 (String) itemDescription,
274 itemDisabled,
275 itemLabelEscaped,
276 itemValue.equals(noSelectionValue));
277
278
279 if(wroteRequestMapVarValue)
280 {
281
282 if (oldRequestMapVarValue != null)
283 {
284 _facesContext.getExternalContext()
285 .getRequestMap().put(var, oldRequestMapVarValue);
286 }
287 else
288 {
289 _facesContext.getExternalContext()
290 .getRequestMap().remove(var);
291 }
292 }
293 }
294 return (SelectItem) item;
295 }
296 throw new NoSuchElementException();
297 }
298
299 public void remove()
300 {
301 throw new UnsupportedOperationException();
302 }
303
304 private boolean getBooleanAttribute(UIComponent component, String attrName, boolean defaultValue)
305 {
306 Object value = component.getAttributes().get(attrName);
307 if (value == null)
308 {
309 return defaultValue;
310 }
311 else if (value instanceof Boolean)
312 {
313 return (Boolean) value;
314 }
315 else
316 {
317
318
319
320 return Boolean.valueOf(value.toString());
321 }
322 }
323
324 private String getPathToComponent(UIComponent component)
325 {
326 StringBuffer buf = new StringBuffer();
327
328 if (component == null)
329 {
330 buf.append("{Component-Path : ");
331 buf.append("[null]}");
332 return buf.toString();
333 }
334
335 getPathToComponent(component, buf);
336
337 buf.insert(0, "{Component-Path : ");
338 buf.append("}");
339
340 return buf.toString();
341 }
342
343 private void getPathToComponent(UIComponent component, StringBuffer buf)
344 {
345 if (component == null)
346 {
347 return;
348 }
349
350 StringBuffer intBuf = new StringBuffer();
351
352 intBuf.append("[Class: ");
353 intBuf.append(component.getClass().getName());
354 if (component instanceof UIViewRoot)
355 {
356 intBuf.append(",ViewId: ");
357 intBuf.append(((UIViewRoot) component).getViewId());
358 }
359 else
360 {
361 intBuf.append(",Id: ");
362 intBuf.append(component.getId());
363 }
364 intBuf.append("]");
365
366 buf.insert(0, intBuf);
367
368 getPathToComponent(component.getParent(), buf);
369 }
370 }