Source Code Cross Referenced for Repeater.java in  » Library » Apache-beehive-1.0.2-src » org » apache » beehive » netui » tags » databinding » repeater » 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 » Library » Apache beehive 1.0.2 src » org.apache.beehive.netui.tags.databinding.repeater 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         * 
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         * 
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         *
017:         * $Header:$
018:         */
019:        package org.apache.beehive.netui.tags.databinding.repeater;
020:
021:        import javax.servlet.jsp.JspException;
022:        import javax.servlet.jsp.tagext.*;
023:        import java.util.Iterator;
024:        import java.util.List;
025:        import java.util.Collections;
026:
027:        import org.apache.beehive.netui.script.common.DataAccessProviderStack;
028:        import org.apache.beehive.netui.script.common.IDataAccessProvider;
029:        import org.apache.beehive.netui.tags.AbstractClassicTag;
030:        import org.apache.beehive.netui.tags.ExpressionHandling;
031:        import org.apache.beehive.netui.tags.databinding.repeater.pad.PadContext;
032:        import org.apache.beehive.netui.util.Bundle;
033:        import org.apache.beehive.netui.util.exception.LocalizedUnsupportedOperationException;
034:        import org.apache.beehive.netui.util.internal.InternalStringBuilder;
035:        import org.apache.beehive.netui.util.iterator.IteratorFactory;
036:        import org.apache.beehive.netui.util.logging.Logger;
037:
038:        /**
039:         * The <netui-data:repeater> tag is a markup-generic tag that repeats over a data set.
040:         * The repeater tag set is used to render data from a data set into a page.  The repeater
041:         * itself does not render any markup. Instead, the markup from its contained tags is
042:         * rendered to create the content generated by this tag.  The tags in the repeater tag
043:         * set are as follows:
044:         * <table border="1" cellspacing="0" cellpadding="5" width="75%">
045:         * <tr><td><b>Tag</b></td><td><b>Description</b></td></tr>
046:         * <tr><td>{@link RepeaterHeader}</td><td>Renders once in the {@link #HEADER} state.</td></tr>
047:         * <tr><td>{@link RepeaterItem}</td><td>Renders once in the {@link #ITEM} state.</td></tr>
048:         * <tr><td>{@link RepeaterFooter}</td><td>Renders once in the {@link #FOOTER} state.</td></tr>
049:         * <tr><td>{@link org.apache.beehive.netui.tags.databinding.repeater.pad.Pad}</td><td>Used to convert irregular data sets into regular data sets through padding or truncating the output.</td></tr>
050:         * </table>
051:         * <p>The repeater can render in two modes; the first mode is a simple mode where the body of
052:         * the repeater is rendered once for each item in the data set.  In this case, none of the
053:         * other tags above are present in the repeater body.  For example, the following will
054:         * render an unordered HTML list of items that are list items which contain the lastName, firstName
055:         * of the current "customer" in the data set.</p>
056:         * <pre>
057:         * &lt;ul&gt;
058:         * &lt;netui-data:repeater dataSource="pageInput.customers"&gt;
059:         *     &lt;li&gt;&lt;netui:span value="${container.item.lastName}, ${container.item.firstName}"/&gt;&lt;/li&gt;
060:         * &lt;/netui-data:repeater&gt;
061:         * &lt;/ul&gt;
062:         * </pre>
063:         * <p>The second mode is a more structured mode
064:         * of rendering where the tags above are used to delineate iteration boundaries on the body of
065:         * a &lt;netui-data:repeater> tag.  In this case, if one of the above tags is present,
066:         * any content directly in the body of the repeater is not rendered; rather, the content
067:         * inside the structured tags of the repeater is rendered.</p>
068:         * <p>For example, the following will render the same output as the example
069:         * shown above, but it uses the structured tags for rendering the
070:         * <code>pageFlow.customers</code> expression:</p>
071:         * <pre>
072:         * &lt;netui-data:repeater dataSource="pageInput.customers"&gt;
073:         *     &lt;netui-data:repeaterHeader&gt;
074:         *         &lt;ul&gt;
075:         *     &lt;/netui-data:repeaterHeader&gt;
076:         *     &lt;netui-data:repeaterItem&gt;
077:         *         &lt;li&gt;&lt;netui:span value="${container.item.lastName}, ${container.item.firstName}"/&gt;&lt;/li&gt;
078:         *     &lt;/netui-data:repeaterItem&gt;
079:         *     &lt;netui-data:repeaterFooter&gt;
080:         *         &lt;/ul&gt;
081:         *     &lt;/netui-data:repeaterFooter&gt;
082:         * &lt;/netui-data:repeater&gt;
083:         * </pre>
084:         *
085:         * @jsptagref.tagdescription <p>Iterates over a data set to render it as HTML.
086:         * The HTML is specified either directly within the the body of
087:         * &lt;netui-data:repeater> tag or within an associated set of "helper" tags.
088:         * The "helper" tags are listed below.
089:         * <p/>
090:         * <blockquote>
091:         * <table border="1" cellspacing="0" cellpadding="5" width="90%">
092:         * <tr><td><b>Tag</b></td><td><b>Description</b></td></tr>
093:         * <tr><td>{@link RepeaterHeader}</td><td>Renders once at the start of the iteration.</td></tr>
094:         * <tr><td>{@link RepeaterItem}</td><td>Renders once for each iteration.</td></tr>
095:         * <tr><td>{@link RepeaterFooter}</td><td>Renders once at the end of the iteration.</td></tr>
096:         * <tr><td>{@link org.apache.beehive.netui.tags.databinding.repeater.pad.Pad}</td><td>Used to convert
097:         * irregular data sets into regular data sets through padding
098:         * or truncating the output.</td></tr>
099:         * </table>
100:         * </blockquote>
101:         * <p/>
102:         * <p>The &lt;netui-data:repeater> tag can render in two modes; the first mode is a simple mode where the body of
103:         * the &lt;netui-data:repeater> tag is rendered once for each item in the data set.  In this case, none of the
104:         * other tags above are present in the repeater body.  For example, the following will
105:         * render the items in the "customers" data set as an unordered HTML list.</p>
106:         * <p/>
107:         * <pre>     &lt;ul&gt;
108:         *         &lt;netui-data:repeater dataSource="pageInput.customers"&gt;
109:         *             &lt;li&gt;&lt;netui:span value="${container.item.lastName}, ${container.item.firstName}"/&gt;&lt;/li&gt;
110:         *         &lt;/netui-data:repeater&gt;
111:         *     &lt;/ul&gt;</pre>
112:         * <p/>
113:         * <p>The second mode is a more structured mode
114:         * of rendering where the "helper" tags
115:         * are used to define the rendering of the data set.  In this case, if one of the helper tags
116:         * is present,
117:         * any HTML markup directly in the body of the &lt;netui-data:repeater> tag is not rendered; rather, the HTML markup
118:         * inside the helper tags is rendered.</p>
119:         * <p>For example, the following will render the same output as the example
120:         * shown above, but it uses the "helper" tags for rendering the
121:         * HTML markup:</p>
122:         * <p/>
123:         * <pre>
124:         *     &lt;netui-data:repeater dataSource="pageInput.customers"&gt;
125:         *         &lt;netui-data:repeaterHeader&gt;
126:         *             &lt;ul&gt;
127:         *         &lt;/netui-data:repeaterHeader&gt;
128:         *         &lt;netui-data:repeaterItem&gt;
129:         *             &lt;li&gt;&lt;netui:span value="${container.item.lastName}, ${container.item.firstName}"/&gt;&lt;/li&gt;
130:         *         &lt;/netui-data:repeaterItem&gt;
131:         *         &lt;netui-data:repeaterFooter&gt;
132:         *             &lt;/ul&gt;
133:         *         &lt;/netui-data:repeaterFooter&gt;
134:         *     &lt;/netui-data:repeater&gt;</pre>
135:         * @example The following sample renders the data set as an HTML table.  The table has two columns, "index" and "name",
136:         * and each iteration over the data set is rendered as a row of the table.
137:         * <p/>
138:         * <pre>    &lt;netui-data:repeater dataSource="pageInput.myDataSet">
139:         *        &lt;netui-data:repeaterHeader>
140:         *            &lt;table border="1">
141:         *                &lt;tr>
142:         *                    &lt;td>&lt;b>index&lt;/b>&lt;/td>
143:         *                    &lt;td>&lt;b>name&lt;/b>&lt;/td>
144:         *                &lt;/tr>
145:         *        &lt;/netui-data:repeaterHeader>
146:         *        &lt;netui-data:repeaterItem>
147:         *            &lt;tr>
148:         *                &lt;td>
149:         *                    &lt;netui:span value="${container.index}" />
150:         *                &lt;/td>
151:         *                &lt;td>
152:         *                    &lt;netui: value="${container.item}" />
153:         *                &lt;/td>
154:         *            &lt;/tr>
155:         *        &lt;/netui-data:repeaterItem>
156:         *        &lt;netui-data:repeaterFooter>
157:         *            &lt;/table>
158:         *        &lt;/netui-data:repeaterFooter>
159:         *    &lt;/netui-data:repeater></pre>
160:         * @netui:tag name="repeater" description="A markup-generic tag that repeats over a data set, and renders the data onto the page."
161:         */
162:        public class Repeater extends AbstractClassicTag implements 
163:                IDataAccessProvider, TryCatchFinally {
164:
165:            private static final Logger LOGGER = Logger
166:                    .getInstance(Repeater.class);
167:
168:            /**
169:             * A Repeater rendering state that signals the beginning of repeater rendering.
170:             */
171:            public static final int INIT = 0;
172:
173:            /**
174:             * A Repeater rendering state that signals the rendering of the HEADER.
175:             * The body renders in the HEADER state once.
176:             */
177:            public static final int HEADER = 1;
178:
179:            /**
180:             * A Repeater rendering state that signals the rendering of the ITEM.
181:             * The body renders in the ITEM state once for each item in the
182:             * data set.
183:             */
184:            public static final int ITEM = 2;
185:
186:            /**
187:             * A Repeater rendering state that signals the rendering of the FOOTER.
188:             * The body renders in the FOOTER state once.
189:             */
190:            public static final int FOOTER = 3;
191:
192:            /**
193:             * A Repeater rendering state that signals the end of repeater rendering.
194:             */
195:            public static final int END = 4;
196:
197:            private boolean _ignoreNulls = false;
198:            private boolean _haveKids = false;
199:            private boolean _containerInPageContext = false;
200:            private int _currentIndex = -1;
201:            private int _renderedItems = 0;
202:            private int _renderState = INIT;
203:            private Object _defaultText = null;
204:            private Object _currentItem = null;
205:            private String _dataSource = null;
206:            private Iterator _iterator = null;
207:            private PadContext _padContext = null;
208:            private InternalStringBuilder _contentBuffer = null;
209:
210:            /**
211:             * Get the name of this tag.  This is used to identify the type of this tag
212:             * for reporting tag errors.
213:             *
214:             * @return a constant String representing the name of this tag.
215:             */
216:            public String getTagName() {
217:                return "Repeater";
218:            }
219:
220:            /**
221:             * Set a boolean that describes whether the repeater should ignore null
222:             * items encountered while iterating over a data set.
223:             *
224:             * @param ignoreNulls whether or not to ignore nulls
225:             * @jsptagref.attributedescription
226:             * Boolean. If set to true, any null iteration items in the data set will be ignored.
227:             * @jsptagref.attributesyntaxvalue <i>boolean_ignoreNulls</i>
228:             * @netui:attribute required="false"
229:             */
230:            public void setIgnoreNulls(boolean ignoreNulls) {
231:                _ignoreNulls = ignoreNulls;
232:            }
233:
234:            /**
235:             * @param padContext
236:             */
237:            public void setPadContext(PadContext padContext) {
238:                if (_padContext == null)
239:                    _padContext = padContext;
240:
241:                LOGGER.debug("Repeater has a padContext with text: "
242:                        + _padContext);
243:
244:                return;
245:            }
246:
247:            /**
248:             * Set the text that will be rendered if the dataSource expression
249:             * references a null object and the defaultText attribute is non-null.
250:             *
251:             * @param defaultText the default text
252:             * @jsptagref.attributedescription
253:             * The text to render if the <code>dataSource</code> attribute references a null data set.
254:             * @jsptagref.attributesyntaxvalue <i>string_defaultText</i>
255:             * @netui:attribute required="false" rtexprvalue="true"
256:             */
257:            public void setDefaultText(Object defaultText) {
258:                _defaultText = defaultText;
259:            }
260:
261:            /**
262:             * Get the index of the current iteration through the body of this tag.  This
263:             * data can be accessed using the expression <code>container.index</code>
264:             * on an attribute of a databindable NetUI tag that is contained within the
265:             * repeating body of this tag.  This expression is only valid when the dataset
266:             * is being rendered.
267:             *
268:             * @return the integer index of the current data item in the data set
269:             * @see org.apache.beehive.netui.script.common.IDataAccessProvider
270:             */
271:            public int getCurrentIndex() {
272:                return _currentIndex;
273:            }
274:
275:            /**
276:             * Get the item that is currently being rendered by this repeating tag.
277:             * This can be accessed using the expression <code>expression.item</code>
278:             * on an attribute of a databindable NetUI tag that is contained within
279:             * the repeating body of this tag.  The expression is only valid when the dataset
280:             * is being rendered.
281:             *
282:             * @return the current item in the data set
283:             * @see org.apache.beehive.netui.script.common.IDataAccessProvider
284:             */
285:            public Object getCurrentItem() {
286:                return _currentItem;
287:            }
288:
289:            /**
290:             * Get the metadata for the current item.  This method is not supported by
291:             * this tag.
292:             *
293:             * @throws UnsupportedOperationException this tag does not support this method from the IDataAccessProvider interface
294:             * @see org.apache.beehive.netui.script.common.IDataAccessProvider
295:             */
296:            public Object getCurrentMetadata() {
297:                LocalizedUnsupportedOperationException uoe = new LocalizedUnsupportedOperationException(
298:                        "The "
299:                                + getTagName()
300:                                + "does not export metadata for its iterated items.");
301:                uoe.setLocalizedMessage(Bundle.getErrorString(
302:                        "Tags_DataAccessProvider_metadataUnsupported",
303:                        new Object[] { getTagName() }));
304:                throw uoe;
305:            }
306:
307:            /**
308:             * Get the parent IDataAccessProvider for this tag.  If this tag is contained within
309:             * a IDataAccessProvider, the containing IDataAccessProvider is available through the
310:             * expression <code>container.container</code>.  Any valid properties of the
311:             * parent IDataAccessProvider can be accessed through this expression.  This method
312:             * will return null if there is no parent IDataAccessProvider
313:             *
314:             * @return a containing IDataAccessProvider if one exists, null otherwise.
315:             * @see org.apache.beehive.netui.script.common.IDataAccessProvider
316:             */
317:            public IDataAccessProvider getProviderParent() {
318:                IDataAccessProvider dap = (IDataAccessProvider) SimpleTagSupport
319:                        .findAncestorWithClass(this , IDataAccessProvider.class);
320:                return dap;
321:            }
322:
323:            /**
324:             * Get the current render state for the repeater.  This tag is used by child tags
325:             * to access the current location in the repeater's rendering lifecycle.
326:             *
327:             * @return an integer that represents the current state of the grid; this is one
328:             *         of {@link #INIT}, {@link #HEADER}, {@link #ITEM},{@link #FOOTER}, or {@link #END}.
329:             */
330:            public int getRenderState() {
331:                return _renderState;
332:            }
333:
334:            /**
335:             * Add content to the content that is being buffered by this tag.  All content
336:             * written by the body of this tag is added to this buffer.  The buffer is rendered
337:             * at the end of the tag's lifecycle if no fatal errors have occurred during this
338:             * tag's lifecycle.
339:             *
340:             * @param content content that this tag should render.
341:             */
342:            public void addContent(String content) {
343:                if (_contentBuffer == null) {
344:                    int size = (content != null ? (5 * content.length()) : 1024);
345:                    _contentBuffer = new InternalStringBuilder(size);
346:                }
347:
348:                _contentBuffer.append(content);
349:            }
350:
351:            /**
352:             * Method used by tags in the repeater tag set to register the presence of a contained
353:             * tag.  When registered, the repeater will change the way in which it renders to
354:             * either use structured or non-structured rendering.
355:             * @param repeaterComponent {@link RepeaterComponent} to register with the Repeater parent
356:             */
357:            public void registerChildTag(RepeaterComponent repeaterComponent) {
358:                _haveKids = true;
359:            }
360:
361:            /**
362:             * Start rendering the repeater.
363:             * @return {@link #SKIP_BODY} if an error occurs; {@link #EVAL_BODY_BUFFERED} otherwise
364:             * @throws JspException if an error occurs that can not be reported in the page
365:             */
366:            public int doStartTag() throws JspException {
367:                Object source = evaluateDataSource();
368:
369:                // report any errors that may have occured 
370:                if (hasErrors())
371:                    return SKIP_BODY;
372:
373:                _renderState = INIT;
374:
375:                boolean empty = false;
376:                if (source != null) {
377:                    _iterator = IteratorFactory.createIterator(source);
378:                    if (_iterator == null) {
379:                        LOGGER.warn(Bundle
380:                                .getString("Tags_Repeater_nullIterator"));
381:                        _iterator = Collections.EMPTY_LIST.iterator();
382:                    }
383:
384:                    if (_iterator.hasNext()) {
385:                        _currentIndex = 0;
386:                        _currentItem = _iterator.next();
387:
388:                        if (_ignoreNulls && _currentItem == null) {
389:                            /*
390:                              doStartTag doesn't know if the repeater is structured or unstructured
391:                              thus, if ignoreNulls is true, it's going to make an attempt to go
392:                              through the body with a non-null item.  if there are no non-null
393:                              items in the data structure, the doAfterBody method will handle
394:                              this correctly, but a data structure with a null first item
395:                              will render the same as a data structure with a null second item
396:                             */
397:                            advanceToNonNullItem();
398:
399:                            /*
400:                               this null check needs to re-run here because the advanceToNonNullItem method
401:                               side-effects the _currentItem.
402:                             */
403:                            if (_currentItem == null)
404:                                empty = true;
405:                        }
406:                    }
407:                    /* there is no data set of there are zero items in the iterator */
408:                    else
409:                        empty = true;
410:                }
411:                /* the dataSource evaluated to null */
412:                else {
413:                    _iterator = Collections.EMPTY_LIST.iterator();
414:                    empty = true;
415:                }
416:
417:                if (empty) {
418:                    /* if the defaultText attribute is non-null, it will be evaluated as an expression and rendered to the page */
419:                    if (_defaultText != null)
420:                        addContent(_defaultText.toString());
421:                    return SKIP_BODY;
422:                } else {
423:                    DataAccessProviderStack.addDataAccessProvider(this ,
424:                            pageContext);
425:                    _containerInPageContext = true;
426:                    return EVAL_BODY_BUFFERED;
427:                }
428:            }
429:
430:            /**
431:             * <p>
432:             * Continue rendering the repeater changing the render state or advancing to a new data item
433:             * as needed.
434:             * </p>
435:             * @return {@link #SKIP_BODY} if an error occurs or the data set has been rendered; {@link #EVAL_BODY_AGAIN} otherwise
436:             */
437:            public int doAfterBody() {
438:
439:                if (hasErrors())
440:                    return SKIP_BODY;
441:
442:                LOGGER
443:                        .debug("structured repeater: " + _haveKids
444:                                + " render state: "
445:                                + renderStateToString(_renderState));
446:
447:                /*
448:                  structured rendering of the repeater; body content is ignored and real
449:                  content is rendered through cooperating nested tags
450:                 */
451:                if (_haveKids)
452:                    return renderStructured();
453:                /*
454:                  unstructured rendering of the repeater; this means that there isn't
455:                  a repeater(Header|Item|Footer) inside the body of the repeater.
456:                 */
457:                else {
458:                    if (bodyContent != null) {
459:                        addContent(bodyContent.getString());
460:                        bodyContent.clearBody();
461:                    }
462:
463:                    if (_iterator.hasNext()) {
464:                        _currentIndex++;
465:                        _currentItem = _iterator.next();
466:
467:                        if (_ignoreNulls && _currentItem == null) {
468:                            advanceToNonNullItem();
469:
470:                            /* ignoring null items and no more non-null items, so skip to doEndTag() */
471:                            if (_currentItem == null)
472:                                return SKIP_BODY;
473:                        }
474:
475:                        /* found another item; re-render the repeater's body */
476:                        return EVAL_BODY_AGAIN;
477:                    }
478:                    /* no more items; skip to doEndTag() */
479:                    else
480:                        return SKIP_BODY;
481:                }
482:            }
483:
484:            /**
485:             * Complete rendering the repeater.
486:             * @return {@link #EVAL_PAGE}
487:             * @throws JspException if an error occurs that can not be reported in the page
488:             */
489:            public int doEndTag() throws JspException {
490:
491:                if (hasErrors())
492:                    reportErrors();
493:                else if (_contentBuffer != null)
494:                    write(_contentBuffer.toString());
495:
496:                return EVAL_PAGE;
497:            }
498:
499:            public void doFinally() {
500:                localRelease();
501:            }
502:
503:            public void doCatch(Throwable t) throws Throwable {
504:                throw t;
505:            }
506:
507:            /**
508:             * Reset all of the fields of this tag.
509:             */
510:            protected void localRelease() {
511:                super .localRelease();
512:                _currentItem = null;
513:                _currentIndex = -1;
514:                _iterator = null;
515:                _defaultText = null;
516:                _renderState = INIT;
517:                _haveKids = false;
518:                _contentBuffer = null;
519:                _padContext = null;
520:                _ignoreNulls = false;
521:                _renderedItems = 0;
522:                if (_containerInPageContext) {
523:                    DataAccessProviderStack
524:                            .removeDataAccessProvider(pageContext);
525:                    _containerInPageContext = false;
526:                }
527:            }
528:
529:            /**
530:             * Render a the repeater using the full repeater lifecycle.  This
531:             * method is executed after each pass through the body if there
532:             * are tags from the repeater tag set in the body of this repeater.
533:             * This method ensures that the repeater tag runs as a full state
534:             * machine for these tags.
535:             *
536:             * @return EVAL_BODY_AGAIN unless the lifecycle has completed; then return SKIP_BODY
537:             */
538:            /* todo: perf -- optimize the number of trips through the body by ignoring the header / footer when necessary */
539:            private int renderStructured() {
540:                if (LOGGER.isDebugEnabled() && _padContext != null)
541:                    LOGGER.debug("\ncurrentIndex: " + _currentIndex + "\n"
542:                            + "checkMaxRepeat: "
543:                            + _padContext.checkMaxRepeat(_currentIndex) + "\n"
544:                            + "checkMinRepeat: "
545:                            + _padContext.checkMinRepeat(_currentIndex) + "\n");
546:
547:                if (_renderState == INIT) {
548:                    _renderState = HEADER;
549:                    return EVAL_BODY_AGAIN;
550:                }
551:
552:                if (_renderState == HEADER) {
553:                    assert _renderedItems == 0;
554:
555:                    /* this would only happen if Pad.maxRepeat == 0 */
556:                    if (_padContext != null
557:                            && _padContext.checkMaxRepeat(_renderedItems)) {
558:                        _renderState = FOOTER;
559:                        return EVAL_BODY_AGAIN;
560:                    }
561:
562:                    if (_currentItem == null && _ignoreNulls) {
563:                        advanceToNonNullItem();
564:
565:                        /* no non-null item was found; render the footer */
566:                        if (_currentItem == null) {
567:                            doPadding();
568:                            // render the header
569:                            _renderState = FOOTER;
570:                        }
571:                        /* non-null item found; it's not the 0th item; render it */
572:                        else
573:                            _renderState = ITEM;
574:                    }
575:                    /* 0th item is non-null; render it */
576:                    else
577:                        _renderState = ITEM;
578:
579:                    return EVAL_BODY_AGAIN;
580:                }
581:
582:                if (_renderState == ITEM) {
583:                    _renderedItems++;
584:
585:                    /* check that the maximum number of items to render has *not* been reached */
586:                    if (_iterator.hasNext()
587:                            && (_padContext == null || (_padContext != null && !_padContext
588:                                    .checkMaxRepeat(_renderedItems)))) {
589:                        _currentIndex++;
590:                        _currentItem = _iterator.next();
591:
592:                        if (_ignoreNulls && _currentItem == null) {
593:                            advanceToNonNullItem();
594:
595:                            /* last item */
596:                            if (_currentItem == null) {
597:                                doPadding();
598:
599:                                /* render the header */
600:                                _renderState = FOOTER;
601:                                return EVAL_BODY_AGAIN;
602:                            }
603:                        }
604:
605:                        /* if _ignoreNulls is false, the _currentItem may be null here */
606:                        return EVAL_BODY_AGAIN;
607:                    }
608:                    /*
609:                     have finished rendering items for some reason:
610:                      1) there isn't a next item
611:                      2) reached the maximum number of items to render
612:                      So:
613:                      1) pad if necessary
614:                      2) render the footer
615:                     */
616:                    else {
617:                        doPadding();
618:
619:                        _renderState = FOOTER;
620:                        return EVAL_BODY_AGAIN;
621:                    }
622:                }
623:
624:                if (_renderState == FOOTER) {
625:                    _renderState = END;
626:                    return SKIP_BODY;
627:                }
628:
629:                return SKIP_BODY;
630:            }
631:
632:            /**
633:             * <p/>
634:             * Internal utility method.
635:             * </p>
636:             * </p>
637:             * This is called in places where the repeater needs to move to the next
638:             * non-null item in the data set to render.  This occurs when the
639:             * current data item is null and the <code>ignoreNulls</code>
640:             * flag has been set to skip rendering null items in the data set.
641:             * </p>
642:             * <p/>
643:             * This method side-effects to advance the iterator to the next
644:             * non-null item or the end if there are zero remaining non-null
645:             * items.
646:             * </p>
647:             * <p/>
648:             * At the end, the <code>currentItem</code> may be null, and the
649:             * <code>currentIndex</code> will reference either the integer
650:             * location in the data structure of the non-null data item, or
651:             * it will reference the end of the data structure.
652:             * </p>
653:             */
654:            private final void advanceToNonNullItem() {
655:                assert _iterator != null;
656:                assert _currentItem == null;
657:
658:                while (_iterator.hasNext() && _currentItem == null) {
659:                    _currentItem = _iterator.next();
660:                    _currentIndex++;
661:                }
662:            }
663:
664:            /**
665:             * When using the repeater's pad tag, it is possible to require a minimum number of
666:             * items render in the repeater.  This method pads out the number of items until it
667:             * reaches the {@link org.apache.beehive.netui.tags.databinding.repeater.pad.PadContext}'s
668:             * <code>minRepeat</code> property.
669:             */
670:            private final void doPadding() {
671:                if (_padContext != null
672:                        && !_padContext.checkMinRepeat(_renderedItems)) {
673:                    /*
674:                      since padding is now running, un-set the current item so that the last
675:                      item isn't accessible during any later data binding
676:                     */
677:                    _currentItem = null;
678:
679:                    for (int i = _renderedItems; !_padContext.checkMinRepeat(i); i++) {
680:                        _currentIndex++;
681:                        addContent(_padContext.getPadText());
682:                    }
683:                }
684:            }
685:
686:            /**
687:             * An internal method that turns the current render state into a string for debugging.
688:             */
689:            private static final String renderStateToString(int state) {
690:                switch (state) {
691:                case INIT:
692:                    return "INIT";
693:                case HEADER:
694:                    return "HEADER";
695:                case ITEM:
696:                    return "ITEM";
697:                case FOOTER:
698:                    return "FOOTER";
699:                case END:
700:                    return "END";
701:                default:
702:                    return "INVALID STATE";
703:                }
704:            }
705:
706:            /**
707:             * Return an <code>ArrayList</code> which represents a chain of <code>INameInterceptor</code>
708:             * objects.  This method by default returns <code>null</code> and should be overridden
709:             * by objects that support naming.
710:             * @return an <code>ArrayList</code> that will contain <code>INameInterceptor</code> objects.
711:             */
712:            protected List getNamingChain() {
713:                return AbstractClassicTag.DefaultNamingChain;
714:            }
715:
716:            /**
717:             * Sets the tag's data source (can be an expression).
718:             * @param dataSource - the data source
719:             * @jsptagref.attributedescription <p>The <code>dataSource</code> attribute determines both
720:             * (1) the source of populating data for the tag and
721:             * (2) the object to which the tag submits data.
722:             *
723:             * <p>For example, assume that the Controller file (= JPF file) contains
724:             * a Form Bean with the property foo.  Then the following &lt;netui:textBox> tag will
725:             * (1) draw populating data from the Form Bean's foo property and (2)
726:             * submit user defined data to the same property.
727:             *
728:             * <p>&nbsp;&nbsp;&nbsp;&nbsp;<code>&lt;netui:textBox dataSource="actionForm.foo" /></code>
729:             *
730:             * <p>The <code>dataSource</code> attribute takes either a data binding expression or
731:             * the name of a Form Bean property.  In the
732:             * above example, <code>&lt;netui:textBox dataSource="foo" /></code>
733:             * would have the exactly same behavior.
734:             *
735:             * <p>When the tag is used to submit data, the data binding expression must
736:             * refer to a Form Bean property.
737:             * In cases where the tag is not used to submit data, but is used for
738:             * displaying data only, the data
739:             * binding expression need not refer to a Form Bean property.  For example,
740:             * assume that myIterativeData is a member variable on
741:             * the Controller file ( = JPF file).  The following &lt;netui-data:repeater>
742:             * tag draws its data from myIterativeData.
743:             *
744:             * <p>&nbsp;&nbsp;&nbsp;&nbsp;<code>&lt;netui-data:repeater dataSource="pageFlow.myIterativeData"></code>
745:             * @jsptagref.attributesyntaxvalue <i>expression_datasource</i>
746:             * @netui:attribute required="true"
747:             */
748:            public void setDataSource(String dataSource) {
749:                _dataSource = dataSource;
750:            }
751:
752:            /**
753:             * Gets the tag's data source (can be an expression).
754:             * @return the data source
755:             */
756:            public String getDataSource() {
757:                return "{" + _dataSource + "}";
758:            }
759:
760:            /**
761:             * Return the Object that is represented by the specified data source.
762:             * @return Object
763:             * @throws JspException
764:             */
765:            private Object evaluateDataSource() throws JspException {
766:                ExpressionHandling expr = new ExpressionHandling(this );
767:                String dataSource = getDataSource();
768:                String ds = expr.ensureValidExpression(dataSource,
769:                        "dataSource", "DataSourceError");
770:                if (ds == null)
771:                    return null;
772:
773:                /* have a valid expression */
774:                return expr.evaluateExpression(dataSource, "dataSource",
775:                        pageContext);
776:            }
777:        }
w__ww___.___j___a___va2_s___.___c_o__m___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.