KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > displaytag > render > HtmlTableWriter


1 /**
2  * Licensed under the Artistic License; you may not use this file
3  * except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  * http://displaytag.sourceforge.net/license.html
7  *
8  * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
9  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11  */

12 package org.displaytag.render;
13
14 import java.io.IOException JavaDoc;
15 import java.text.MessageFormat JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.Map JavaDoc;
18
19 import javax.servlet.jsp.JspException JavaDoc;
20 import javax.servlet.jsp.JspWriter JavaDoc;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.displaytag.exception.DecoratorException;
25 import org.displaytag.exception.ObjectLookupException;
26 import org.displaytag.exception.WrappedRuntimeException;
27 import org.displaytag.model.Column;
28 import org.displaytag.model.HeaderCell;
29 import org.displaytag.model.Row;
30 import org.displaytag.model.TableModel;
31 import org.displaytag.pagination.PaginatedList;
32 import org.displaytag.pagination.SmartListHelper;
33 import org.displaytag.properties.MediaTypeEnum;
34 import org.displaytag.properties.SortOrderEnum;
35 import org.displaytag.properties.TableProperties;
36 import org.displaytag.tags.CaptionTag;
37 import org.displaytag.tags.TableTagParameters;
38 import org.displaytag.util.Anchor;
39 import org.displaytag.util.Href;
40 import org.displaytag.util.HtmlAttributeMap;
41 import org.displaytag.util.ParamEncoder;
42 import org.displaytag.util.TagConstants;
43
44
45 /**
46  * A table writer that formats a table in HTML and writes it to a JSP page.
47  * @author Fabrizio Giustina
48  * @author Jorge L. Barroso
49  * @version $Id$
50  * @see org.displaytag.render.TableWriterTemplate
51  * @since 1.1
52  */

