1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
package org.apache.myfaces.view.facelets.tag.jstl.core; |
20 | |
|
21 | |
import java.io.IOException; |
22 | |
import java.lang.reflect.Array; |
23 | |
import java.util.Collection; |
24 | |
import java.util.Iterator; |
25 | |
import java.util.List; |
26 | |
import java.util.Map; |
27 | |
|
28 | |
import javax.el.ELException; |
29 | |
import javax.el.ValueExpression; |
30 | |
import javax.faces.FacesException; |
31 | |
import javax.faces.component.UIComponent; |
32 | |
import javax.faces.view.facelets.FaceletContext; |
33 | |
import javax.faces.view.facelets.FaceletException; |
34 | |
import javax.faces.view.facelets.TagAttribute; |
35 | |
import javax.faces.view.facelets.TagAttributeException; |
36 | |
import javax.faces.view.facelets.TagConfig; |
37 | |
import javax.faces.view.facelets.TagHandler; |
38 | |
|
39 | |
import org.apache.myfaces.view.facelets.AbstractFaceletContext; |
40 | |
import org.apache.myfaces.view.facelets.FaceletCompositionContext; |
41 | |
import org.apache.myfaces.view.facelets.PageContext; |
42 | |
import org.apache.myfaces.view.facelets.tag.ComponentContainerHandler; |
43 | |
import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport; |
44 | |
|
45 | |
|
46 | |
|
47 | |
|
48 | |
|
49 | |
|
50 | |
|
51 | |
|
52 | |
|
53 | |
|
54 | |
|
55 | |
|
56 | |
|
57 | |
|
58 | |
|
59 | |
|
60 | |
public final class LegacyForEachHandler extends TagHandler implements ComponentContainerHandler |
61 | |
{ |
62 | |
|
63 | |
private static class ArrayIterator implements Iterator<Object> |
64 | |
{ |
65 | |
|
66 | |
protected final Object array; |
67 | |
|
68 | |
protected int i; |
69 | |
|
70 | |
protected final int len; |
71 | |
|
72 | |
public ArrayIterator(Object src) |
73 | 0 | { |
74 | 0 | this.i = 0; |
75 | 0 | this.array = src; |
76 | 0 | this.len = Array.getLength(src); |
77 | 0 | } |
78 | |
|
79 | |
public boolean hasNext() |
80 | |
{ |
81 | 0 | return this.i < this.len; |
82 | |
} |
83 | |
|
84 | |
public Object next() |
85 | |
{ |
86 | 0 | return Array.get(this.array, this.i++); |
87 | |
} |
88 | |
|
89 | |
public void remove() |
90 | |
{ |
91 | 0 | throw new UnsupportedOperationException(); |
92 | |
} |
93 | |
} |
94 | |
|
95 | |
|
96 | |
|
97 | |
|
98 | |
|
99 | |
|
100 | |
|
101 | |
|
102 | |
|
103 | |
|
104 | |
|
105 | |
private final TagAttribute begin; |
106 | |
|
107 | |
|
108 | |
|
109 | |
|
110 | |
|
111 | |
|
112 | |
|
113 | |
|
114 | |
|
115 | |
|
116 | |
private final TagAttribute end; |
117 | |
|
118 | |
|
119 | |
|
120 | |
|
121 | |
|
122 | |
private final TagAttribute items; |
123 | |
|
124 | |
|
125 | |
|
126 | |
|
127 | |
|
128 | |
|
129 | |
private final TagAttribute step; |
130 | |
|
131 | |
private final TagAttribute tranzient; |
132 | |
|
133 | |
|
134 | |
|
135 | |
|
136 | |
|
137 | |
|
138 | |
|
139 | |
|
140 | |
private final TagAttribute var; |
141 | |
|
142 | |
|
143 | |
|
144 | |
|
145 | |
|
146 | |
|
147 | |
private final TagAttribute varStatus; |
148 | |
|
149 | |
|
150 | |
|
151 | |
|
152 | |
public LegacyForEachHandler(TagConfig config) |
153 | |
{ |
154 | 0 | super(config); |
155 | 0 | this.items = this.getAttribute("items"); |
156 | 0 | this.var = this.getAttribute("var"); |
157 | 0 | this.begin = this.getAttribute("begin"); |
158 | 0 | this.end = this.getAttribute("end"); |
159 | 0 | this.step = this.getAttribute("step"); |
160 | 0 | this.varStatus = this.getAttribute("varStatus"); |
161 | 0 | this.tranzient = this.getAttribute("transient"); |
162 | |
|
163 | 0 | if (this.items == null && this.begin != null && this.end == null) |
164 | |
{ |
165 | 0 | throw new TagAttributeException(this.tag, this.begin, |
166 | |
"If the 'items' attribute is not specified, but the 'begin' attribute is, " |
167 | |
+ "then the 'end' attribute is required"); |
168 | |
} |
169 | 0 | } |
170 | |
|
171 | |
public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException, |
172 | |
ELException |
173 | |
{ |
174 | |
|
175 | 0 | int s = this.getBegin(ctx); |
176 | 0 | int e = this.getEnd(ctx); |
177 | 0 | int m = this.getStep(ctx); |
178 | 0 | Integer sO = this.begin != null ? Integer.valueOf(s) : null; |
179 | 0 | Integer eO = this.end != null ? Integer.valueOf(e) : null; |
180 | 0 | Integer mO = this.step != null ? Integer.valueOf(m) : null; |
181 | |
|
182 | 0 | boolean t = this.getTransient(ctx); |
183 | 0 | Object src = null; |
184 | 0 | ValueExpression srcVE = null; |
185 | 0 | if (this.items != null) |
186 | |
{ |
187 | 0 | srcVE = this.items.getValueExpression(ctx, Object.class); |
188 | 0 | src = srcVE.getValue(ctx); |
189 | |
} |
190 | |
else |
191 | |
{ |
192 | 0 | byte[] b = new byte[e + 1]; |
193 | 0 | for (int i = 0; i < b.length; i++) |
194 | |
{ |
195 | 0 | b[i] = (byte) i; |
196 | |
} |
197 | 0 | src = b; |
198 | |
} |
199 | 0 | FaceletCompositionContext fcc = FaceletCompositionContext.getCurrentInstance(ctx); |
200 | 0 | if (src != null) |
201 | |
{ |
202 | |
try |
203 | |
{ |
204 | 0 | fcc.startComponentUniqueIdSection(); |
205 | 0 | AbstractFaceletContext actx = (AbstractFaceletContext) ctx; |
206 | 0 | PageContext pctx = actx.getPageContext(); |
207 | 0 | Iterator<?> itr = this.toIterator(src); |
208 | 0 | if (itr != null) |
209 | |
{ |
210 | 0 | int i = 0; |
211 | |
|
212 | |
|
213 | 0 | while (i < s && itr.hasNext()) |
214 | |
{ |
215 | 0 | itr.next(); |
216 | 0 | i++; |
217 | |
} |
218 | |
|
219 | 0 | String v = this.getVarName(ctx); |
220 | 0 | String vs = this.getVarStatusName(ctx); |
221 | 0 | ValueExpression ve = null; |
222 | 0 | ValueExpression vO = this.capture(v, pctx); |
223 | 0 | ValueExpression vsO = this.capture(vs, pctx); |
224 | 0 | int mi = 0; |
225 | 0 | Object value = null; |
226 | |
try |
227 | |
{ |
228 | 0 | boolean first = true; |
229 | 0 | while (i <= e && itr.hasNext()) |
230 | |
{ |
231 | 0 | value = itr.next(); |
232 | |
|
233 | |
|
234 | 0 | if (v != null) |
235 | |
{ |
236 | 0 | if (t || srcVE == null) |
237 | |
{ |
238 | 0 | if (value == null) |
239 | |
{ |
240 | 0 | pctx.getAttributes().put(v, null); |
241 | |
} |
242 | |
else |
243 | |
{ |
244 | 0 | pctx.getAttributes().put(v, |
245 | |
ctx.getExpressionFactory().createValueExpression( |
246 | |
value, Object.class)); |
247 | |
} |
248 | |
} |
249 | |
else |
250 | |
{ |
251 | 0 | ve = this.getVarExpr(srcVE, src, value, i); |
252 | 0 | pctx.getAttributes().put(v, ve); |
253 | |
} |
254 | |
} |
255 | |
|
256 | |
|
257 | 0 | if (vs != null) |
258 | |
{ |
259 | 0 | IterationStatus itrS = new IterationStatus(first, !itr.hasNext(), i, sO, eO, mO, value); |
260 | 0 | if (t || srcVE == null) |
261 | |
{ |
262 | 0 | if (srcVE == null) |
263 | |
{ |
264 | 0 | pctx.getAttributes().put(vs, null); |
265 | |
} |
266 | |
else |
267 | |
{ |
268 | 0 | pctx.getAttributes().put(vs, |
269 | |
ctx.getExpressionFactory().createValueExpression( |
270 | |
itrS, Object.class)); |
271 | |
} |
272 | |
} |
273 | |
else |
274 | |
{ |
275 | 0 | ve = new IterationStatusExpression(itrS); |
276 | 0 | pctx.getAttributes().put(vs, ve); |
277 | |
} |
278 | |
} |
279 | |
|
280 | |
|
281 | 0 | this.nextHandler.apply(ctx, parent); |
282 | |
|
283 | |
|
284 | 0 | mi = 1; |
285 | 0 | while (mi < m && itr.hasNext()) |
286 | |
{ |
287 | 0 | itr.next(); |
288 | 0 | mi++; |
289 | 0 | i++; |
290 | |
} |
291 | 0 | i++; |
292 | |
|
293 | 0 | first = false; |
294 | |
} |
295 | |
} |
296 | |
finally |
297 | |
{ |
298 | |
|
299 | 0 | if (v != null) |
300 | |
{ |
301 | 0 | pctx.getAttributes().put(v, vO); |
302 | |
} |
303 | |
else |
304 | |
{ |
305 | 0 | pctx.getAttributes().remove(v); |
306 | |
} |
307 | 0 | if (vs != null) |
308 | |
{ |
309 | 0 | pctx.getAttributes().put(vs, vsO); |
310 | |
} |
311 | |
else |
312 | |
{ |
313 | 0 | pctx.getAttributes().remove(vs); |
314 | |
} |
315 | 0 | } |
316 | |
} |
317 | |
} |
318 | |
finally |
319 | |
{ |
320 | 0 | fcc.endComponentUniqueIdSection(); |
321 | 0 | } |
322 | |
} |
323 | |
|
324 | 0 | if (fcc.isUsingPSSOnThisView() && fcc.isRefreshTransientBuildOnPSS() && !fcc.isRefreshingTransientBuild()) |
325 | |
{ |
326 | |
|
327 | 0 | ComponentSupport.markComponentToRestoreFully(ctx.getFacesContext(), parent); |
328 | |
} |
329 | 0 | if (fcc.isDynamicComponentSection()) |
330 | |
{ |
331 | 0 | ComponentSupport.markComponentToRefreshDynamically(ctx.getFacesContext(), parent); |
332 | |
} |
333 | 0 | } |
334 | |
|
335 | |
private final ValueExpression capture(String name, PageContext pctx) |
336 | |
{ |
337 | 0 | if (name != null) |
338 | |
{ |
339 | 0 | return pctx.getAttributes().put(name, null); |
340 | |
} |
341 | 0 | return null; |
342 | |
} |
343 | |
|
344 | |
private final int getBegin(FaceletContext ctx) |
345 | |
{ |
346 | 0 | if (this.begin != null) |
347 | |
{ |
348 | 0 | return this.begin.getInt(ctx); |
349 | |
} |
350 | 0 | return 0; |
351 | |
} |
352 | |
|
353 | |
private final int getEnd(FaceletContext ctx) |
354 | |
{ |
355 | 0 | if (this.end != null) |
356 | |
{ |
357 | 0 | return this.end.getInt(ctx); |
358 | |
} |
359 | 0 | return Integer.MAX_VALUE - 1; |
360 | |
} |
361 | |
|
362 | |
private final int getStep(FaceletContext ctx) |
363 | |
{ |
364 | 0 | if (this.step != null) |
365 | |
{ |
366 | 0 | return this.step.getInt(ctx); |
367 | |
} |
368 | 0 | return 1; |
369 | |
} |
370 | |
|
371 | |
private final boolean getTransient(FaceletContext ctx) |
372 | |
{ |
373 | 0 | if (this.tranzient != null) |
374 | |
{ |
375 | 0 | return this.tranzient.getBoolean(ctx); |
376 | |
} |
377 | 0 | return false; |
378 | |
} |
379 | |
|
380 | |
private final ValueExpression getVarExpr(ValueExpression ve, Object src, Object value, int i) |
381 | |
{ |
382 | 0 | if (src instanceof List || src.getClass().isArray()) |
383 | |
{ |
384 | 0 | return new IndexedValueExpression(ve, i); |
385 | |
} |
386 | 0 | else if (src instanceof Map && value instanceof Map.Entry) |
387 | |
{ |
388 | 0 | return new MappedValueExpression(ve, (Map.Entry) value); |
389 | |
} |
390 | 0 | else if (src instanceof Collection) |
391 | |
{ |
392 | 0 | return new IteratedValueExpression(ve, value); |
393 | |
} |
394 | 0 | throw new IllegalStateException("Cannot create VE for: " + src); |
395 | |
} |
396 | |
|
397 | |
private final String getVarName(FaceletContext ctx) |
398 | |
{ |
399 | 0 | if (this.var != null) |
400 | |
{ |
401 | 0 | return this.var.getValue(ctx); |
402 | |
} |
403 | 0 | return null; |
404 | |
} |
405 | |
|
406 | |
private final String getVarStatusName(FaceletContext ctx) |
407 | |
{ |
408 | 0 | if (this.varStatus != null) |
409 | |
{ |
410 | 0 | return this.varStatus.getValue(ctx); |
411 | |
} |
412 | 0 | return null; |
413 | |
} |
414 | |
|
415 | |
private final Iterator<?> toIterator(Object src) |
416 | |
{ |
417 | 0 | if (src == null) |
418 | |
{ |
419 | 0 | return null; |
420 | |
} |
421 | 0 | else if (src instanceof Collection) |
422 | |
{ |
423 | 0 | return ((Collection<?>) src).iterator(); |
424 | |
} |
425 | 0 | else if (src instanceof Map) |
426 | |
{ |
427 | 0 | return ((Map<?, ?>) src).entrySet().iterator(); |
428 | |
} |
429 | 0 | else if (src.getClass().isArray()) |
430 | |
{ |
431 | 0 | return new ArrayIterator(src); |
432 | |
} |
433 | |
else |
434 | |
{ |
435 | 0 | throw new TagAttributeException(this.tag, this.items, |
436 | |
"Must evaluate to a Collection, Map, Array, or null."); |
437 | |
} |
438 | |
} |
439 | |
|
440 | |
} |