1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.struts2.jasper.tagplugins.jstl.core;
20
21 import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
22 import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
23
24 public final class ForEach implements TagPlugin {
25
26 private boolean hasVar, hasBegin, hasEnd, hasStep;
27
28 public void doTag(TagPluginContext ctxt) {
29
30 String index = null;
31
32 boolean hasVarStatus = ctxt.isAttributeSpecified("varStatus");
33 if (hasVarStatus) {
34 ctxt.dontUseTagPlugin();
35 return;
36 }
37
38 hasVar = ctxt.isAttributeSpecified("var");
39 hasBegin = ctxt.isAttributeSpecified("begin");
40 hasEnd = ctxt.isAttributeSpecified("end");
41 hasStep = ctxt.isAttributeSpecified("step");
42
43 boolean hasItems = ctxt.isAttributeSpecified("items");
44 if (hasItems) {
45 doCollection(ctxt);
46 return;
47 }
48
49
50 index = ctxt.getTemporaryVariableName();
51 ctxt.generateJavaSource("for (int " + index + " = ");
52 ctxt.generateAttribute("begin");
53 ctxt.generateJavaSource("; " + index + " <= ");
54 ctxt.generateAttribute("end");
55 if (hasStep) {
56 ctxt.generateJavaSource("; " + index + "+=");
57 ctxt.generateAttribute("step");
58 ctxt.generateJavaSource(") {");
59 } else {
60 ctxt.generateJavaSource("; " + index + "++) {");
61 }
62
63
64
65 if (hasVar
66 ctxt.generateJavaSource("_jspx_page_context.setAttribute(");
67 ctxt.generateAttribute("var");
68 ctxt.generateJavaSource(", String.valueOf(" + index + "));");
69 }
70 ctxt.generateBody();
71 ctxt.generateJavaSource("}");
72 }
73
74 /***
75 * Generate codes for Collections
76 * The pseudo code is:
77 */
78 private void doCollection(TagPluginContext ctxt) {
79
80 ctxt.generateImport("java.util.*");
81 generateIterators(ctxt);
82
83 String itemsV = ctxt.getTemporaryVariableName();
84 ctxt.generateJavaSource("Object " + itemsV + "= ");
85 ctxt.generateAttribute("items");
86 ctxt.generateJavaSource(";");
87
88 String indexV = null, beginV = null, endV = null, stepV = null;
89 if (hasBegin) {
90 beginV = ctxt.getTemporaryVariableName();
91 ctxt.generateJavaSource("int " + beginV + " = ");
92 ctxt.generateAttribute("begin");
93 ctxt.generateJavaSource(";");
94 }
95 if (hasEnd) {
96 indexV = ctxt.getTemporaryVariableName();
97 ctxt.generateJavaSource("int " + indexV + " = 0;");
98 endV = ctxt.getTemporaryVariableName();
99 ctxt.generateJavaSource("int " + endV + " = ");
100 ctxt.generateAttribute("end");
101 ctxt.generateJavaSource(";");
102 }
103 if (hasStep) {
104 stepV = ctxt.getTemporaryVariableName();
105 ctxt.generateJavaSource("int " + stepV + " = ");
106 ctxt.generateAttribute("step");
107 ctxt.generateJavaSource(";");
108 }
109
110 String iterV = ctxt.getTemporaryVariableName();
111 ctxt.generateJavaSource("Iterator " + iterV + " = null;");
112
113 ctxt.generateJavaSource("if (" + itemsV + " instanceof Object[])");
114 ctxt.generateJavaSource(iterV + "=toIterator((Object[])" + itemsV + ");");
115
116 ctxt.generateJavaSource("else if (" + itemsV + " instanceof boolean[])");
117 ctxt.generateJavaSource(iterV + "=toIterator((boolean[])" + itemsV + ");");
118
119 ctxt.generateJavaSource("else if (" + itemsV + " instanceof byte[])");
120 ctxt.generateJavaSource(iterV + "=toIterator((byte[])" + itemsV + ");");
121
122 ctxt.generateJavaSource("else if (" + itemsV + " instanceof char[])");
123 ctxt.generateJavaSource(iterV + "=toIterator((char[])" + itemsV + ");");
124
125 ctxt.generateJavaSource("else if (" + itemsV + " instanceof short[])");
126 ctxt.generateJavaSource(iterV + "=toIterator((short[])" + itemsV + ");");
127
128 ctxt.generateJavaSource("else if (" + itemsV + " instanceof int[])");
129 ctxt.generateJavaSource(iterV + "=toIterator((int[])" + itemsV + ");");
130
131 ctxt.generateJavaSource("else if (" + itemsV + " instanceof long[])");
132 ctxt.generateJavaSource(iterV + "=toIterator((long[])" + itemsV + ");");
133
134 ctxt.generateJavaSource("else if (" + itemsV + " instanceof float[])");
135 ctxt.generateJavaSource(iterV + "=toIterator((float[])" + itemsV + ");");
136
137 ctxt.generateJavaSource("else if (" + itemsV + " instanceof double[])");
138 ctxt.generateJavaSource(iterV + "=toIterator((double[])" + itemsV + ");");
139
140
141 ctxt.generateJavaSource("else if (" + itemsV + " instanceof Collection)");
142 ctxt.generateJavaSource(iterV + "=((Collection)" + itemsV + ").iterator();");
143
144
145 ctxt.generateJavaSource("else if (" + itemsV + " instanceof Iterator)");
146 ctxt.generateJavaSource(iterV + "=(Iterator)" + itemsV + ";");
147
148
149 ctxt.generateJavaSource("else if (" + itemsV + " instanceof Enumeration)");
150 ctxt.generateJavaSource(iterV + "=toIterator((Enumeration)" + itemsV + ");");
151
152
153 ctxt.generateJavaSource("else if (" + itemsV + " instanceof Map)");
154 ctxt.generateJavaSource(iterV + "=((Map)" + itemsV + ").entrySet().iterator();");
155
156 if (hasBegin) {
157 String tV = ctxt.getTemporaryVariableName();
158 ctxt.generateJavaSource("for (int " + tV + "=" + beginV + ";" +
159 tV + ">0 && " + iterV + ".hasNext(); " +
160 tV + "--)");
161 ctxt.generateJavaSource(iterV + ".next();");
162 }
163
164 ctxt.generateJavaSource("while (" + iterV + ".hasNext()){");
165 if (hasVar) {
166 ctxt.generateJavaSource("_jspx_page_context.setAttribute(");
167 ctxt.generateAttribute("var");
168 ctxt.generateJavaSource(", " + iterV + ".next());");
169 }
170
171 ctxt.generateBody();
172
173 if (hasStep) {
174 String tV = ctxt.getTemporaryVariableName();
175 ctxt.generateJavaSource("for (int " + tV + "=" + stepV + "-1;" +
176 tV + ">0 && " + iterV + ".hasNext(); " +
177 tV + "--)");
178 ctxt.generateJavaSource(iterV + ".next();");
179 }
180 if (hasEnd) {
181 if (hasStep) {
182 ctxt.generateJavaSource(indexV + "+=" + stepV + ";");
183 } else {
184 ctxt.generateJavaSource(indexV + "++;");
185 }
186 if (hasBegin) {
187 ctxt.generateJavaSource("if(" + beginV + "+" + indexV +
188 ">" + endV + ")");
189 } else {
190 ctxt.generateJavaSource("if(" + indexV + ">" + endV + ")");
191 }
192 ctxt.generateJavaSource("break;");
193 }
194 ctxt.generateJavaSource("}");
195 }
196
197 /***
198 * Generate iterators for data types supported in items
199 */
200 private void generateIterators(TagPluginContext ctxt) {
201
202
203 ctxt.generateDeclaration("ObjectArrayIterator",
204 "private Iterator toIterator(final Object[] a){\n" +
205 " return (new Iterator() {\n" +
206 " int index=0;\n" +
207 " public boolean hasNext() {\n" +
208 " return index < a.length;}\n" +
209 " public Object next() {\n" +
210 " return a[index++];}\n" +
211 " public void remove() {}\n" +
212 " });\n" +
213 "}"
214 );
215
216
217 ctxt.generateDeclaration("booleanArrayIterator",
218 "private Iterator toIterator(final boolean[] a){\n" +
219 " return (new Iterator() {\n" +
220 " int index=0;\n" +
221 " public boolean hasNext() {\n" +
222 " return index < a.length;}\n" +
223 " public Object next() {\n" +
224 " return new Boolean(a[index++]);}\n" +
225 " public void remove() {}\n" +
226 " });\n" +
227 "}"
228 );
229
230
231 ctxt.generateDeclaration("byteArrayIterator",
232 "private Iterator toIterator(final byte[] a){\n" +
233 " return (new Iterator() {\n" +
234 " int index=0;\n" +
235 " public boolean hasNext() {\n" +
236 " return index < a.length;}\n" +
237 " public Object next() {\n" +
238 " return new Byte(a[index++]);}\n" +
239 " public void remove() {}\n" +
240 " });\n" +
241 "}"
242 );
243
244
245 ctxt.generateDeclaration("charArrayIterator",
246 "private Iterator toIterator(final char[] a){\n" +
247 " return (new Iterator() {\n" +
248 " int index=0;\n" +
249 " public boolean hasNext() {\n" +
250 " return index < a.length;}\n" +
251 " public Object next() {\n" +
252 " return new Character(a[index++]);}\n" +
253 " public void remove() {}\n" +
254 " });\n" +
255 "}"
256 );
257
258
259 ctxt.generateDeclaration("shortArrayIterator",
260 "private Iterator toIterator(final short[] a){\n" +
261 " return (new Iterator() {\n" +
262 " int index=0;\n" +
263 " public boolean hasNext() {\n" +
264 " return index < a.length;}\n" +
265 " public Object next() {\n" +
266 " return new Short(a[index++]);}\n" +
267 " public void remove() {}\n" +
268 " });\n" +
269 "}"
270 );
271
272
273 ctxt.generateDeclaration("intArrayIterator",
274 "private Iterator toIterator(final int[] a){\n" +
275 " return (new Iterator() {\n" +
276 " int index=0;\n" +
277 " public boolean hasNext() {\n" +
278 " return index < a.length;}\n" +
279 " public Object next() {\n" +
280 " return new Integer(a[index++]);}\n" +
281 " public void remove() {}\n" +
282 " });\n" +
283 "}"
284 );
285
286
287 ctxt.generateDeclaration("longArrayIterator",
288 "private Iterator toIterator(final long[] a){\n" +
289 " return (new Iterator() {\n" +
290 " int index=0;\n" +
291 " public boolean hasNext() {\n" +
292 " return index < a.length;}\n" +
293 " public Object next() {\n" +
294 " return new Long(a[index++]);}\n" +
295 " public void remove() {}\n" +
296 " });\n" +
297 "}"
298 );
299
300
301 ctxt.generateDeclaration("floatArrayIterator",
302 "private Iterator toIterator(final float[] a){\n" +
303 " return (new Iterator() {\n" +
304 " int index=0;\n" +
305 " public boolean hasNext() {\n" +
306 " return index < a.length;}\n" +
307 " public Object next() {\n" +
308 " return new Float(a[index++]);}\n" +
309 " public void remove() {}\n" +
310 " });\n" +
311 "}"
312 );
313
314
315 ctxt.generateDeclaration("doubleArrayIterator",
316 "private Iterator toIterator(final double[] a){\n" +
317 " return (new Iterator() {\n" +
318 " int index=0;\n" +
319 " public boolean hasNext() {\n" +
320 " return index < a.length;}\n" +
321 " public Object next() {\n" +
322 " return new Double(a[index++]);}\n" +
323 " public void remove() {}\n" +
324 " });\n" +
325 "}"
326 );
327
328
329 ctxt.generateDeclaration("enumIterator",
330 "private Iterator toIterator(final Enumeration e){\n" +
331 " return (new Iterator() {\n" +
332 " public boolean hasNext() {\n" +
333 " return e.hasMoreElements();}\n" +
334 " public Object next() {\n" +
335 " return e.nextElement();}\n" +
336 " public void remove() {}\n" +
337 " });\n" +
338 "}"
339 );
340
341 }
342 }