KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > jsp > java > JstlCoreForEach


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.jsp.java;
31
32 import com.caucho.jsp.JspParseException;
33 import com.caucho.jsp.TagInstance;
34 import com.caucho.vfs.WriteStream;
35 import com.caucho.xml.QName;
36
37 import java.io.IOException JavaDoc;
38 import java.util.ArrayList JavaDoc;
39
40 /**
41  * Special generator for a JSTL c:forEach tag.
42  */

43 public class JstlCoreForEach extends JstlNode {
44   private static final QName VAR = new QName("var");
45   private static final QName VAR_STATUS = new QName("varStatus");
46   
47   private static final QName ITEMS = new QName("items");
48   private static final QName BEGIN = new QName("begin");
49   private static final QName END = new QName("end");
50   private static final QName STEP = new QName("step");
51   
52   private String JavaDoc _var;
53   private String JavaDoc _varStatus;
54
55   private String JavaDoc _items;
56   private JspAttribute _itemsAttr;
57
58   private String JavaDoc _begin;
59   private JspAttribute _beginAttr;
60
61   private String JavaDoc _end;
62   private JspAttribute _endAttr;
63
64   private String JavaDoc _step;
65   private JspAttribute _stepAttr;
66
67   private boolean _isInteger;
68   private int _depth;
69   private String JavaDoc _tagVar;
70
71   private TagInstance _tag;
72   
73   /**
74    * Adds an attribute.
75    */

76   public void addAttribute(QName name, String JavaDoc value)
77     throws JspParseException
78   {
79     if (VAR.equals(name))
80       _var = value;
81     else if (VAR_STATUS.equals(name))
82       _varStatus = value;
83     else if (ITEMS.equals(name)) {
84       _items = value;
85       _attributeNames.add(name);
86       _attributeValues.add(value);
87     }
88     else if (BEGIN.equals(name))
89       _begin = value;
90     else if (END.equals(name))
91       _end = value;
92     else if (STEP.equals(name))
93       _step = value;
94     else
95       throw error(L.l("`{0}' is an unknown attribute for <{1}>.",
96                       name.getName(), getTagName()));
97   }
98   
99   /**
100    * Adds an attribute.
101    */

102   public void addAttribute(QName name, JspAttribute value)
103     throws JspParseException
104   {
105     if (ITEMS.equals(name))
106       _itemsAttr = value;
107     else if (BEGIN.equals(name))
108       _beginAttr = value;
109     else if (END.equals(name))
110       _endAttr = value;
111     else if (STEP.equals(name))
112       _stepAttr = value;
113     else
114       throw error(L.l("`{0}' is an unknown jsp:attribute for <{1}>.",
115                       name.getName(), getTagName()));
116   }
117
118   /**
119    * Returns true if the tag has scripting values.
120    */

121   public boolean hasScripting()
122   {
123     return (super.hasScripting() ||
124         hasScripting(_items) || hasScripting(_itemsAttr) ||
125         hasScripting(_begin) || hasScripting(_beginAttr) ||
126         hasScripting(_end) || hasScripting(_endAttr) ||
127         hasScripting(_step) || hasScripting(_stepAttr));
128   }
129
130   /**
131    * Returns true for an integer forEach.
132    */

133   public boolean isInteger()
134   {
135     return _items == null && _itemsAttr == null;
136   }
137
138   public TagInstance getTag()
139   {
140     return _tag;
141   }
142
143   /**
144    * Returns the tag name for the current tag.
145    */

146   public String JavaDoc getCustomTagName()
147   {
148     if (_tag == null)
149       return null;
150     else
151       return _tag.getId();
152   }
153
154   /**
155    * Returns true for a simple tag.
156    */

157   public boolean isSimpleTag()
158   {
159     return false;
160   }
161
162   /**
163    * Generates the XML text representation for the tag validation.
164    *
165    * @param os write stream to the generated XML.
166    */

167   public void printXml(WriteStream os)
168     throws IOException JavaDoc
169   {
170     os.print("<c:forEach");
171       
172     if (_itemsAttr != null) {
173       os.print(" items=\"");
174       _itemsAttr.printXml(os);
175       os.print("\"");
176     }
177     else if (_items != null) {
178       os.print(" items=\"");
179       printXmlText(os, _items);
180       os.print("\"");
181     }
182       
183     if (_beginAttr != null) {
184       os.print(" begin=\"");
185       _beginAttr.printXml(os);
186       os.print("\"");
187     }
188     else if (_begin != null) {
189       os.print(" begin=\"");
190       printXmlText(os, _begin);
191       os.print("\"");
192     }
193       
194     if (_endAttr != null) {
195       os.print(" end=\"");
196       _endAttr.printXml(os);
197       os.print("\"");
198     }
199     else if (_end != null) {
200       os.print(" end=\"");
201       printXmlText(os, _end);
202       os.print("\"");
203     }
204       
205     if (_stepAttr != null) {
206       os.print(" step=\"");
207       _stepAttr.printXml(os);
208       os.print("\"");
209     }
210     else if (_step != null) {
211       os.print(" step=\"");
212       printXmlText(os, _step);
213       os.print("\"");
214     }
215
216     os.print(">");
217
218     printXmlChildren(os);
219
220     os.print("</c:forEach>");
221   }
222   
223   /**
224    * Generates the prologue for the c:forEach tag.
225    */

226   public void generatePrologue(JspJavaWriter out)
227     throws Exception JavaDoc
228   {
229     TagInstance parent = getParent().getTag();
230
231     _tag = parent.findTag(getQName(), _attributeNames, false);
232
233     if (_tag != null) {
234       _tagVar = _tag.getId();
235     }
236     else {
237       String JavaDoc id = "_jsp_loop_" + _gen.uniqueId();
238       
239       _tag = parent.addTag(getQName(), null, null,
240                _attributeNames, _attributeValues, false);
241
242       _tag.setId(id);
243       
244       _tagVar = _tag.getId();
245
246       if (isInteger())
247     out.println("com.caucho.jsp.IntegerLoopSupportTag " + _tagVar + " = null;");
248       else
249     out.println("com.caucho.jsp.IteratorLoopSupportTag " + _tagVar + " = null;");
250     }
251
252     generatePrologueChildren(out);
253   }
254
255   private boolean hasDeclaration()
256   {
257     return (_varStatus != null || hasTag());
258   }
259
260   /**
261    * Returns the depth of the loop tags.
262    */

263   private int getDepth()
264   {
265     JspNode node = this;
266     int depth = 0;
267
268     for (; ! (node instanceof JspSegmentNode); node = node.getParent()) {
269       if (node instanceof JstlCoreForEach) {
270     JstlCoreForEach forEach = (JstlCoreForEach) node;
271
272     if (forEach.isInteger() == isInteger())
273       depth++;
274       }
275     }
276
277     return depth;
278   }
279
280   /**
281    * Returns true if this is the first declaration for the forEach
282    */

283   private boolean isFirst()
284   {
285     JspNode node = this;
286     
287     for (; ! (node instanceof JspSegmentNode); node = node.getParent()) {
288     }
289     
290     return isFirst(node, getDepth()) == 1;
291   }
292
293   /**
294    * Returns true if this is the first declaration for the forEach
295    */

296   private int isFirst(JspNode node, int depth)
297   {
298     if (node == this)
299       return 1;
300     else if (node instanceof JstlCoreForEach) {
301       JstlCoreForEach forEach = (JstlCoreForEach) node;
302
303       if (forEach.isInteger() == isInteger() &&
304       forEach.getDepth() == depth &&
305       forEach.hasDeclaration())
306     return 0;
307     }
308     
309     if (node instanceof JspContainerNode) {
310       ArrayList JavaDoc<JspNode> children = ((JspContainerNode) node).getChildren();
311
312       if (children == null)
313     return -1;
314
315       for (int i = 0; i < children.size(); i++) {
316     JspNode child = children.get(i);
317
318     int result = isFirst(child, depth);
319
320     if (result >= 0)
321       return result;
322       }
323     }
324     
325     return -1;
326   }
327   
328   /**
329    * Generates the code for the c:forEach tag.
330    */

331   public void generate(JspJavaWriter out)
332     throws Exception JavaDoc
333   {
334     if (_items == null && _itemsAttr == null)
335       generateIntegerForEach(out);
336     else
337       generateCollectionForEach(out);
338   }
339   
340   /**
341    * Generates the code for the c:forEach tag.
342    */

343   public void generateIntegerForEach(JspJavaWriter out)
344     throws Exception JavaDoc
345   {
346     if (_begin == null && _beginAttr == null)
347       throw error(L.l("required attribute `begin' missing from <{0}>",
348                       getTagName()));
349
350     if (_end == null && _endAttr == null)
351       throw error(L.l("required attribute `end' missing from <{0}>",
352                       getTagName()));
353
354     int uniqueId = _gen.uniqueId();
355
356     String JavaDoc oldVar = "_jsp_oldVar_" + uniqueId;
357     String JavaDoc oldStatusVar = "_jsp_status_" + uniqueId;
358     
359     if (_tagVar != null) {
360       out.println("if (" + _tagVar + " == null)");
361       out.println(" " + _tagVar + " = new com.caucho.jsp.IntegerLoopSupportTag();");
362
363       if (hasTag()) {
364     JspNode parentTagNode = getParent().getParentTagNode();
365
366     if (parentTagNode == null) {
367       out.println(_tagVar + ".setParent((javax.servlet.jsp.tagext.Tag) null);");
368     }
369     else {
370       out.println(_tagVar + ".setParent(" + parentTagNode.getCustomTagName() + ");");
371     }
372       }
373     }
374
375     String JavaDoc beginVar = "_jsp_begin_" + uniqueId;
376     String JavaDoc endVar = "_jsp_end_" + uniqueId;
377     String JavaDoc iVar = "_jsp_i_" + uniqueId;
378     
379     out.print("int " + beginVar + " = ");
380     if (_beginAttr != null)
381       out.print(_beginAttr.generateValue(int.class));
382     else
383       out.print(generateValue(int.class, _begin));
384     out.println(";");
385
386     out.print("int " + endVar + " = ");
387     if (_endAttr != null)
388       out.print(_endAttr.generateValue(int.class));
389     else
390       out.print(generateValue(int.class, _end));
391     out.println(";");
392     
393     String JavaDoc stepVar = null;
394     if (_step != null || _stepAttr != null) {
395       stepVar = "_jsp_step_" + uniqueId;
396       out.print("int " + stepVar + " = ");
397       
398       if (_stepAttr != null)
399     out.print(_stepAttr.generateValue(int.class));
400       else
401     out.print(generateValue(int.class, _step));
402       
403       out.println(";");
404     }
405     else
406       stepVar = "1";
407
408     if (_tagVar != null)
409       out.println(_tagVar + ".init(" + beginVar + ", " + endVar + ", " + stepVar + ");");
410
411     if (_varStatus != null) {
412       out.print("Object " + oldStatusVar + " = pageContext.putAttribute(\"");
413       out.print(escapeJavaString(_varStatus));
414       out.println("\", " + _tagVar + ");");
415     }
416
417     if (_var != null) {
418       out.print("Object " + oldVar + " = pageContext.getAttribute(\"");
419       out.print(escapeJavaString(_var));
420       out.println("\");");
421     }
422
423     out.print("for (int " + iVar + " = " + beginVar + "; ");
424     out.print(iVar + " <= " + endVar + "; ");
425     out.println(iVar + " += " + stepVar + ") {");
426     out.pushDepth();
427
428     if (_var != null) {
429       out.print("pageContext.setAttribute(\"" + escapeJavaString(_var) + "\"");
430       out.println(", new Integer(" + iVar + "));");
431     }
432
433     if (_tagVar != null) {
434       out.println(_tagVar + ".setCurrent(" + iVar + ");");
435     }
436
437     generateChildren(out);
438     
439     out.popDepth();
440     out.println("}");
441
442     if (_var != null) {
443       out.print("pageContext.pageSetOrRemove(\"");
444       out.print(escapeJavaString(_var));
445       out.println("\", " + oldVar + ");");
446     }
447
448     if (_varStatus != null) {
449       out.print("pageContext.pageSetOrRemove(\"");
450       out.print(escapeJavaString(_varStatus));
451       out.println("\", " + oldStatusVar + ");");
452     }
453   }
454   
455   /**
456    * Generates the code for the c:forEach tag.
457    */

458   public void generateCollectionForEach(JspJavaWriter out)
459     throws Exception JavaDoc
460   {
461     int uniqueId = _gen.uniqueId();
462
463     String JavaDoc oldVar = "_jsp_oldVar_" + uniqueId;
464     String JavaDoc oldStatusVar = "_jsp_status_" + uniqueId;
465     
466     if (_tagVar != null) {
467       out.println("if (" + _tagVar + " == null)");
468       out.println(" " + _tagVar + " = new com.caucho.jsp.IteratorLoopSupportTag();");
469
470       if (hasTag()) {
471     JspNode parentTagNode = getParent().getParentTagNode();
472
473     if (parentTagNode == null) {
474       out.println(_tagVar + ".setParent((javax.servlet.jsp.tagext.Tag) null);");
475     }
476     else {
477       out.println(_tagVar + ".setParent(" + parentTagNode.getCustomTagName() + ");");
478     }
479       }
480     }
481
482     String JavaDoc iterVar = "_jsp_iter_" + uniqueId;
483     String JavaDoc iVar = "_jsp_i_" + uniqueId;
484     out.print("java.util.Iterator " + iterVar + " = com.caucho.jstl.el.ForEachTag.getIterator(");
485     if (_itemsAttr != null)
486       out.print(_itemsAttr.generateValue(Object JavaDoc.class));
487     else
488       out.print(generateValue(Object JavaDoc.class, _items));
489     out.println(");");
490
491     String JavaDoc beginVar = null;
492     if (_beginAttr != null || _begin != null) {
493       beginVar = "_jsp_begin_" + uniqueId;
494       out.print("int " + beginVar + " = ");
495       if (_beginAttr != null)
496     out.print(_beginAttr.generateValue(int.class));
497       else
498     out.print(generateValue(int.class, _begin));
499       out.println(";");
500     }
501
502     String JavaDoc intVar = "_jsp_int_" + uniqueId;
503     if (beginVar != null) {
504       out.print("for (int " + intVar + " = " + beginVar + ";");
505       out.println(intVar + " > 0; " + intVar + "--)");
506       out.println(" if (" + iterVar + ".hasNext()) " + iterVar + ".next();");
507     }
508
509     String JavaDoc endVar = null;
510     if (_endAttr != null || _end != null) {
511       endVar = "_jsp_end_" + uniqueId;
512       
513       out.print("int " + endVar + " = ");
514       if (_endAttr != null)
515     out.print(_endAttr.generateValue(int.class));
516       else
517     out.print(generateValue(int.class, _end));
518       out.println(";");
519     }
520     
521     String JavaDoc stepVar = null;
522     if (_step != null || _stepAttr != null) {
523       stepVar = "_jsp_step_" + uniqueId;
524       out.print("int " + stepVar + " = ");
525       
526       if (_stepAttr != null)
527     out.print(_stepAttr.generateValue(int.class));
528       else
529     out.print(generateValue(int.class, _step));
530       
531       out.println(";");
532     }
533     else
534       stepVar = "1";
535
536     if (_tagVar != null) {
537       out.print(_tagVar + ".init(");
538       if (beginVar != null)
539     out.print(beginVar + ", ");
540       else
541     out.print("0, ");
542       
543       if (endVar != null)
544     out.print(endVar + ", ");
545       else
546     out.print("Integer.MAX_VALUE, ");
547
548       out.println(stepVar + ");");
549     }
550
551     if (_varStatus != null) {
552       out.print("Object " + oldStatusVar + " = pageContext.putAttribute(\"");
553       out.print(escapeJavaString(_varStatus));
554       out.println("\", " + _tagVar + ");");
555     }
556
557     if (_var != null) {
558       out.print("Object " + oldVar + " = pageContext.getAttribute(\"");
559       out.print(escapeJavaString(_var));
560       out.println("\");");
561     }
562
563     if (endVar != null) {
564       String JavaDoc begin = beginVar == null ? "0" : beginVar;
565       
566       out.print("for (int " + intVar + " = " + begin + "; ");
567       out.print(intVar + " <= " + endVar);
568
569       out.print(" && " + iterVar + ".hasNext(); ");
570       
571       out.println(intVar + " += " + stepVar + ") {");
572     }
573     else
574       out.println("while (" + iterVar + ".hasNext()) {");
575     
576     out.pushDepth();
577
578     out.println("Object " + iVar + " = " + iterVar + ".next();");
579
580     if (_var != null) {
581       out.print("pageContext.setAttribute(\"" + escapeJavaString(_var) + "\"");
582       out.println(", " + iVar + ");");
583     }
584
585     if (_tagVar != null) {
586       out.println(_tagVar + ".setCurrent(" + iVar + ", " + iterVar + ".hasNext());");
587     }
588
589     generateChildren(out);
590
591     if (! stepVar.equals("1")) {
592       String JavaDoc stepI = "_jsp_si_" + uniqueId;
593
594       out.print("for (int " + stepI + " = " + stepVar + "; ");
595       out.println(stepI + " > 1; " + stepI + "--)");
596       out.println(" if (" + iterVar + ".hasNext()) " + iterVar + ".next();");
597       out.println("if (! " + iterVar + ".hasNext())");
598       out.println(" break;");
599     }
600     
601     out.popDepth();
602     out.println("}");
603
604     if (_var != null) {
605       out.print("pageContext.pageSetOrRemove(\"");
606       out.print(escapeJavaString(_var));
607       out.println("\", " + oldVar + ");");
608     }
609
610     if (_varStatus != null) {
611       out.print("pageContext.pageSetOrRemove(\"");
612       out.print(escapeJavaString(_varStatus));
613       out.println("\", " + oldStatusVar + ");");
614     }
615   }
616 }
617
Popular Tags