53 public class HtmlTableWriter extends TableWriterAdapter
54 {
55
56     /**
57      * Logger.
58      */

59     private static Log log = LogFactory.getLog(HtmlTableWriter.class);
60
61     /**
62      * <code>TableModel</code>
63      */

64     private TableModel tableModel;
65
66     /**
67      * <code>TableProperties</code>
68      */

69     private TableProperties properties;
70
71     /**
72      * Output destination.
73      */

74     private JspWriter JavaDoc out;
75
76     /**
77      * The param encoder used to generate unique parameter names. Initialized at the first use of encodeParameter().
78      */

79     private ParamEncoder paramEncoder;
80
81     /**
82      * base href used for links.
83      */

84     private Href baseHref;
85
86     /**
87      * add export links.
88      */

89     private boolean export;
90
91     private CaptionTag captionTag;
92
93     /**
94      * The paginated list containing the external pagination and sort parameters The presence of this paginated list is
95      * what determines if external pagination and sorting is used or not.
96      */

97     private PaginatedList paginatedList;
98
99     /**
100      * Used by various functions when the person wants to do paging.
101      */

102     private SmartListHelper listHelper;
103
104     /**
105      * page size.
106      */

107     private int pagesize;
108
109     private HtmlAttributeMap attributeMap;
110
111     /**
112      * Unique table id.
113      */

114     private String JavaDoc uid;
115
116     /**
117      * This table writer uses a <code>TableTag</code> and a <code>JspWriter</code> to do its work.
118      * @param tableTag <code>TableTag</code> instance called back by this writer.
119      * @param out The output destination.
120      */

121     public HtmlTableWriter(
122         TableModel tableModel,
123         TableProperties tableProperties,
124         Href baseHref,
125         boolean export,
126         JspWriter JavaDoc out,
127         CaptionTag captionTag,
128         PaginatedList paginatedList,
129         SmartListHelper listHelper,
130         int pagesize,
131         HtmlAttributeMap attributeMap,
132         String JavaDoc uid)
133     {
134         this.tableModel = tableModel;
135         this.properties = tableProperties;
136         this.baseHref = baseHref;
137         this.export = export;
138         this.out = out;
139         this.captionTag = captionTag;
140         this.paginatedList = paginatedList;
141         this.listHelper = listHelper;
142         this.pagesize = pagesize;
143         this.attributeMap = attributeMap;
144         this.uid = uid;
145     }
146
147     /**
148      * Writes a banner containing search result and paging navigation above an HTML table to a JSP page.
149      * @see org.displaytag.render.TableWriterTemplate#writeTopBanner(org.displaytag.model.TableModel)
150      */

151     protected void writeTopBanner(TableModel model)
152     {
153         writeSearchResultAndNavigation();
154     }
155
156     /**
157      * Writes an HTML table's opening tags to a JSP page.
158      * @see org.displaytag.render.TableWriterTemplate#writeTableOpener(org.displaytag.model.TableModel)
159      */

160     protected void writeTableOpener(TableModel model)
161     {
162         this.write(getOpenTag());
163     }
164
165     /**
166      * Writes an HTML table's caption to a JSP page.
167      * @see org.displaytag.render.TableWriterTemplate#writeCaption(org.displaytag.model.TableModel)
168      */

169     protected void writeCaption(TableModel model)
170     {
171         this.write(captionTag.getOpenTag() + model.getCaption() + captionTag.getCloseTag());
172     }
173
174     /**
175      * Writes an HTML table's footer to a JSP page; HTML requires tfoot to appear before tbody.
176      * @see org.displaytag.render.TableWriterTemplate#writeFooter(org.displaytag.model.TableModel)
177      */

178     protected void writePreBodyFooter(TableModel model)
179     {
180         this.write(TagConstants.TAG_TFOOTER_OPEN);
181         this.write(model.getFooter());
182         this.write(TagConstants.TAG_TFOOTER_CLOSE);
183     }
184
185     /**
186      * Writes the start of an HTML table's body to a JSP page.
187      * @see org.displaytag.render.TableWriterTemplate#writeTableBodyOpener(org.displaytag.model.TableModel)
188      */

189     protected void writeTableBodyOpener(TableModel model)
190     {
191         this.write(TagConstants.TAG_TBODY_OPEN);
192
193     }
194
195     /**
196      * Writes the end of an HTML table's body to a JSP page.
197      * @see org.displaytag.render.TableWriterTemplate#writeTableBodyCloser(org.displaytag.model.TableModel)
198      */

199     protected void writeTableBodyCloser(TableModel model)
200     {
201         this.write(TagConstants.TAG_TBODY_CLOSE);
202     }
203
204     /**
205      * Writes the closing structure of an HTML table to a JSP page.
206      * @see org.displaytag.render.TableWriterTemplate#writeTableCloser(org.displaytag.model.TableModel)
207      */

208     protected void writeTableCloser(TableModel model)
209     {
210         this.write(TagConstants.TAG_OPENCLOSING);
211         this.write(TagConstants.TABLE_TAG_NAME);
212         this.write(TagConstants.TAG_CLOSE);
213     }
214
215     /**
216      * Writes a banner containing search result, paging navigation, and export links below an HTML table to a JSP page.
217      * @see org.displaytag.render.TableWriterTemplate#writeBottomBanner(org.displaytag.model.TableModel)
218      */

219     protected void writeBottomBanner(TableModel model)
220     {
221         writeNavigationAndExportLinks();
222     }
223
224     /**
225      * @see org.displaytag.render.TableWriterTemplate#writeDecoratedTableFinish(org.displaytag.model.TableModel)
226      */

227     protected void writeDecoratedTableFinish(TableModel model)
228     {
229         model.getTableDecorator().finish();
230     }
231
232     /**
233      * @see org.displaytag.render.TableWriterTemplate#writeDecoratedRowStart(org.displaytag.model.TableModel)
234      */

235     protected void writeDecoratedRowStart(TableModel model)
236     {
237         this.write(model.getTableDecorator().startRow());
238     }
239
240     /**
241      * Writes an HTML table's row-opening tag to a JSP page.
242      * @see org.displaytag.render.TableWriterTemplate#writeRowOpener(org.displaytag.model.Row)
243      */

244     protected void writeRowOpener(Row row)
245     {
246         this.write(row.getOpenTag());
247     }
248
249     /**
250      * Writes an HTML table's column-opening tag to a JSP page.
251      * @see org.displaytag.render.TableWriterTemplate#writeColumnOpener(org.displaytag.model.Column)
252      */

253     protected void writeColumnOpener(Column column) throws ObjectLookupException, DecoratorException
254     {
255         this.write(column.getOpenTag());
256     }
257
258     /**
259      * Writes an HTML table's column-closing tag to a JSP page.
260      * @see org.displaytag.render.TableWriterTemplate#writeColumnCloser(org.displaytag.model.Column)
261      */

262     protected void writeColumnCloser(Column column)
263     {
264         this.write(column.getCloseTag());
265     }
266
267     /**
268      * Writes to a JSP page an HTML table row that has no columns.
269      * @see org.displaytag.render.TableWriterTemplate#writeRowWithNoColumns(java.lang.String)
270      */

271     protected void writeRowWithNoColumns(String JavaDoc rowValue)
272     {
273         this.write(TagConstants.TAG_TD_OPEN);
274         this.write(rowValue);
275         this.write(TagConstants.TAG_TD_CLOSE);
276     }
277
278     /**
279      * Writes an HTML table's row-closing tag to a JSP page.
280      * @see org.displaytag.render.TableWriterTemplate#writeRowCloser(org.displaytag.model.Row)
281      */

282     protected void writeRowCloser(Row row)
283     {
284         this.write(row.getCloseTag());
285     }
286
287     /**
288      * @see org.displaytag.render.TableWriterTemplate#writeDecoratedRowFinish(org.displaytag.model.TableModel)
289      */

290     protected void writeDecoratedRowFinish(TableModel model)
291     {
292         this.write(model.getTableDecorator().finishRow());
293     }
294
295     /**
296      * Writes an HTML message to a JSP page explaining that the table model contains no data.
297      * @see org.displaytag.render.TableWriterTemplate#writeEmptyListMessage(java.lang.String)
298      */

299     protected void writeEmptyListMessage(String JavaDoc emptyListMessage)
300     {
301         this.write(emptyListMessage);
302     }
303
304     /**
305      * Writes a HTML table column value to a JSP page.
306      * @see org.displaytag.render.TableWriterTemplate#writeColumnValue(java.lang.String,org.displaytag.model.Column)
307      */

308     protected void writeColumnValue(Object JavaDoc value, Column column)
309     {
310         this.write(value);
311     }
312
313     /**
314      * Writes an HTML message to a JSP page explaining that the row contains no data.
315      * @see org.displaytag.render.TableWriterTemplate#writeEmptyListRowMessage(java.lang.String)
316      */

317     protected void writeEmptyListRowMessage(String JavaDoc message)
318     {
319         this.write(message);
320     }
321
322     /**
323      * Writes an HTML table's column header to a JSP page.
324      * @see org.displaytag.render.TableWriterTemplate#writeTableHeader(org.displaytag.model.TableModel)
325      */

326     protected void writeTableHeader(TableModel model)
327     {
328
329         if (log.isDebugEnabled())
330         {
331             log.debug("[" + tableModel.getId() + "] getTableHeader called");
332         }
333
334         // open thead
335
write(TagConstants.TAG_THEAD_OPEN);
336
337         // open tr
338
write(TagConstants.TAG_TR_OPEN);
339
340         // no columns?
341
if (this.tableModel.isEmpty())
342         {
343             write(TagConstants.TAG_TH_OPEN);
344             write(TagConstants.TAG_TH_CLOSE);
345         }
346
347         // iterator on columns for header
348
Iterator JavaDoc iterator = this.tableModel.getHeaderCellList().iterator();
349
350         while (iterator.hasNext())
351         {
352             // get the header cell
353
HeaderCell headerCell = (HeaderCell) iterator.next();
354
355             if (headerCell.getSortable())
356             {
357                 String JavaDoc cssSortable = this.properties.getCssSortable();
358                 headerCell.addHeaderClass(cssSortable);
359             }
360
361             // if sorted add styles
362
if (headerCell.isAlreadySorted())
363             {
364                 // sorted css class
365
headerCell.addHeaderClass(this.properties.getCssSorted());
366
367                 // sort order css class
368
headerCell.addHeaderClass(this.properties.getCssOrder(this.tableModel.isSortOrderAscending()));
369             }
370
371             // append th with html attributes
372
write(headerCell.getHeaderOpenTag());
373
374             // title
375
String JavaDoc header = headerCell.getTitle();
376
377             // column is sortable, create link
378
if (headerCell.getSortable())
379             {
380                 // creates the link for sorting
381
Anchor anchor = new Anchor(getSortingHref(headerCell), header);
382
383                 // append to buffer
384
header = anchor.toString();
385             }
386
387             write(header);
388             write(headerCell.getHeaderCloseTag());
389         }
390
391         // close tr
392
write(TagConstants.TAG_TR_CLOSE);
393
394         // close thead
395
write(TagConstants.TAG_THEAD_CLOSE);
396
397         if (log.isDebugEnabled())
398         {
399             log.debug("[" + tableModel.getId() + "] getTableHeader end");
400         }
401     }
402
403     /**
404      * Generates the link to be added to a column header for sorting.
405      * @param headerCell header cell the link should be added to
406      * @return Href for sorting
407      */

408     private Href getSortingHref(HeaderCell headerCell)
409     {
410         // costruct Href from base href, preserving parameters
411
Href href = (Href) this.baseHref.clone();
412
413         if (this.paginatedList == null)
414         {
415             // add column number as link parameter
416
if (!this.tableModel.isLocalSort() && (headerCell.getSortName() != null))
417             {
418                 href.addParameter(encodeParameter(TableTagParameters.PARAMETER_SORT), headerCell.getSortName());
419                 href.addParameter(encodeParameter(TableTagParameters.PARAMETER_SORTUSINGNAME), "1");
420             }
421             else
422             {
423                 href.addParameter(encodeParameter(TableTagParameters.PARAMETER_SORT), headerCell.getColumnNumber());
424             }
425
426             boolean nowOrderAscending = true;
427
428             if (headerCell.getDefaultSortOrder() != null)
429             {
430                 boolean sortAscending = SortOrderEnum.ASCENDING.equals(headerCell.getDefaultSortOrder());
431                 nowOrderAscending = headerCell.isAlreadySorted()
432                     ? !this.tableModel.isSortOrderAscending()
433                     : sortAscending;
434             }
435             else
436             {
437                 nowOrderAscending = !(headerCell.isAlreadySorted() && this.tableModel.isSortOrderAscending());
438             }
439
440             int sortOrderParam = nowOrderAscending ? SortOrderEnum.ASCENDING.getCode() : SortOrderEnum.DESCENDING
441                 .getCode();
442             href.addParameter(encodeParameter(TableTagParameters.PARAMETER_ORDER), sortOrderParam);
443
444             // If user want to sort the full table I need to reset the page number.
445
// or if we aren't sorting locally we need to reset the page as well.
446
if (this.tableModel.isSortFullTable() || !this.tableModel.isLocalSort())
447             {
448                 href.addParameter(encodeParameter(TableTagParameters.PARAMETER_PAGE), 1);
449             }
450         }
451         else
452         {
453             if (properties.getPaginationSkipPageNumberInSort())
454             {
455                 href.removeParameter(properties.getPaginationPageNumberParam());
456             }
457
458             String JavaDoc sortProperty = headerCell.getSortProperty();
459             if (sortProperty == null)
460             {
461                 sortProperty = headerCell.getBeanPropertyName();
462             }
463
464             href.addParameter(properties.getPaginationSortParam(), sortProperty);
465             String JavaDoc dirParam;
466             if (headerCell.isAlreadySorted())
467             {
468                 dirParam = tableModel.isSortOrderAscending() ? properties.getPaginationDescValue() : properties
469                     .getPaginationAscValue();
470             }
471             else
472             {
473                 dirParam = properties.getPaginationAscValue();
474             }
475             href.addParameter(properties.getPaginationSortDirectionParam(), dirParam);
476             if (paginatedList.getSearchId() != null)
477             {
478                 href.addParameter(properties.getPaginationSearchIdParam(), paginatedList.getSearchId());
479             }
480         }
481
482         return href;
483     }
484
485     /**
486      * encode a parameter name to be unique in the page using ParamEncoder.
487      * @param parameterName parameter name to encode
488      * @return String encoded parameter name
489      */

490     private String JavaDoc encodeParameter(String JavaDoc parameterName)
491     {
492         // paramEncoder has been already instantiated?
493
if (this.paramEncoder == null)
494         {
495             // use the id attribute to get the unique identifier
496
this.paramEncoder = new ParamEncoder(this.tableModel.getId());
497         }
498
499         return this.paramEncoder.encodeParameterName(parameterName);
500     }
501
502     /**
503      * Generates table footer with links for export commands.
504      */

505     public void writeNavigationAndExportLinks()
506     {
507         // Put the page stuff there if it needs to be there...
508
if (this.properties.getAddPagingBannerBottom())
509         {
510             writeSearchResultAndNavigation();
511         }
512
513         // add export links (only if the table is not empty)
514
if (this.export && this.tableModel.getRowListPage().size() != 0)
515         {
516             writeExportLinks();
517         }
518     }
519
520     /**
521      * generates the search result and navigation bar.
522      */

523     public void writeSearchResultAndNavigation()
524     {
525         if ((this.paginatedList == null && this.pagesize != 0 && this.listHelper != null)
526             || (this.paginatedList != null))
527         {
528             // create a new href
529
Href navigationHref = (Href) this.baseHref.clone();
530
531             write(this.listHelper.getSearchResultsSummary());
532
533             String JavaDoc pageParameter;
534             if (paginatedList == null)
535             {
536                 pageParameter = encodeParameter(TableTagParameters.PARAMETER_PAGE);
537             }
538             else
539             {
540                 pageParameter = properties.getPaginationPageNumberParam();
541                 if ((paginatedList.getSearchId() != null)
542                     && (!navigationHref.getParameterMap().containsKey(properties.getPaginationSearchIdParam())))
543                 {
544                     navigationHref.addParameter(properties.getPaginationSearchIdParam(), paginatedList.getSearchId());
545                 }
546             }
547             write(this.listHelper.getPageNavigationBar(navigationHref, pageParameter));
548         }
549     }
550
551     /**
552      * Writes the formatted export links section.
553      */

554     private void writeExportLinks()
555     {
556         // Figure out what formats they want to export, make up a little string
557
Href exportHref = (Href) this.baseHref.clone();
558
559         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(200);
560         Iterator JavaDoc iterator = MediaTypeEnum.iterator();
561
562         while (iterator.hasNext())
563         {
564             MediaTypeEnum currentExportType = (MediaTypeEnum) iterator.next();
565
566             if (this.properties.getAddExport(currentExportType))
567             {
568
569                 if (buffer.length() > 0)
570                 {
571                     buffer.append(this.properties.getExportBannerSeparator());
572                 }
573
574                 exportHref.addParameter(encodeParameter(TableTagParameters.PARAMETER_EXPORTTYPE), currentExportType
575                     .getCode());
576
577                 // export marker
578
exportHref.addParameter(TableTagParameters.PARAMETER_EXPORTING, "1");
579
580                 Anchor anchor = new Anchor(exportHref, this.properties.getExportLabel(currentExportType));
581                 buffer.append(anchor.toString());
582             }
583         }
584
585         String JavaDoc[] exportOptions = {buffer.toString()};
586         write(MessageFormat.format(this.properties.getExportBanner(), exportOptions));
587     }
588
589     /**
590      * create the open tag containing all the attributes.
591      * @return open tag string: <code>%lt;table attribute="value" ... ></code>
592      */

593     public String JavaDoc getOpenTag()
594     {
595
596         if (this.uid != null && attributeMap.get(TagConstants.ATTRIBUTE_ID) == null)
597         {
598             // we need to clone the attribute map in order to "fix" the html id when using only the "uid" attribute
599
Map JavaDoc localAttributeMap = (Map JavaDoc) attributeMap.clone();
600             localAttributeMap.put(TagConstants.ATTRIBUTE_ID, this.uid);
601
602             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
603             buffer.append(TagConstants.TAG_OPEN).append(TagConstants.TABLE_TAG_NAME);
604             buffer.append(localAttributeMap);
605             buffer.append(TagConstants.TAG_CLOSE);
606
607             return buffer.toString();
608
609         }
610
611         // fast, no clone
612
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
613
614         buffer.append(TagConstants.TAG_OPEN).append(TagConstants.TABLE_TAG_NAME);
615         buffer.append(attributeMap);
616         buffer.append(TagConstants.TAG_CLOSE);
617
618         return buffer.toString();
619     }
620
621     /**
622      * Utility method.
623      * @param string String
624      */

625     public void write(String JavaDoc string)
626     {
627         if (string != null)
628         {
629             try
630             {
631                 out.write(string);
632             }
633             catch (IOException JavaDoc e)
634             {
635                 throw new WrappedRuntimeException(getClass(), e);
636             }
637         }
638
639     }
640
641     public void writeTable(TableModel model, String JavaDoc id) throws JspException JavaDoc
642     {
643         super.writeTable(model, id);
644     }
645
646     /**
647      * Utility method.
648      * @param string String
649      */

650     public void write(Object JavaDoc string)
651     {
652         if (string != null)
653         {
654             try
655             {
656                 out.write(string.toString());
657             }
658             catch (IOException JavaDoc e)
659             {
660                 throw new WrappedRuntimeException(getClass(), e);
661             }
662         }
663
664     }
665
666 }
667
Popular Tags