Source Code Cross Referenced for CellRepeater.java in  » Library » Apache-beehive-1.0.2-src » org » apache » beehive » netui » tags » databinding » cellrepeater » 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.cellrepeater 
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.cellrepeater;
020:
021:        import java.util.ArrayList;
022:        import java.util.Iterator;
023:        import java.util.List;
024:        import java.util.Collections;
025:        import javax.servlet.jsp.JspException;
026:        import javax.servlet.jsp.tagext.TryCatchFinally;
027:        import javax.servlet.jsp.tagext.SimpleTagSupport;
028:        import javax.servlet.ServletRequest;
029:
030:        import org.apache.beehive.netui.script.common.IDataAccessProvider;
031:        import org.apache.beehive.netui.script.common.DataAccessProviderStack;
032:        import org.apache.beehive.netui.tags.AbstractClassicTag;
033:        import org.apache.beehive.netui.tags.ExpressionHandling;
034:        import org.apache.beehive.netui.tags.rendering.TagRenderingBase;
035:        import org.apache.beehive.netui.tags.rendering.TableTag;
036:        import org.apache.beehive.netui.tags.rendering.TdTag;
037:        import org.apache.beehive.netui.tags.rendering.TrTag;
038:        import org.apache.beehive.netui.tags.rendering.AbstractRenderAppender;
039:        import org.apache.beehive.netui.tags.rendering.StringBuilderRenderAppender;
040:        import org.apache.beehive.netui.tags.rendering.ConstantRendering;
041:        import org.apache.beehive.netui.util.Bundle;
042:        import org.apache.beehive.netui.util.exception.LocalizedUnsupportedOperationException;
043:        import org.apache.beehive.netui.util.internal.InternalStringBuilder;
044:        import org.apache.beehive.netui.util.iterator.IteratorFactory;
045:        import org.apache.beehive.netui.util.logging.Logger;
046:
047:        /**
048:         * <p/>
049:         * This tag is a repeating, databound tag that renders its body each cell of a table of the specified dimensions.
050:         * The tag is bound to a dataset that is specified in the <code>dataSource</code> attribute.  For each item in
051:         * the data set, the body of this tag is rendered, and NetUI tags in the body that are databound
052:         * can use the <code>container.item</code> syntax to access the "current" data item in the iteration.
053:         * Properties on this data item can be accessed using expressions.
054:         * </p>
055:         * <p>
056:         * The tag will automatically insert the open and close table, row, and cell tags which will comprise
057:         * the table that is rendered.  Style attributes may be set using attributes on this tag in order to
058:         * cusotmize the tag's final appearance.  The dimensions of the table are specified by using at least
059:         * one of the attributes columns and rows.  If only one is specified, the other will be inferred by
060:         * using the size of the given data set.  As a result, the entire dataset will be rendered.  For example,
061:         * if a table should be four columns wide and the data set has twenty items, the resulting table will
062:         * have five rows.  If the data set is fewer items than the number of cells that should be rendered,
063:         * the cells are padded with HTML table cells:
064:         * </p>
065:         * <pre>
066:         *     &lt;td&gt;&amp;nbsp;&lt;/td&gt;
067:         * </pre>
068:         * <p/>
069:         * This will prevent rendering a malformed HTML table.  If the number of cells to render is smaller than
070:         * the fully specified dimensions of the table, only this number of cells will be rendered.  For example,
071:         * if the data set is size fifty but the <code>rows</code> and the <code>columns</code> attributes are
072:         * both seven, only the first forty-nine items in the dataset will be rendered and the fiftieth
073:         * will not be shown.  The values of the <code>rows</code> and the <code>columns</code> can be databound with
074:         * an expression; in this case, each value will be converted into an integer.  An error will be reported
075:         * on the page if this conversion fails.
076:         * </p><p>
077:         * This tag implements the {@link IDataAccessProvider} interface which provides tags access to the "current"
078:         * data item.  Properties on the <code>IDataAccessProvider</code> interface are available through the
079:         * "container" binding context, which can be used inside of the body of the CellRepeater.  Properties of
080:         * the <code>IDataAccessProvider</code> interface that are available include:
081:         * <table border="1" cellspacing="0" cellpadding="5" width="75%">
082:         * <tr><td><b>Name</b></td><td><b>Description</b></td></tr>
083:         * <tr><td>index</td><td>the current index in the iteration; this index is absolute to the dataset</td></tr>
084:         * <tr><td>parent</td><td>any <code>IDataAccessProvider</code> parent of this tag</td></tr>
085:         * <tr><td>item</td><td>the current data item</td></tr>
086:         * </table>
087:         * </p>
088:         * <p/>
089:         * <b>Note:</b> the metadata property of the <code>container</code> binding context is not supported
090:         * on the CellRepeater.
091:         * </p>
092:         *
093:         * @jsptagref.tagdescription
094:         * <p/>
095:         * This tag is a repeating, databound tag that renders its body each cell of a table of the specified dimensions.
096:         * The tag is bound to a dataset that is specified in the <code>dataSource</code> attribute.  For each item in
097:         * the data set, the body of this tag is rendered, and NetUI tags in the body that are databound
098:         * can use the <code>container.item</code> syntax to access the "current" data item in the iteration.
099:         * Properties on this data item can be accessed using expressions.
100:         * </p>
101:         * <p>
102:         * The tag will automatically insert the open and close table, row, and cell tags which will comprise
103:         * the table that is rendered.  Style attributes may be set using attributes on this tag in order to
104:         * cusotmize the tag's final appearance.  The dimensions of the table are specified by using at least
105:         * one of the attributes columns and rows.  If only one is specified, the other will be inferred by
106:         * using the size of the given data set.  As a result, the entire dataset will be rendered.  For example,
107:         * if a table should be four columns wide and the data set has twenty items, the resulting table will
108:         * have five rows.  If the data set is fewer items than the number of cells that should be rendered,
109:         * the cells are padded with HTML table cells:
110:         * </p>
111:         * <pre>
112:         *     &lt;td&gt;&amp;nbsp;&lt;/td&gt;
113:         * </pre>
114:         * <p/>
115:         * This will prevent rendering a malformed HTML table.  If the number of cells to render is smaller than
116:         * the fully specified dimensions of the table, only this number of cells will be rendered.  For example,
117:         * if the data set is size fifty but the <code>rows</code> and the <code>columns</code> attributes are
118:         * both seven, only the first forty-nine items in the dataset will be rendered and the fiftieth
119:         * will not be shown.  The values of the <code>rows</code> and the <code>columns</code> can be databound with
120:         * an expression; in this case, each value will be converted into an integer.  An error will be reported
121:         * on the page if this conversion fails.
122:         * </p><p>
123:         * This tag implements the {@link IDataAccessProvider} interface which provides tags access to the "current"
124:         * data item.  Properties on the <code>IDataAccessProvider</code> interface are available through the
125:         * "container" binding context, which can be used inside of the body of the CellRepeater.  Properties of
126:         * the <code>IDataAccessProvider</code> interface that are available include:
127:         * <table border="1" cellspacing="0" cellpadding="5" width="75%">
128:         * <tr><td><b>Name</b></td><td><b>Description</b></td></tr>
129:         * <tr><td>index</td><td>the current index in the iteration; this index is absolute to the dataset</td></tr>
130:         * <tr><td>parent</td><td>any <code>IDataAccessProvider</code> parent of this tag</td></tr>
131:         * <tr><td>item</td><td>the current data item</td></tr>
132:         * </table>
133:         * </p>
134:         * <p/>
135:         * <b>Note:</b> the metadata property of the <code>container</code> binding context is not supported
136:         * on the CellRepeater.
137:         * </p>
138:         *
139:         * @example
140:         * In this example, the &lt;netui-data:cellRepeater> tag creates a table with the number of columns set
141:         * given as <code>${pageFlow.numColumns}</code> and as many rows as necessary to display all the items in the
142:         * <code>pageFlow.itemArray</code> data set.
143:         * <pre>
144:         *    &lt;netui-data:cellRepeater dataSource="pageFlow.itemArray" columns="pageFlow.numColumns">
145:         *        Item: &lt;netui:span value="${container.item}"/>
146:         *    &lt;/netui-data:cellRepeater>
147:         * </pre>
148:         * @netui:tag name="cellRepeater"
149:         *            description="A repeating, databound tag that renders its body into each cell of a table of the specified dimensions."
150:         */
151:        public class CellRepeater extends AbstractClassicTag implements 
152:                IDataAccessProvider, TryCatchFinally {
153:
154:            private static final Logger LOGGER = Logger
155:                    .getInstance(CellRepeater.class);
156:            private static final int DIMENSION_DEFAULT_VALUE = -1;
157:            private static final TableTag.State STATE_TABLE = new TableTag.State();
158:            private static final TrTag.State STATE_TR = new TrTag.State();
159:            private static final TdTag.State STATE_TD = new TdTag.State();
160:
161:            private boolean _valid = true;
162:            private boolean _verticalRepeat = false;
163:            private boolean _containerInPageContext = false;
164:            private int _columns = DIMENSION_DEFAULT_VALUE;
165:            private int _rows = DIMENSION_DEFAULT_VALUE;
166:            private int _currentIndex = -1;
167:            private int _currentRow = -1;
168:            private int _currentColumn = -1;
169:
170:            private ArrayList _dataList = null;
171:            private Object _currentItem = null;
172:            private String _dataSource = null;
173:            private String _altCellClass = null;
174:            private String _cellClass = null;
175:            private ConstantRendering _htmlConstantRendering = null;
176:            private TagRenderingBase _tableRenderer = null;
177:            private TagRenderingBase _trRenderer = null;
178:            private TagRenderingBase _tdRenderer = null;
179:            private TableTag.State _tableState = null;
180:            private TdTag.State _tdState = null;
181:            private TrTag.State _trState = null;
182:            private InternalStringBuilder _sb = null;
183:            private AbstractRenderAppender _appender = null;
184:
185:            /**
186:             * Get the name of this tag.  This is used to identify the type of this tag
187:             * for reporting tag errors.
188:             *
189:             * @return a constant String representing the name of this tag.
190:             */
191:            public String getTagName() {
192:                return "CellRepeater";
193:            }
194:
195:            /**
196:             * The HTML style class that is rendered on the HTML table.  For example, if the row class is "tableClass",
197:             * each opening table tag is:
198:             * <pre>
199:             *     &lt;table class="tableClass"&gt;
200:             * </pre>
201:             *
202:             * @param tableClass the name of a style class in a CSS
203:             * @jsptagref.attributedescription
204:             * The HTML style class that is rendered on the HTML table.  For example, if the row class is "tableClass",
205:             * each opening table tag is:
206:             * <pre>
207:             *     &lt;table class="tableClass"&gt;
208:             * </pre>
209:             * @jsptagref.attributesyntaxvalue <i>string_class</i>
210:             * @netui:attribute required="false"
211:             */
212:            public void setTableClass(String tableClass) {
213:                if ("".equals(tableClass))
214:                    return;
215:                _tableState = new TableTag.State();
216:                _tableState.styleClass = tableClass;
217:            }
218:
219:            /**
220:             * Set the HTML style class that is rendered on each HTML table row that
221:             * is opened by this tag.  For example, if the row class is "rowClass",
222:             * each opening table row tag is:
223:             * <pre>
224:             *     &lt;tr class="rowClass"&gt;
225:             * </pre>
226:             *
227:             * @param rowClass the name of a style class in the CSS
228:             * @jsptagref.attributedescription
229:             * Set the HTML style class that is rendered on each HTML table row that
230:             * is opened by this tag.  For example, if the row class is "rowClass",
231:             * each opening table row tag is:
232:             * <pre>
233:             *     &lt;tr class="rowClass"&gt;
234:             * </pre>
235:             * @jsptagref.attributesyntaxvalue <i>string_class</i>
236:             * @netui:attribute required="false"
237:             */
238:            public void setRowClass(String rowClass) {
239:                if ("".equals(rowClass))
240:                    return;
241:                _trState = new TrTag.State();
242:                _trState.styleClass = rowClass;
243:            }
244:
245:            /**
246:             * Set the HTML style class that is rendered on each HTML table cell that
247:             * is opened by this tag.  For example, if the cell class is "cellClass",
248:             * each opening table cell tag is:
249:             * <pre>
250:             *     &lt;td class="cellClass"&gt;
251:             * </pre>
252:             *
253:             * @param cellClass the name of a style class in a CSS
254:             * @jsptagref.attributedescription
255:             * Set the HTML style class that is rendered on each HTML table cell that
256:             * is opened by this tag.  For example, if the cell class is "cellClass",
257:             * each opening table cell tag is:
258:             * <pre>
259:             *     &lt;td class="cellClass"&gt;
260:             * </pre>
261:             * @jsptagref.attributesyntaxvalue <i>string_class</i>
262:             * @netui:attribute required="false"
263:             */
264:            public void setCellClass(String cellClass) {
265:                if ("".equals(cellClass))
266:                    return;
267:                _cellClass = cellClass;
268:            }
269:
270:            /**
271:             * Set the HTML style class that is rendered on each HTML table cell that
272:             * is opened by this tag.  The starting cell is alternated for each row, which
273:             * results in a checkerboard colored table being displayed.  For example, if the
274:             * alteranting cell class is \"alternatingCellClass\", every other table cell
275:             * tag is:
276:             * <pre>
277:             *     &lt;td cell="alternatingCellClass"&gt;
278:             * </pre>
279:             *
280:             * @param alternatingCellClass the name of a style class in a CSS
281:             * @jsptagref.attributedescription
282:             * The HTML style class that is rendered on alternating table cells.
283:             * The starting cell is alternated for each row, which
284:             * results in a checkerboard colored table being displayed.  For example, if the
285:             * alteranting cell class is "alternatingCellClass", every other table cell
286:             * tag is:
287:             * <pre>
288:             *     &lt;td cell="alternatingCellClass"&gt;</pre>
289:             * @jsptagref.attributesyntaxvalue <i>string_class</i>
290:             * @netui:attribute required="false"
291:             */
292:            public void setAlternatingCellClass(String alternatingCellClass) {
293:                if ("".equals(alternatingCellClass))
294:                    return;
295:                _altCellClass = alternatingCellClass;
296:            }
297:
298:            /**
299:             * This tag can render the items in its dataset horizontally or vertically.  If
300:             * the rows are rendered horizontally, the items in the dataset are rendered
301:             * across each row from top to bottom.  Otherwise, they are rendered down each
302:             * column from left to right.  The default is to render the items horizontally.
303:             *
304:             * @param verticalRepeat if set to <code>true</code>, the dataset is rendered down
305:             *                       each column; otherwise it is rendered across each row, the default.
306:             * @jsptagref.attributedescription
307:             * Boolean. If true the data set is rendered vertically, otherwise it is rendered horizontally.  If
308:             * the rows are rendered horizontally, the items in the data set are rendered
309:             * across each row from top to bottom.  Otherwise, they are rendered down each
310:             * column from left to right.  The default is to render the items horizontally.
311:             * @jsptagref.attributesyntaxvalue <i>boolean_verticalRepeat</i>
312:             * @netui:attribute required="false"
313:             */
314:            public void setVerticalRepeat(boolean verticalRepeat) {
315:                _verticalRepeat = verticalRepeat;
316:            }
317:
318:            /**
319:             * Set the number of columns that should be rendered in the table
320:             * generated by the tag.  If the columns attribute is specified but
321:             * the rows attribute is not, the rows attribute will be inferred
322:             * using the size of the dataset.
323:             *
324:             * @param columns an integer or an expression
325:             * @jsptagref.attributedescription
326:             * Integer. The number of columns that should be rendered in the HTML table.
327:             * If the <code>columns</code> attribute is specified but
328:             * the <code>rows</code> attribute is not, the <code>rows</code> attribute will be inferred
329:             * using the size of the data set.
330:             * @jsptagref.attributesyntaxvalue <i>integer_columns</i>
331:             * @netui:attribute required="false" rtexprvalue="true"
332:             */
333:            public void setColumns(int columns) {
334:                _columns = columns;
335:            }
336:
337:            /**
338:             * Set the number of rows that should be rendered in the table
339:             * generated by the tag.  If the rows attribute is specified but
340:             * the columns attribute is not, the columns attribute will be
341:             * inferred using the size of the dataset.
342:             *
343:             * @param rows an integer or an expression whose value can be
344:             *             converted into an integer.
345:             * @jsptagref.attributedescription
346:             * Integer. The number of rows that should be rendered in the HTML table.
347:             * If the <code>rows</code> attribute is specified but
348:             * the <code>columns</code> attribute is not, the <code>columns</code> attribute will be
349:             * inferred using the size of the data set.
350:             * @jsptagref.attributesyntaxvalue <i>integer_rows</i>
351:             * @netui:attribute required="false" rtexprvalue="true"
352:             */
353:            public void setRows(int rows) {
354:                _rows = rows;
355:            }
356:
357:            /**
358:             * <p>The <code>dataSource</code> attribute determines both
359:             * (1) the source of populating data for the tag and
360:             * (2) the object to which the tag submits data.
361:             *
362:             * <p>For example, assume that the Controller file (= JPF file) contains
363:             * a Form Bean with the property foo.  Then the following &lt;netui:textBox> tag will
364:             * (1) draw populating data from the Form Bean's foo property and (2)
365:             * submit user defined data to the same property.
366:             *
367:             * <p>&nbsp;&nbsp;&nbsp;&nbsp;<code>&lt;netui:textBox dataSource="actionForm.foo" /></code>
368:             *
369:             * <p>When the tag is used to submit data, the data binding expression must
370:             * refer to a Form Bean property.
371:             * In cases where the tag is not used to submit data, but is used for
372:             * displaying data only, the data
373:             * binding expression need not refer to a Form Bean property.  For example,
374:             * assume that myIterativeData is a member variable on
375:             * the Controller file ( = JPF file).  The following &lt;netui-data:repeater>
376:             * tag draws its data from myIterativeData.
377:
378:             * @param dataSource the data source
379:             * @jsptagref.attributedescription
380:             * <p>The <code>dataSource</code> attribute determines both
381:             * (1) the source of populating data for the tag and
382:             * (2) the object to which the tag submits data.
383:             *
384:             * <p>For example, assume that the Controller file (= JPF file) contains
385:             * a Form Bean with the property foo.  Then the following &lt;netui:textBox> tag will
386:             * (1) draw populating data from the Form Bean's foo property and (2)
387:             * submit user defined data to the same property.
388:             *
389:             * <p>&nbsp;&nbsp;&nbsp;&nbsp;<code>&lt;netui:textBox dataSource="actionForm.foo" /></code>
390:             *
391:             * <p>When the tag is used to submit data, the data binding expression must
392:             * refer to a Form Bean property.
393:             * In cases where the tag is not used to submit data, but is used for
394:             * displaying data only, the data
395:             * binding expression need not refer to a Form Bean property.  For example,
396:             * assume that myIterativeData is a member variable on
397:             * the Controller file ( = JPF file).  The following &lt;netui-data:repeater>
398:             * tag draws its data from myIterativeData.
399:             *
400:             * <p>&nbsp;&nbsp;&nbsp;&nbsp;<code>&lt;netui-data:cellRepeater dataSource="pageFlow.myIterativeData"></code>
401:             * @jsptagref.attributesyntaxvalue <i>expression_datasource</i>
402:             * @netui:attribute required="true"
403:             */
404:            public void setDataSource(String dataSource) {
405:                _dataSource = dataSource;
406:            }
407:
408:            /**
409:             * Prepare to render the dataset that was specified in the dataSource attribute.  The
410:             * dataSource expression is evaluated and the table's dimensions are computed.  If
411:             * there is no data in the dataset but the rows and columns attributes were specified,
412:             * an empty table of the given dimensions is rendered.
413:             *
414:             * @return EVAL_BODY_BUFFERED or SKIP_BODY if errors are reported, the data set
415:             *         is null, or there is no data in the data set
416:             * @throws JspException if errors occurred that could not be reported in the page
417:             */
418:            public int doStartTag() throws JspException {
419:                ServletRequest request = pageContext.getRequest();
420:
421:                _tableRenderer = TagRenderingBase.Factory.getRendering(
422:                        TagRenderingBase.TABLE_TAG, request);
423:                _trRenderer = TagRenderingBase.Factory.getRendering(
424:                        TagRenderingBase.TR_TAG, request);
425:                _tdRenderer = TagRenderingBase.Factory.getRendering(
426:                        TagRenderingBase.TD_TAG, request);
427:                _htmlConstantRendering = TagRenderingBase.Factory
428:                        .getConstantRendering(request);
429:
430:                _sb = new InternalStringBuilder(1024);
431:                _appender = new StringBuilderRenderAppender(_sb);
432:
433:                Object source = evaluateDataSource();
434:
435:                if (hasErrors())
436:                    return SKIP_BODY;
437:
438:                if (source != null) {
439:                    Iterator iterator = IteratorFactory.createIterator(source);
440:                    if (iterator == null) {
441:                        LOGGER
442:                                .info("CellRepeater: The data structure from which to create an iterator is null.");
443:                        iterator = Collections.EMPTY_LIST.iterator();
444:                    }
445:
446:                    if (iterator != null) {
447:                        _dataList = new ArrayList();
448:                        while (iterator.hasNext()) {
449:                            _dataList.add(iterator.next());
450:                        }
451:                    }
452:                }
453:
454:                if (_rows == DIMENSION_DEFAULT_VALUE
455:                        || _columns == DIMENSION_DEFAULT_VALUE) {
456:                    /* try to guess the dimensions of the table */
457:                    if (_dataList != null && _dataList.size() > 0) {
458:                        guessDimensions(_dataList);
459:
460:                        if (hasErrors())
461:                            return SKIP_BODY;
462:                    }
463:                    /* the size of the data set isn't guessable */
464:                    else {
465:                        _valid = false;
466:                        return SKIP_BODY;
467:                    }
468:                }
469:
470:                /* check to make sure the rows / columns are actually valid before starting to render */
471:                if (_rows <= 0) {
472:                    String msg = Bundle.getString(
473:                            "Tags_CellRepeater_invalidRowValue", new Object[] {
474:                                    getTagName(), new Integer(_rows) });
475:                    registerTagError(msg, null);
476:                }
477:
478:                if (_columns <= 0) {
479:                    String msg = Bundle
480:                            .getString("Tags_CellRepeater_invalidColumnValue",
481:                                    new Object[] { getTagName(),
482:                                            new Integer(_columns) });
483:                    registerTagError(msg, null);
484:                }
485:
486:                if (hasErrors())
487:                    return SKIP_BODY;
488:
489:                openTableTag(_appender, _tableState);
490:
491:                _currentRow = 0;
492:                _currentColumn = 0;
493:
494:                DataAccessProviderStack
495:                        .addDataAccessProvider(this , pageContext);
496:                _containerInPageContext = true;
497:
498:                boolean haveItem = ensureItem(0, _dataList);
499:                if (haveItem) {
500:                    openRowTag(_appender, _trState);
501:                    openCellTag(_appender, _currentColumn);
502:                    return EVAL_BODY_BUFFERED;
503:                } else {
504:                    // special case -- with no items, render the entire table here
505:                    for (int i = 0; i < _rows; i++) {
506:                        openRowTag(_appender, _trState);
507:                        for (int j = 0; j < _columns; j++) {
508:                            openCellTag(_appender, computeStyleIndex(i, j));
509:                            _htmlConstantRendering.NBSP(_appender);
510:                            closeCellTag(_appender);
511:                        }
512:                        closeRowTag(_appender);
513:                        _appender.append("\n");
514:                    }
515:                    _currentRow = _rows;
516:                    _currentColumn = _columns;
517:                    return SKIP_BODY;
518:                }
519:            }
520:
521:            /**
522:             * Continue rendering the body of this tag until the dimensions of the table have been reached or
523:             * the entire dataset has been rendered.  The buffered body content from the previous iteration
524:             * of the body is added to the content this tag will render, @see addContent(java.lang.String).
525:             * Pad the table if the dimensions have not been met but the dataset is empty.
526:             *
527:             * @return EVAL_BODY_BUFFERED if there is more data to render in the dataset or
528:             *         SKIP_BODY if the end of the dataset is reached or an error occurs
529:             */
530:            public int doAfterBody() {
531:                if (bodyContent != null) {
532:                    _appender.append(bodyContent.getString());
533:                    bodyContent.clearBody();
534:                }
535:
536:                /*
537:                   this loop exists so that the table is filled out correctly up to the specified
538:                   or guessed table dimensions.  this is a little bit of a kludge; this logic should be done
539:                   in doEndTag()
540:                 */
541:                boolean haveNext = false;
542:                while (!haveNext) {
543:                    _currentColumn++;
544:
545:                    /* close the previous cell whose content was rendered the last time the tag body was executed */
546:                    closeCellTag(_appender);
547:
548:                    /* open a new table row */
549:                    if (_currentColumn == _columns) {
550:                        _currentRow++;
551:                        _currentColumn = 0;
552:                        closeRowTag(_appender);
553:                        _appender.append("\n");
554:                    }
555:
556:                    /* reached the end of the table as the current row is now equal to the total number of rows */
557:                    if (_currentRow == _rows)
558:                        return SKIP_BODY;
559:
560:                    if (_currentColumn == 0)
561:                        openRowTag(_appender, _trState != null ? _trState
562:                                : STATE_TR);
563:
564:                    int itemIndex = -1;
565:                    if (_verticalRepeat)
566:                        itemIndex = _currentColumn * _rows + _currentRow;
567:                    else
568:                        itemIndex = _currentRow * _columns + _currentColumn;
569:
570:                    haveNext = ensureItem(itemIndex, _dataList);
571:
572:                    openCellTag(_appender, computeStyleIndex(_currentRow,
573:                            _currentColumn));
574:
575:                    /* render empty cell and continue filling the table */
576:                    if (!haveNext)
577:                        _htmlConstantRendering.NBSP(_appender);
578:                    /* open a new table cell and render the body once again.  note, this exits the while loop above */
579:                    else
580:                        return EVAL_BODY_AGAIN;
581:                }
582:
583:                /* default is to skip the tag body */
584:                return SKIP_BODY;
585:            }
586:
587:            /**
588:             * Complete rendering the tag.  If no errors have occurred, the content that
589:             * the tag buffered is rendered.
590:             *
591:             * @return EVAL_PAGE to continue evaluating the page
592:             * @throws JspException if an error occurs that can not be reported on the page
593:             */
594:            public int doEndTag() throws JspException {
595:                if (hasErrors())
596:                    reportErrors();
597:                else if (_valid) {
598:                    closeTableTag(_appender);
599:                    write(_sb.toString());
600:                }
601:
602:                return EVAL_PAGE;
603:            }
604:
605:            public void doFinally() {
606:                localRelease();
607:            }
608:
609:            public void doCatch(Throwable t) throws Throwable {
610:                throw t;
611:            }
612:
613:            /**
614:             * Gets the tag's data source (can be an expression).
615:             * @return the data source
616:             */
617:            public String getDataSource() {
618:                return "{" + _dataSource + "}";
619:            }
620:
621:            /**
622:             * Get the index of the current iteration through the body of this tag.  This
623:             * data can be accessed using the expression <code>container.index</code>
624:             * on an attribute of a databindable NetUI tag that is contained within the
625:             * repeating body of this tag.  This expression is only valid when the dataset
626:             * is being rendered.
627:             *
628:             * @return the integer index of the current data item in the data set
629:             * @see org.apache.beehive.netui.script.common.IDataAccessProvider
630:             */
631:            public int getCurrentIndex() {
632:                return _currentIndex;
633:            }
634:
635:            /**
636:             * Get the item that is currently being rendered by this repeating tag.
637:             * This can be accessed using the expression <code>expression.item</code>
638:             * on an attribute of a databindable netUI tag that is contained within
639:             * the repeating body of this tag.  The expression is only valid when the dataset
640:             * is being rendered.
641:             *
642:             * @return the current item in the data set
643:             * @see org.apache.beehive.netui.script.common.IDataAccessProvider
644:             */
645:            public Object getCurrentItem() {
646:                return _currentItem;
647:            }
648:
649:            /**
650:             * Get the metadata for the current item.  This method is not supported by
651:             * this tag.
652:             *
653:             * @throws UnsupportedOperationException this tag does not support this method from the IDataAccessProvider interface
654:             * @see org.apache.beehive.netui.script.common.IDataAccessProvider
655:             */
656:            public Object getCurrentMetadata() {
657:                LocalizedUnsupportedOperationException uoe = new LocalizedUnsupportedOperationException(
658:                        "The "
659:                                + getTagName()
660:                                + "does not export metadata for its iterated items.");
661:                uoe.setLocalizedMessage(Bundle.getErrorString(
662:                        "Tags_DataAccessProvider_metadataUnsupported",
663:                        new Object[] { getTagName() }));
664:                throw uoe;
665:            }
666:
667:            /**
668:             * Get the parent IDataAccessProvider for this tag.  If this tag is contained within
669:             * a IDataAccessProvider, the containing IDataAccessProvider is available through the
670:             * expression <code>container.container</code>.  Any valid properties of the
671:             * parent IDataAccessProvider can be accessed through this expression.  This method
672:             * will return null if there is no parent IDataAccessProvider
673:             *
674:             * @return a containing IDataAccessProvider if one exists, null otherwise.
675:             * @see org.apache.beehive.netui.script.common.IDataAccessProvider
676:             */
677:            public IDataAccessProvider getProviderParent() {
678:                return (IDataAccessProvider) SimpleTagSupport
679:                        .findAncestorWithClass(this , IDataAccessProvider.class);
680:            }
681:
682:            /**
683:             * Return an <code>ArrayList</code> which represents a chain of <code>INameInterceptor</code>
684:             * objects.  This method by default returns <code>null</code> and should be overridden
685:             * by objects that support naming.
686:             * @return an <code>ArrayList</code> that will contain <code>INameInterceptor</code> objects.
687:             */
688:            protected List getNamingChain() {
689:                return AbstractClassicTag.DefaultNamingChain;
690:            }
691:
692:            /**
693:             * Reset all of the fields of this tag.
694:             */
695:            protected void localRelease() {
696:                super .localRelease();
697:
698:                if (bodyContent != null)
699:                    bodyContent.clearBody();
700:
701:                _rows = DIMENSION_DEFAULT_VALUE;
702:                _columns = DIMENSION_DEFAULT_VALUE;
703:                _currentRow = -1;
704:                _currentColumn = -1;
705:                _currentIndex = -1;
706:                _verticalRepeat = false;
707:                _dataList = null;
708:                _currentItem = null;
709:                _valid = true;
710:                _dataSource = null;
711:
712:                if (_tdState != null)
713:                    _tdState.clear();
714:                if (_trState != null)
715:                    _trState.clear();
716:                if (_tableState != null)
717:                    _tableState.clear();
718:
719:                _tableRenderer = null;
720:                _tdRenderer = null;
721:                _trRenderer = null;
722:
723:                _sb = null;
724:                _appender = null;
725:
726:                if (_containerInPageContext) {
727:                    DataAccessProviderStack
728:                            .removeDataAccessProvider(pageContext);
729:                    _containerInPageContext = false;
730:                }
731:            }
732:
733:            private final void guessDimensions(ArrayList data)
734:                    throws JspException {
735:
736:                if (_rows == 0 || _columns == 0)
737:                    registerTagError(
738:                            Bundle
739:                                    .getString("Tags_CellRepeater_missingRowsOrColumns"),
740:                            null);
741:
742:                if (data == null)
743:                    return;
744:
745:                int dataSize = data.size();
746:                if (_rows == DIMENSION_DEFAULT_VALUE
747:                        && _columns == DIMENSION_DEFAULT_VALUE) {
748:                    registerTagError(Bundle
749:                            .getString("Tags_CellRepeater_invalidRowOrColumn"),
750:                            null);
751:                } else if (_rows == DIMENSION_DEFAULT_VALUE) {
752:                    int remainder = dataSize % _columns;
753:                    _rows = (dataSize / _columns) + (remainder > 0 ? 1 : 0);
754:                    LOGGER.debug("guessed row size: " + _rows);
755:                } else if (_columns == DIMENSION_DEFAULT_VALUE) {
756:                    int remainder = dataSize % _rows;
757:                    _columns = (dataSize / _rows) + (remainder > 0 ? 1 : 0);
758:                    LOGGER.debug("guessed column size: " + _columns);
759:                }
760:            }
761:
762:            private void openTableTag(AbstractRenderAppender appender,
763:                    TableTag.State tableState) {
764:                if (tableState == null)
765:                    tableState = STATE_TABLE;
766:                _tableRenderer.doStartTag(appender, tableState);
767:            }
768:
769:            private void closeTableTag(AbstractRenderAppender appender) {
770:                assert appender != null;
771:                assert _tableRenderer != null;
772:                _tableRenderer.doEndTag(appender);
773:            }
774:
775:            private void openRowTag(AbstractRenderAppender appender,
776:                    TrTag.State trState) {
777:                if (trState == null)
778:                    trState = STATE_TR;
779:                _trRenderer.doStartTag(appender, trState);
780:            }
781:
782:            private void closeRowTag(AbstractRenderAppender appender) {
783:                assert _trRenderer != null;
784:                assert appender != null;
785:                _trRenderer.doEndTag(appender);
786:            }
787:
788:            private void openCellTag(AbstractRenderAppender appender, int index) {
789:                assert appender != null;
790:                assert index >= 0;
791:                assert _tdRenderer != null;
792:
793:                TdTag.State tdState = STATE_TD;
794:                if (_cellClass != null) {
795:                    if (_tdState != null)
796:                        _tdState.clear();
797:                    else
798:                        _tdState = new TdTag.State();
799:                    if (index % 2 == 0)
800:                        _tdState.styleClass = _cellClass;
801:                    else
802:                        _tdState.styleClass = (_altCellClass != null ? _altCellClass
803:                                : _cellClass);
804:                    tdState = _tdState;
805:                }
806:
807:                _tdRenderer.doStartTag(appender, tdState);
808:            }
809:
810:            private void closeCellTag(AbstractRenderAppender appender) {
811:                assert _tdRenderer != null;
812:                assert appender != null;
813:                _tdRenderer.doEndTag(appender);
814:            }
815:
816:            private int computeStyleIndex(int r, int c) {
817:                return c + (r % 2);
818:            }
819:
820:            private boolean ensureItem(int index, ArrayList data) {
821:                LOGGER.debug("item: "
822:                        + 0
823:                        + " data: "
824:                        + (data == null ? "null data"
825:                                : (index < data.size() ? "" + index
826:                                        : "index out of bounds for size "
827:                                                + data.size())));
828:
829:                if (data != null && index < data.size()) {
830:                    _currentItem = data.get(index);
831:                    _currentIndex = index;
832:                    return true;
833:                } else
834:                    return false;
835:            }
836:
837:            /**
838:             * Return the Object that is represented by the specified data source.
839:             * @return Object
840:             * @throws JspException
841:             */
842:            private Object evaluateDataSource() throws JspException {
843:                ExpressionHandling expr = new ExpressionHandling(this );
844:                String dataSource = getDataSource();
845:                String ds = expr.ensureValidExpression(dataSource,
846:                        "dataSource", "DataSourceError");
847:                if (ds == null)
848:                    return null;
849:
850:                Object o = expr.evaluateExpression(dataSource, "dataSource",
851:                        pageContext);
852:                return o;
853:            }
854:        }
w__w_w.___j___a__va_2__s_._c__om_ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.