Source Code Cross Referenced for LoopTagSupport.java in  » EJB-Server-GlassFish » appserv-jstl » javax » servlet » jsp » jstl » core » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » EJB Server GlassFish » appserv jstl » javax.servlet.jsp.jstl.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         * 
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         * 
006:         * Portions Copyright Apache Software Foundation.
007:         * 
008:         * The contents of this file are subject to the terms of either the GNU
009:         * General Public License Version 2 only ("GPL") or the Common Development
010:         * and Distribution License("CDDL") (collectively, the "License").  You
011:         * may not use this file except in compliance with the License. You can obtain
012:         * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
013:         * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
014:         * language governing permissions and limitations under the License.
015:         * 
016:         * When distributing the software, include this License Header Notice in each
017:         * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
018:         * Sun designates this particular file as subject to the "Classpath" exception
019:         * as provided by Sun in the GPL Version 2 section of the License file that
020:         * accompanied this code.  If applicable, add the following below the License
021:         * Header, with the fields enclosed by brackets [] replaced by your own
022:         * identifying information: "Portions Copyrighted [year]
023:         * [name of copyright owner]"
024:         * 
025:         * Contributor(s):
026:         * 
027:         * If you wish your version of this file to be governed by only the CDDL or
028:         * only the GPL Version 2, indicate your decision by adding "[Contributor]
029:         * elects to include this software in this distribution under the [CDDL or GPL
030:         * Version 2] license."  If you don't indicate a single choice of license, a
031:         * recipient has the option to distribute your version of this file under
032:         * either the CDDL, the GPL Version 2 or to extend the choice of license to
033:         * its licensees as provided above.  However, if you add GPL Version 2 code
034:         * and therefore, elected the GPL Version 2 license, then the option applies
035:         * only if the new code is made subject to such option by the copyright
036:         * holder.
037:         */
038:
039:        package javax.servlet.jsp.jstl.core;
040:
041:        import java.util.List;
042:        import java.util.Collection;
043:        import java.util.Enumeration;
044:        import java.util.Map;
045:        import java.util.Iterator;
046:
047:        import javax.el.ValueExpression;
048:        import javax.el.VariableMapper;
049:        import javax.el.ELException;
050:
051:        import javax.servlet.jsp.JspException;
052:        import javax.servlet.jsp.JspTagException;
053:        import javax.servlet.jsp.PageContext;
054:        import javax.servlet.jsp.tagext.IterationTag;
055:        import javax.servlet.jsp.tagext.TagSupport;
056:        import javax.servlet.jsp.tagext.TryCatchFinally;
057:
058:        /**
059:         * <p>Base support class to facilitate implementation of iteration tags.</p>
060:         *
061:         * <p>Since most iteration tags will behave identically with respect to
062:         * actual iterative behavior, JSTL provides this
063:         * base support class to facilitate implementation.  Many iteration tags
064:         * will extend this and merely implement the <tt>hasNext()</tt> and 
065:         * <tt>next()</tt> methods
066:         * to provide contents for the handler to iterate over.</p>
067:         *
068:         * <p>In particular, this base class provides support for:</p>
069:         * 
070:         * <ul>
071:         *  <li> Iteration control, based on protected <tt>prepare()</tt>, <tt>next()</tt>,
072:         *       and <tt>hasNext()</tt> methods
073:         *  <li> Subsetting (<tt>begin</tt>, <tt>end</tt>, <tt>step></tt>functionality, 
074:         *       including validation
075:         *       of subset parameters for sensibility)
076:         *  <li> item retrieval (<tt>getCurrent()</tt>)
077:         *  <li> status retrieval (<tt>LoopTagStatus</tt>)
078:         *  <li> exposing attributes (set by <tt>var</tt> and <tt>varStatus</tt> attributes)
079:         * </ul>
080:         *
081:         * <p>In providing support for these tasks, <tt>LoopTagSupport</tt> contains
082:         * certain control variables that act to modify the iteration.  Accessors
083:         * are provided for these control variables when the variables represent
084:         * information needed or wanted at translation time (e.g., <tt>var</tt>, 
085:         * <tt>varStatus</tt>).  For
086:         * other variables, accessors cannot be provided here since subclasses
087:         * may differ on their implementations of how those accessors are received.
088:         * For instance, one subclass might accept a <tt>String</tt> and convert it into
089:         * an object of a specific type by using an expression evaluator; others
090:         * might accept objects directly.  Still others might not want to expose
091:         * such information to outside control.</p>
092:         *
093:         * @author Shawn Bayern
094:         */
095:
096:        public abstract class LoopTagSupport extends TagSupport implements 
097:                LoopTag, IterationTag, TryCatchFinally {
098:            //*********************************************************************
099:            // 'Protected' state 
100:
101:            /*
102:             * JavaBean-style properties and other state slaved to them.  These
103:             * properties can be set directly by accessors; they will not be
104:             * modified by the LoopTagSupport implementation -- and should
105:             * not be modified by subclasses outside accessors unless those
106:             * subclasses are perfectly aware of what they're doing.
107:             * (An example where such non-accessor modification might be sensible
108:             * is in the doStartTag() method of an EL-aware subclass.)
109:             */
110:
111:            /** Starting index ('begin' attribute) */
112:            protected int begin;
113:
114:            /**
115:             * Ending index of the iteration ('end' attribute).
116:             * A value of -1 internally indicates 'no end
117:             * specified', although accessors for the core JSTL tags do not
118:             * allow this value to be supplied directly by the user.
119:             */
120:            protected int end;
121:
122:            /** Iteration step ('step' attribute) */
123:            protected int step;
124:
125:            /** Boolean flag indicating whether 'begin' was specified. */
126:            protected boolean beginSpecified;
127:
128:            /** Boolean flag indicating whether 'end' was specified. */
129:            protected boolean endSpecified;
130:
131:            /** Boolean flag indicating whether 'step' was specified. */
132:            protected boolean stepSpecified;
133:
134:            /** Attribute-exposing control */
135:            protected String itemId, statusId;
136:
137:            /** The deferred expression if any */
138:            protected ValueExpression deferredExpression;
139:
140:            /** A temporary used to hold the previous value (from the enclosing
141:                iteration tag) for the EL variable.  */
142:            private ValueExpression oldMappedValue;
143:
144:            //*********************************************************************
145:            // 'Private' state (implementation details)
146:
147:            /*
148:             * State exclusively internal to the default, reference implementation.
149:             * (While this state is kept private to ensure consistency, 'status'
150:             * and 'item' happen to have one-for-one, read-only, accesor methods
151:             * as part of the LoopTag interface.)
152:             *
153:             * 'last' is kept separately for two reasons:  (a) to avoid
154:             * running a computation every time it's requested, and (b) to
155:             * let LoopTagStatus.isLast() avoid throwing any exceptions,
156:             * which would complicate subtag and scripting-variable use.
157:             *
158:             * Our 'internal index' begins at 0 and increases by 'step' each
159:             * round; this is arbitrary, but it seemed a simple way of keeping
160:             * track of the information we need.  To avoid computing
161:             * getLoopStatus().getCount() by dividing index / step, we keep
162:             * a separate 'count' and increment it by 1 each round (as a minor
163:             * performance improvement).
164:             */
165:            private LoopTagStatus status; // our LoopTagStatus
166:            private Object item; // the current item
167:            private int index; // the current internal index
168:            private int count; // the iteration count
169:            private boolean last; // current round == last one?
170:            private IteratedExpression iteratedExpression;
171:
172:            // holds an instance shared by all ValueExpression created
173:            // for variableMapper, for iterators.
174:
175:            //*********************************************************************
176:            // Constructor
177:
178:            /**
179:             * Constructs a new LoopTagSupport.  As with TagSupport, subclasses
180:             * should not implement constructors with arguments, and no-arguments
181:             * constructors implemented by subclasses must call the superclass
182:             * constructor.
183:             */
184:            public LoopTagSupport() {
185:                super ();
186:                init();
187:            }
188:
189:            //*********************************************************************
190:            // Abstract methods
191:
192:            /**
193:             * <p>Returns the next object over which the tag should iterate.  This
194:             * method must be provided by concrete subclasses of LoopTagSupport
195:             * to inform the base logic about what objects it should iterate over.</p>
196:             *
197:             * <p>It is expected that this method will generally be backed by an
198:             * Iterator, but this will not always be the case.  In particular, if
199:             * retrieving the next object raises the possibility of an exception
200:             * being thrown, this method allows that exception to propagate back
201:             * to the JSP container as a JspTagException; a standalone Iterator
202:             * would not be able to do this.  (This explains why LoopTagSupport
203:             * does not simply call for an Iterator from its subtags.)</p>
204:             * 
205:             * @return the java.lang.Object to use in the next round of iteration
206:             * @exception java.util.NoSuchElementException
207:             *            if next() is called but no new elements are available
208:             * @exception javax.servlet.jsp.JspTagException
209:             *            for other, unexpected exceptions
210:             */
211:            protected abstract Object next() throws JspTagException;
212:
213:            /**
214:             * <p>Returns information concerning the availability of more items
215:             * over which to iterate.  This method must be provided by concrete
216:             * subclasses of LoopTagSupport to assist the iterative logic
217:             * provided by the supporting base class.</p>
218:             *  
219:             * <p>See <a href="#next()">next</a> for more information about the
220:             * purpose and expectations behind this tag.</p>
221:             *
222:             * @return <tt>true</tt> if there is at least one more item to iterate
223:             *         over, <tt>false</tt> otherwise
224:             * @exception javax.servlet.jsp.JspTagException
225:             * @see #next
226:             */
227:            protected abstract boolean hasNext() throws JspTagException;
228:
229:            /**
230:             * <p>Prepares for a single tag invocation.  Specifically, allows
231:             * subclasses to prepare for calls to hasNext() and next(). 
232:             * Subclasses can assume that prepare() will be called once for
233:             * each invocation of doStartTag() in the superclass.</p>
234:             *
235:             * @exception javax.servlet.jsp.JspTagException
236:             */
237:            protected abstract void prepare() throws JspTagException;
238:
239:            //*********************************************************************
240:            // Lifecycle management and implementation of iterative behavior
241:
242:            /**
243:             * Releases any resources this LoopTagSupport may have (or inherit).
244:             */
245:            public void release() {
246:                super .release();
247:                init();
248:            }
249:
250:            /**
251:             * Begins iterating by processing the first item.
252:             */
253:            public int doStartTag() throws JspException {
254:                if (end != -1 && begin > end) {
255:                    // JSTL 1.1. We simply do not execute the loop.
256:                    return SKIP_BODY;
257:                }
258:
259:                // we're beginning a new iteration, so reset our counts (etc.)
260:                index = 0;
261:                count = 1;
262:                last = false;
263:                iteratedExpression = null;
264:                deferredExpression = null;
265:
266:                // let the subclass conduct any necessary preparation
267:                prepare();
268:
269:                // throw away the first 'begin' items (if they exist)
270:                discardIgnoreSubset(begin);
271:
272:                // get the item we're interested in
273:                if (hasNext())
274:                    // index is 0-based, so we don't update it for the first item
275:                    item = next();
276:                else
277:                    return SKIP_BODY;
278:
279:                /*
280:                 * now discard anything we have to "step" over.
281:                 * (we do this in advance to support LoopTagStatus.isLast())
282:                 */
283:                discard(step - 1);
284:
285:                // prepare to include our body...
286:                exposeVariables(true);
287:                calibrateLast();
288:                return EVAL_BODY_INCLUDE;
289:            }
290:
291:            /**
292:             * Continues the iteration when appropriate -- that is, if we (a) have
293:             * more items and (b) don't run over our 'end' (given our 'step').
294:             */
295:            public int doAfterBody() throws JspException {
296:
297:                // re-sync the index, given our prior behind-the-scenes 'step'
298:                index += step - 1;
299:
300:                // increment the count by 1 for each round
301:                count++;
302:
303:                // everything's been prepared for us, so just get the next item
304:                if (hasNext() && !atEnd()) {
305:                    index++;
306:                    item = next();
307:                } else
308:                    return SKIP_BODY;
309:
310:                /*
311:                 * now discard anything we have to "step" over.
312:                 * (we do this in advance to support LoopTagStatus.isLast())
313:                 */
314:                discard(step - 1);
315:
316:                // prepare to re-iterate...
317:                exposeVariables(false);
318:                calibrateLast();
319:                return EVAL_BODY_AGAIN;
320:            }
321:
322:            /**
323:             * Removes any attributes that this LoopTagSupport set.
324:             *
325:             * <p> These attributes are intended to support scripting variables with
326:             * NESTED scope, so we don't want to pollute attribute space by leaving
327:             * them lying around.
328:             */
329:            public void doFinally() {
330:                /*
331:                 * Make sure to un-expose variables, restoring them to their
332:                 * prior values, if applicable.
333:                 */
334:                unExposeVariables();
335:            }
336:
337:            /**
338:             * Rethrows the given Throwable.
339:             */
340:            public void doCatch(Throwable t) throws Throwable {
341:                throw t;
342:            }
343:
344:            //*********************************************************************
345:            // Accessor methods
346:
347:            /*
348:             * Overview:  The getXXX() methods we provide implement the Tag
349:             * contract.  setXXX() accessors are provided only for those
350:             * properties (attributes) that must be known at translation time,
351:             * on the premise that these accessors will vary less than the
352:             * others in terms of their interface with the page author.
353:             */
354:
355:            /*
356:             * (Purposely inherit JavaDoc and semantics from LoopTag.
357:             * Subclasses can override this if necessary, but such a need is
358:             * expected to be rare.)
359:             */
360:            public Object getCurrent() {
361:                return item;
362:            }
363:
364:            /*
365:             * (Purposely inherit JavaDoc and semantics from LoopTag.
366:             * Subclasses can override this method for more fine-grained control
367:             * over LoopTagStatus, but an effort has been made to simplify
368:             * implementation of subclasses that are happy with reasonable default
369:             * behavior.)
370:             */
371:            public LoopTagStatus getLoopStatus() {
372:
373:                // local implementation with reasonable default behavior
374:                class Status implements  LoopTagStatus {
375:
376:                    /*
377:                     * All our methods are straightforward.  We inherit
378:                     * our JavaDoc from LoopTagSupport; see that class
379:                     * for more information.
380:                     */
381:
382:                    public Object getCurrent() {
383:                        /*
384:                         * Access the item through getCurrent() instead of just
385:                         * returning the item our containing class stores.  This
386:                         * should allow a subclass of LoopTagSupport to override
387:                         * getCurrent() without having to rewrite getLoopStatus() too.
388:                         */
389:                        return (LoopTagSupport.this .getCurrent());
390:                    }
391:
392:                    public int getIndex() {
393:                        return (index + begin); // our 'index' isn't getIndex()
394:                    }
395:
396:                    public int getCount() {
397:                        return (count);
398:                    }
399:
400:                    public boolean isFirst() {
401:                        return (index == 0); // our 'index' isn't getIndex()
402:                    }
403:
404:                    public boolean isLast() {
405:                        return (last); // use cached value
406:                    }
407:
408:                    public Integer getBegin() {
409:                        if (beginSpecified)
410:                            return Integer.valueOf(begin);
411:                        else
412:                            return null;
413:                    }
414:
415:                    public Integer getEnd() {
416:                        if (endSpecified)
417:                            return Integer.valueOf(end);
418:                        else
419:                            return null;
420:                    }
421:
422:                    public Integer getStep() {
423:                        if (stepSpecified)
424:                            return Integer.valueOf(step);
425:                        else
426:                            return null;
427:                    }
428:                }
429:
430:                /*
431:                 * We just need one per invocation...  Actually, for the current
432:                 * implementation, we just need one per instance, but I'd rather
433:                 * not keep the reference around once release() has been called.
434:                 */
435:                if (status == null)
436:                    status = new Status();
437:
438:                return status;
439:            }
440:
441:            /*
442:             * Get the delimiter for string tokens.  Used only for constructing
443:             * the deferred expression for it.
444:             */
445:            protected String getDelims() {
446:                return ",";
447:            }
448:
449:            /*
450:             * We only support setter methods for attributes that need to be
451:             * offered as Strings or other literals; other attributes will be
452:             * handled directly by implementing classes, since there might be
453:             * both rtexprvalue- and EL-based varieties, which will have
454:             * different signatures.  (We can't pollute child classes by having
455:             * base implementations of those setters here; child classes that
456:             * have attributes with different signatures would end up having
457:             * two incompatible setters, which is illegal for a JavaBean.
458:             */
459:
460:            /**
461:             * Sets the 'var' attribute.
462:             *
463:             * @param id Name of the exported scoped variable storing the current item
464:             * of the iteration.
465:             */
466:            public void setVar(String id) {
467:                this .itemId = id;
468:            }
469:
470:            /**
471:             * Sets the 'varStatus' attribute.
472:             *
473:             * @param statusId Name of the exported scoped variable storing the status
474:             * of the iteration.
475:             */
476:            public void setVarStatus(String statusId) {
477:                this .statusId = statusId;
478:            }
479:
480:            //*********************************************************************
481:            // Protected utility methods
482:
483:            /* 
484:             * These methods validate attributes common to iteration tags.
485:             * Call them if your own subclassing implementation modifies them
486:             * -- e.g., if you set them through an expression language.
487:             */
488:
489:            /**
490:             * Ensures the "begin" property is sensible, throwing an exception
491:             * expected to propagate up if it isn't
492:             */
493:            protected void validateBegin() throws JspTagException {
494:                if (begin < 0)
495:                    throw new JspTagException("'begin' < 0");
496:            }
497:
498:            /**
499:             * Ensures the "end" property is sensible, throwing an exception
500:             * expected to propagate up if it isn't
501:             */
502:            protected void validateEnd() throws JspTagException {
503:                if (end < 0)
504:                    throw new JspTagException("'end' < 0");
505:            }
506:
507:            /**
508:             * Ensures the "step" property is sensible, throwing an exception
509:             * expected to propagate up if it isn't
510:             */
511:            protected void validateStep() throws JspTagException {
512:                if (step < 1)
513:                    throw new JspTagException("'step' <= 0");
514:            }
515:
516:            //*********************************************************************
517:            // Private utility methods
518:
519:            /** (Re)initializes state (during release() or construction) */
520:            private void init() {
521:                // defaults for internal bookkeeping
522:                index = 0; // internal index always starts at 0
523:                count = 1; // internal count always starts at 1
524:                status = null; // we clear status on release()
525:                item = null; // item will be retrieved for each round
526:                last = false; // last must be set explicitly
527:                beginSpecified = false; // not specified until it's specified :-)
528:                endSpecified = false; // (as above)
529:                stepSpecified = false; // (as above)
530:
531:                // defaults for interface with page author
532:                begin = 0; // when not specified, 'begin' is 0 by spec.
533:                end = -1; // when not specified, 'end' is not used
534:                step = 1; // when not specified, 'step' is 1
535:                itemId = null; // when not specified, no variable exported
536:                statusId = null; // when not specified, no variable exported
537:            }
538:
539:            /** Sets 'last' appropriately. */
540:            private void calibrateLast() throws JspTagException {
541:                /*
542:                 * the current round is the last one if (a) there are no remaining
543:                 * elements, or (b) the next one is beyond the 'end'.
544:                 */
545:                last = !hasNext() || atEnd()
546:                        || (end != -1 && (begin + index + step > end));
547:            }
548:
549:            /**
550:             * Exposes attributes (formerly scripting variables, but no longer!)
551:             * if appropriate.  Note that we don't really care, here, whether they're
552:             * scripting variables or not.
553:             */
554:            private void exposeVariables(boolean firstTime)
555:                    throws JspTagException {
556:
557:                /*
558:                 * We need to support null items returned from next(); we
559:                 * do this simply by passing such non-items through to the
560:                 * scoped variable as effectively 'null' (that is, by calling
561:                 * removeAttribute()).
562:                 *
563:                 * Also, just to be defensive, we handle the case of a null
564:                 * 'status' object as well.
565:                 *
566:                 * We call getCurrent() and getLoopStatus() (instead of just using
567:                 * 'item' and 'status') to bridge to subclasses correctly.
568:                 * A subclass can override getCurrent() or getLoopStatus() but still
569:                 * depend on our doStartTag() and doAfterBody(), which call this
570:                 * method (exposeVariables()), to expose 'item' and 'status'
571:                 * correctly.
572:                 */
573:
574:                if (itemId != null) {
575:                    if (getCurrent() == null)
576:                        pageContext.removeAttribute(itemId,
577:                                PageContext.PAGE_SCOPE);
578:                    else if (deferredExpression != null) {
579:                        VariableMapper vm = pageContext.getELContext()
580:                                .getVariableMapper();
581:                        if (vm != null) {
582:                            ValueExpression ve = getVarExpression(deferredExpression);
583:                            ValueExpression tmpValue = vm.setVariable(itemId,
584:                                    ve);
585:                            if (firstTime)
586:                                oldMappedValue = tmpValue;
587:                        }
588:                    } else
589:                        pageContext.setAttribute(itemId, getCurrent());
590:                }
591:                if (statusId != null) {
592:                    if (getLoopStatus() == null)
593:                        pageContext.removeAttribute(statusId,
594:                                PageContext.PAGE_SCOPE);
595:                    else
596:                        pageContext.setAttribute(statusId, getLoopStatus());
597:                }
598:
599:            }
600:
601:            /**
602:             * Removes page attributes that we have exposed and, if applicable,
603:             * restores them to their prior values (and scopes).
604:             */
605:            private void unExposeVariables() {
606:                // "nested" variables are now simply removed
607:                if (itemId != null) {
608:                    pageContext.removeAttribute(itemId, PageContext.PAGE_SCOPE);
609:                    VariableMapper vm = pageContext.getELContext()
610:                            .getVariableMapper();
611:                    if (vm != null)
612:                        vm.setVariable(itemId, oldMappedValue);
613:                }
614:                if (statusId != null)
615:                    pageContext.removeAttribute(statusId,
616:                            PageContext.PAGE_SCOPE);
617:            }
618:
619:            /**
620:             * Cycles through and discards up to 'n' items from the iteration.
621:             * We only know "up to 'n'", not "exactly n," since we stop cycling
622:             * if hasNext() returns false or if we hit the 'end' of the iteration.
623:             * Note: this does not update the iteration index, since this method
624:             * is intended as a behind-the-scenes operation.  The index must be
625:             * updated separately.  (I don't really like this, but it's the simplest
626:             * way to support isLast() without storing two separate inconsistent
627:             * indices.  We need to (a) make sure hasNext() refers to the next
628:             * item we actually *want* and (b) make sure the index refers to the
629:             * item associated with the *current* round, not the next one.
630:             * C'est la vie.)
631:             */
632:            private void discard(int n) throws JspTagException {
633:                /*
634:                 * copy index so we can restore it, but we need to update it
635:                 * as we work so that atEnd() works
636:                 */
637:                int oldIndex = index;
638:                while (n-- > 0 && !atEnd() && hasNext()) {
639:                    index++;
640:                    next();
641:                }
642:                index = oldIndex;
643:            }
644:
645:            /**
646:             * Discards items ignoring subsetting rules.  Useful for discarding
647:             * items from the beginning (i.e., to implement 'begin') where we
648:             * don't want factor in the 'begin' value already.
649:             */
650:            private void discardIgnoreSubset(int n) throws JspTagException {
651:                while (n-- > 0 && hasNext())
652:                    next();
653:            }
654:
655:            /**
656:             * Returns true if the iteration has past the 'end' index (with
657:             * respect to subsetting), false otherwise.  ('end' must be set
658:             * for atEnd() to return true; if 'end' is not set, atEnd()
659:             * always returns false.)
660:             */
661:            private boolean atEnd() {
662:                return ((end != -1) && (begin + index >= end));
663:            }
664:
665:            private ValueExpression getVarExpression(ValueExpression expr) {
666:                Object o = expr.getValue(pageContext.getELContext());
667:                if (o == null)
668:                    return null;
669:
670:                if (o.getClass().isArray() || o instanceof  List) {
671:                    return new IndexedValueExpression(deferredExpression, index);
672:                }
673:
674:                if (o instanceof  Collection || o instanceof  Iterator
675:                        || o instanceof  Enumeration || o instanceof  Map
676:                        || o instanceof  String) {
677:
678:                    if (iteratedExpression == null) {
679:                        iteratedExpression = new IteratedExpression(
680:                                deferredExpression, getDelims());
681:                    }
682:                    return new IteratedValueExpression(iteratedExpression,
683:                            index);
684:                }
685:
686:                throw new ELException(
687:                        "Don't know how to iterate over supplied "
688:                                + "items in forEach");
689:            }
690:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.