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