Clover coverage report - Maven Clover report
Coverage timestamp: Sun Jan 3 2010 19:08:46 CET
file stats: LOC: 757   Methods: 34
NCLOC: 446   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
HtmlTableWriter.java 81.1% 96% 100% 92.6%
coverage coverage
 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;
 15    import java.text.MessageFormat;
 16    import java.util.Iterator;
 17    import java.util.Map;
 18   
 19    import javax.servlet.jsp.JspException;
 20    import javax.servlet.jsp.JspWriter;
 21   
 22    import org.apache.commons.lang.ObjectUtils;
 23    import org.apache.commons.lang.StringUtils;
 24    import org.apache.commons.logging.Log;
 25    import org.apache.commons.logging.LogFactory;
 26    import org.displaytag.exception.DecoratorException;
 27    import org.displaytag.exception.ObjectLookupException;
 28    import org.displaytag.exception.WrappedRuntimeException;
 29    import org.displaytag.model.Column;
 30    import org.displaytag.model.HeaderCell;
 31    import org.displaytag.model.Row;
 32    import org.displaytag.model.TableModel;
 33    import org.displaytag.pagination.PaginatedList;
 34    import org.displaytag.pagination.SmartListHelper;
 35    import org.displaytag.properties.MediaTypeEnum;
 36    import org.displaytag.properties.SortOrderEnum;
 37    import org.displaytag.properties.TableProperties;
 38    import org.displaytag.tags.CaptionTag;
 39    import org.displaytag.tags.TableTagParameters;
 40    import org.displaytag.util.Anchor;
 41    import org.displaytag.util.Href;
 42    import org.displaytag.util.HtmlAttributeMap;
 43    import org.displaytag.util.ParamEncoder;
 44    import org.displaytag.util.PostHref;
 45    import org.displaytag.util.TagConstants;
 46   
 47   
 48    /**
 49    * A table writer that formats a table in HTML and writes it to a JSP page.
 50    * @author Fabrizio Giustina
 51    * @author Jorge L. Barroso
 52    * @version $Id$
 53    * @see org.displaytag.render.TableWriterTemplate
 54    * @since 1.1
 55    */
 56    public class HtmlTableWriter extends TableWriterAdapter
 57    {
 58   
 59    /**
 60    * Logger.
 61    */
 62    private static Log log = LogFactory.getLog(HtmlTableWriter.class);
 63   
 64    /**
 65    * <code>TableModel</code>
 66    */
 67    private TableModel tableModel;
 68   
 69    /**
 70    * <code>TableProperties</code>
 71    */
 72    private TableProperties properties;
 73   
 74    /**
 75    * Output destination.
 76    */
 77    private JspWriter out;
 78   
 79    /**
 80    * The param encoder used to generate unique parameter names. Initialized at the first use of encodeParameter().
 81    */
 82    private ParamEncoder paramEncoder;
 83   
 84    /**
 85    * base href used for links.
 86    */
 87    private Href baseHref;
 88   
 89    /**
 90    * add export links.
 91    */
 92    private boolean export;
 93   
 94    private CaptionTag captionTag;
 95   
 96    /**
 97    * The paginated list containing the external pagination and sort parameters The presence of this paginated list is
 98    * what determines if external pagination and sorting is used or not.
 99    */
 100    private PaginatedList paginatedList;
 101   
 102    /**
 103    * Used by various functions when the person wants to do paging.
 104    */
 105    private SmartListHelper listHelper;
 106   
 107    /**
 108    * page size.
 109    */
 110    private int pagesize;
 111   
 112    private HtmlAttributeMap attributeMap;
 113   
 114    /**
 115    * Unique table id.
 116    */
 117    private String uid;
 118   
 119    /**
 120    * This table writer uses a <code>TableTag</code> and a <code>JspWriter</code> to do its work.
 121    * @param tableTag <code>TableTag</code> instance called back by this writer.
 122    * @param out The output destination.
 123    */
 124  360 public HtmlTableWriter(
 125    TableModel tableModel,
 126    TableProperties tableProperties,
 127    Href baseHref,
 128    boolean export,
 129    JspWriter out,
 130    CaptionTag captionTag,
 131    PaginatedList paginatedList,
 132    SmartListHelper listHelper,
 133    int pagesize,
 134    HtmlAttributeMap attributeMap,
 135    String uid)
 136    {
 137  360 this.tableModel = tableModel;
 138  360 this.properties = tableProperties;
 139  360 this.baseHref = baseHref;
 140  360 this.export = export;
 141  360 this.out = out;
 142  360 this.captionTag = captionTag;
 143  360 this.paginatedList = paginatedList;
 144  360 this.listHelper = listHelper;
 145  360 this.pagesize = pagesize;
 146  360 this.attributeMap = attributeMap;
 147  360 this.uid = uid;
 148    }
 149   
 150    /**
 151    * Writes a banner containing search result and paging navigation above an HTML table to a JSP page.
 152    * @see org.displaytag.render.TableWriterTemplate#writeTopBanner(org.displaytag.model.TableModel)
 153    */
 154  342 protected void writeTopBanner(TableModel model)
 155    {
 156  342 if (this.tableModel.getForm() != null)
 157    {
 158   
 159  2 String js = "<script type=\"text/javascript\">\n"
 160    + "function displaytagform(formname, fields){\n"
 161    + " var objfrm = document.forms[formname];\n"
 162    + " for (j=fields.length-1;j>=0;j--){var f= objfrm.elements[fields[j].f];if (f){f.value=fields[j].v};}\n"
 163    + " objfrm.submit();\n"
 164    + "}\n"
 165    + "</script>";
 166  2 writeFormFields();
 167  2 write(js);
 168    }
 169  342 writeSearchResultAndNavigation();
 170    }
 171   
 172    /**
 173    * Writes an HTML table's opening tags to a JSP page.
 174    * @see org.displaytag.render.TableWriterTemplate#writeTableOpener(org.displaytag.model.TableModel)
 175    */
 176  352 protected void writeTableOpener(TableModel model)
 177    {
 178  352 this.write(getOpenTag());
 179    }
 180   
 181  2 private void writeFormFields()
 182    {
 183  2 Map parameters = baseHref.getParameterMap();
 184   
 185  2 ParamEncoder pe = new ParamEncoder(this.tableModel.getId());
 186   
 187  2 addIfMissing(parameters, pe.encodeParameterName(TableTagParameters.PARAMETER_ORDER));
 188  2 addIfMissing(parameters, pe.encodeParameterName(TableTagParameters.PARAMETER_PAGE));
 189  2 addIfMissing(parameters, pe.encodeParameterName(TableTagParameters.PARAMETER_SORT));
 190   
 191  2 for (Iterator it = parameters.keySet().iterator(); it.hasNext();)
 192    {
 193  6 String key = (String) it.next();
 194  6 Object value = parameters.get(key);
 195   
 196  6 if (value != null & value.getClass().isArray())
 197    {
 198  0 Object[] arr = (Object[]) value;
 199  0 for (int j = 0; j < arr.length; j++)
 200    {
 201  0 writeField(key, arr[j]);
 202    }
 203    }
 204    else
 205    {
 206  6 writeField(key, value);
 207    }
 208    }
 209    }
 210   
 211    /**
 212    * @param key
 213    * @param value
 214    */
 215  6 private void writeField(String key, Object value)
 216    {
 217  6 StringBuffer buffer = new StringBuffer();
 218  6 buffer.append("<input type=\"hidden\" name=\"");
 219  6 buffer.append(esc(key));
 220  6 buffer.append("\" value=\"");
 221  6 buffer.append(value);
 222  6 buffer.append("\"/>");
 223   
 224  6 write(buffer.toString());
 225    }
 226   
 227  6 private String esc(Object value)
 228    {
 229  6 String valueEscaped = StringUtils.replace(ObjectUtils.toString(value), "\"", "\\\"");
 230  6 return valueEscaped;
 231    }
 232   
 233    /**
 234    * Adds an element to the given map if empty (use an empty string as value)
 235    * @param parameters Map of parameters
 236    * @param key param key
 237    */
 238  6 private void addIfMissing(Map parameters, String key)
 239    {
 240  6 if (!parameters.containsKey(key))
 241    {
 242  6 parameters.put(key, StringUtils.EMPTY);
 243    }
 244    }
 245   
 246    /**
 247    * Writes an HTML table's caption to a JSP page.
 248    * @see org.displaytag.render.TableWriterTemplate#writeCaption(org.displaytag.model.TableModel)
 249    */
 250  18 protected void writeCaption(TableModel model)
 251    {
 252  18 this.write(captionTag.getOpenTag() + model.getCaption() + captionTag.getCloseTag());
 253    }
 254   
 255    /**
 256    * Writes an HTML table's footer to a JSP page; HTML requires tfoot to appear before tbody.
 257    * @see org.displaytag.render.TableWriterTemplate#writeFooter(org.displaytag.model.TableModel)
 258    */
 259  4 protected void writePreBodyFooter(TableModel model)
 260    {
 261  4 this.write(TagConstants.TAG_TFOOTER_OPEN);
 262  4 this.write(model.getFooter());
 263  4 this.write(TagConstants.TAG_TFOOTER_CLOSE);
 264    }
 265   
 266    /**
 267    * Writes the start of an HTML table's body to a JSP page.
 268    * @see org.displaytag.render.TableWriterTemplate#writeTableBodyOpener(org.displaytag.model.TableModel)
 269    */
 270  352 protected void writeTableBodyOpener(TableModel model)
 271    {
 272  352 this.write(TagConstants.TAG_TBODY_OPEN);
 273   
 274    }
 275   
 276    /**
 277    * Writes the end of an HTML table's body to a JSP page.
 278    * @see org.displaytag.render.TableWriterTemplate#writeTableBodyCloser(org.displaytag.model.TableModel)
 279    */
 280  352 protected void writeTableBodyCloser(TableModel model)
 281    {
 282  352 this.write(TagConstants.TAG_TBODY_CLOSE);
 283    }
 284   
 285    /**
 286    * Writes the closing structure of an HTML table to a JSP page.
 287    * @see org.displaytag.render.TableWriterTemplate#writeTableCloser(org.displaytag.model.TableModel)
 288    */
 289  352 protected void writeTableCloser(TableModel model)
 290    {
 291  352 this.write(TagConstants.TAG_OPENCLOSING);
 292  352 this.write(TagConstants.TABLE_TAG_NAME);
 293  352 this.write(TagConstants.TAG_CLOSE);
 294    }
 295   
 296    /**
 297    * Writes a banner containing search result, paging navigation, and export links below an HTML table to a JSP page.
 298    * @see org.displaytag.render.TableWriterTemplate#writeBottomBanner(org.displaytag.model.TableModel)
 299    */
 300  352 protected void writeBottomBanner(TableModel model)
 301    {
 302  352 writeNavigationAndExportLinks();
 303    }
 304   
 305    /**
 306    * @see org.displaytag.render.TableWriterTemplate#writeDecoratedTableFinish(org.displaytag.model.TableModel)
 307    */
 308  20 protected void writeDecoratedTableFinish(TableModel model)
 309    {
 310  20 model.getTableDecorator().finish();
 311    }
 312   
 313    /**
 314    * @see org.displaytag.render.TableWriterTemplate#writeDecoratedRowStart(org.displaytag.model.TableModel)
 315    */
 316  40 protected void writeDecoratedRowStart(TableModel model)
 317    {
 318  40 this.write(model.getTableDecorator().startRow());
 319    }
 320   
 321    /**
 322    * Writes an HTML table's row-opening tag to a JSP page.
 323    * @see org.displaytag.render.TableWriterTemplate#writeRowOpener(org.displaytag.model.Row)
 324    */
 325  576 protected void writeRowOpener(Row row)
 326    {
 327  576 this.write(row.getOpenTag());
 328    }
 329   
 330    /**
 331    * Writes an HTML table's column-opening tag to a JSP page.
 332    * @see org.displaytag.render.TableWriterTemplate#writeColumnOpener(org.displaytag.model.Column)
 333    */
 334  1059 protected void writeColumnOpener(Column column) throws ObjectLookupException, DecoratorException
 335    {
 336  1059 this.write(column.getOpenTag());
 337    }
 338   
 339    /**
 340    * Writes an HTML table's column-closing tag to a JSP page.
 341    * @see org.displaytag.render.TableWriterTemplate#writeColumnCloser(org.displaytag.model.Column)
 342    */
 343  1059 protected void writeColumnCloser(Column column)
 344    {
 345  1059 this.write(column.getCloseTag());
 346    }
 347   
 348    /**
 349    * Writes to a JSP page an HTML table row that has no columns.
 350    * @see org.displaytag.render.TableWriterTemplate#writeRowWithNoColumns(java.lang.String)
 351    */
 352  6 protected void writeRowWithNoColumns(String rowValue)
 353    {
 354  6 this.write(TagConstants.TAG_TD_OPEN);
 355  6 this.write(rowValue);
 356  6 this.write(TagConstants.TAG_TD_CLOSE);
 357    }
 358   
 359    /**
 360    * Writes an HTML table's row-closing tag to a JSP page.
 361    * @see org.displaytag.render.TableWriterTemplate#writeRowCloser(org.displaytag.model.Row)
 362    */
 363  576 protected void writeRowCloser(Row row)
 364    {
 365  576 this.write(row.getCloseTag());
 366    }
 367   
 368    /**
 369    * @see org.displaytag.render.TableWriterTemplate#writeDecoratedRowFinish(org.displaytag.model.TableModel)
 370    */
 371  40 protected void writeDecoratedRowFinish(TableModel model)
 372    {
 373  40 this.write(model.getTableDecorator().finishRow());
 374    }
 375   
 376    /**
 377    * Writes an HTML message to a JSP page explaining that the table model contains no data.
 378    * @see org.displaytag.render.TableWriterTemplate#writeEmptyListMessage(java.lang.String)
 379    */
 380  8 protected void writeEmptyListMessage(String emptyListMessage)
 381    {
 382  8 this.write(emptyListMessage);
 383    }
 384   
 385    /**
 386    * Writes a HTML table column value to a JSP page.
 387    * @see org.displaytag.render.TableWriterTemplate#writeColumnValue(java.lang.String,org.displaytag.model.Column)
 388    */
 389  1059 protected void writeColumnValue(Object value, Column column)
 390    {
 391  1059 this.write(value);
 392    }
 393   
 394    /**
 395    * Writes an HTML message to a JSP page explaining that the row contains no data.
 396    * @see org.displaytag.render.TableWriterTemplate#writeEmptyListRowMessage(java.lang.String)
 397    */
 398  4 protected void writeEmptyListRowMessage(String message)
 399    {
 400  4 this.write(message);
 401    }
 402   
 403    /**
 404    * Writes an HTML table's column header to a JSP page.
 405    * @see org.displaytag.render.TableWriterTemplate#writeTableHeader(org.displaytag.model.TableModel)
 406    */
 407  348 protected void writeTableHeader(TableModel model)
 408    {
 409   
 410  348 if (log.isDebugEnabled())
 411    {
 412  348 log.debug("[" + tableModel.getId() + "] getTableHeader called");
 413    }
 414   
 415    // open thead
 416  348 write(TagConstants.TAG_THEAD_OPEN);
 417   
 418    // open tr
 419  348 write(TagConstants.TAG_TR_OPEN);
 420   
 421    // no columns?
 422  348 if (this.tableModel.isEmpty())
 423    {
 424  2 write(TagConstants.TAG_TH_OPEN);
 425  2 write(TagConstants.TAG_TH_CLOSE);
 426    }
 427   
 428    // iterator on columns for header
 429  348 Iterator iterator = this.tableModel.getHeaderCellList().iterator();
 430   
 431  348 while (iterator.hasNext())
 432    {
 433    // get the header cell
 434  657 HeaderCell headerCell = (HeaderCell) iterator.next();
 435   
 436  657 if (headerCell.getSortable())
 437    {
 438  200 String cssSortable = this.properties.getCssSortable();
 439  200 headerCell.addHeaderClass(cssSortable);
 440    }
 441   
 442    // if sorted add styles
 443  657 if (headerCell.isAlreadySorted())
 444    {
 445    // sorted css class
 446  102 headerCell.addHeaderClass(this.properties.getCssSorted());
 447   
 448    // sort order css class
 449  102 headerCell.addHeaderClass(this.properties.getCssOrder(this.tableModel.isSortOrderAscending()));
 450    }
 451   
 452    // append th with html attributes
 453  657 write(headerCell.getHeaderOpenTag());
 454   
 455    // title
 456  657 String header = headerCell.getTitle();
 457   
 458    // column is sortable, create link
 459  657 if (headerCell.getSortable())
 460    {
 461    // creates the link for sorting
 462  200 Anchor anchor = new Anchor(getSortingHref(headerCell), header);
 463   
 464    // append to buffer
 465  200 header = anchor.toString();
 466    }
 467   
 468  657 write(header);
 469  657 write(headerCell.getHeaderCloseTag());
 470    }
 471   
 472    // close tr
 473  348 write(TagConstants.TAG_TR_CLOSE);
 474   
 475    // close thead
 476  348 write(TagConstants.TAG_THEAD_CLOSE);
 477   
 478  348 if (log.isDebugEnabled())
 479    {
 480  348 log.debug("[" + tableModel.getId() + "] getTableHeader end");
 481    }
 482    }
 483   
 484    /**
 485    * Generates the link to be added to a column header for sorting.
 486    * @param headerCell header cell the link should be added to
 487    * @return Href for sorting
 488    */
 489  200 private Href getSortingHref(HeaderCell headerCell)
 490    {
 491    // costruct Href from base href, preserving parameters
 492  200 Href href = (Href) this.baseHref.clone();
 493   
 494  200 if (this.tableModel.getForm() != null)
 495    {
 496  0 href = new PostHref(href, tableModel.getForm());
 497    }
 498   
 499  200 if (this.paginatedList == null)
 500    {
 501    // add column number as link parameter
 502  198 if (!this.tableModel.isLocalSort() && (headerCell.getSortName() != null))
 503    {
 504  6 href.addParameter(encodeParameter(TableTagParameters.PARAMETER_SORT), headerCell.getSortName());
 505  6 href.addParameter(encodeParameter(TableTagParameters.PARAMETER_SORTUSINGNAME), "1");
 506    }
 507    else
 508    {
 509  192 href.addParameter(encodeParameter(TableTagParameters.PARAMETER_SORT), headerCell.getColumnNumber());
 510    }
 511   
 512  198 boolean nowOrderAscending = true;
 513   
 514  198 if (headerCell.getDefaultSortOrder() != null)
 515    {
 516  26 boolean sortAscending = SortOrderEnum.ASCENDING.equals(headerCell.getDefaultSortOrder());
 517  26 nowOrderAscending = headerCell.isAlreadySorted()
 518    ? !this.tableModel.isSortOrderAscending()
 519    : sortAscending;
 520    }
 521    else
 522    {
 523  172 nowOrderAscending = !(headerCell.isAlreadySorted() && this.tableModel.isSortOrderAscending());
 524    }
 525   
 526  198 int sortOrderParam = nowOrderAscending ? SortOrderEnum.ASCENDING.getCode() : SortOrderEnum.DESCENDING
 527    .getCode();
 528  198 href.addParameter(encodeParameter(TableTagParameters.PARAMETER_ORDER), sortOrderParam);
 529   
 530    // If user want to sort the full table I need to reset the page number.
 531    // or if we aren't sorting locally we need to reset the page as well.
 532  198 if (this.tableModel.isSortFullTable() || !this.tableModel.isLocalSort())
 533    {
 534  40 href.addParameter(encodeParameter(TableTagParameters.PARAMETER_PAGE), 1);
 535    }
 536    }
 537    else
 538    {
 539  2 if (properties.getPaginationSkipPageNumberInSort())
 540    {
 541  2 href.removeParameter(properties.getPaginationPageNumberParam());
 542    }
 543   
 544  2 String sortProperty = headerCell.getSortProperty();
 545  2 if (sortProperty == null)
 546    {
 547  2 sortProperty = headerCell.getBeanPropertyName();
 548    }
 549   
 550  2 href.addParameter(properties.getPaginationSortParam(), sortProperty);
 551  2 String dirParam;
 552  2 if (headerCell.isAlreadySorted())
 553    {
 554  2 dirParam = tableModel.isSortOrderAscending() ? properties.getPaginationDescValue() : properties
 555    .getPaginationAscValue();
 556    }
 557    else
 558    {
 559  0 dirParam = properties.getPaginationAscValue();
 560    }
 561  2 href.addParameter(properties.getPaginationSortDirectionParam(), dirParam);
 562  2 if (paginatedList.getSearchId() != null)
 563    {
 564  2 href.addParameter(properties.getPaginationSearchIdParam(), paginatedList.getSearchId());
 565    }
 566    }
 567   
 568  200 return href;
 569    }
 570   
 571    /**
 572    * encode a parameter name to be unique in the page using ParamEncoder.
 573    * @param parameterName parameter name to encode
 574    * @return String encoded parameter name
 575    */
 576  614 private String encodeParameter(String parameterName)
 577    {
 578    // paramEncoder has been already instantiated?
 579  614 if (this.paramEncoder == null)
 580    {
 581    // use the id attribute to get the unique identifier
 582  192 this.paramEncoder = new ParamEncoder(this.tableModel.getId());
 583    }
 584   
 585  614 return this.paramEncoder.encodeParameterName(parameterName);
 586    }
 587   
 588    /**
 589    * Generates table footer with links for export commands.
 590    */
 591  352 public void writeNavigationAndExportLinks()
 592    {
 593    // Put the page stuff there if it needs to be there...
 594  352 if (this.properties.getAddPagingBannerBottom())
 595    {
 596  14 writeSearchResultAndNavigation();
 597    }
 598   
 599    // add export links (only if the table is not empty)
 600  352 if (this.export && this.tableModel.getRowListPage().size() != 0)
 601    {
 602  18 writeExportLinks();
 603    }
 604    }
 605   
 606    /**
 607    * generates the search result and navigation bar.
 608    */
 609  356 public void writeSearchResultAndNavigation()
 610    {
 611  356 if ((this.paginatedList == null && this.pagesize != 0 && this.listHelper != null)
 612    || (this.paginatedList != null))
 613    {
 614    // create a new href
 615  102 Href navigationHref = (Href) this.baseHref.clone();
 616   
 617  102 if (tableModel.getForm() != null)
 618    {
 619  2 navigationHref = new PostHref(navigationHref, tableModel.getForm());
 620    }
 621   
 622  102 write(this.listHelper.getSearchResultsSummary());
 623   
 624  102 String pageParameter;
 625  102 if (paginatedList == null)
 626    {
 627  100 pageParameter = encodeParameter(TableTagParameters.PARAMETER_PAGE);
 628    }
 629    else
 630    {
 631  2 pageParameter = properties.getPaginationPageNumberParam();
 632  2 if ((paginatedList.getSearchId() != null)
 633    && (!navigationHref.getParameterMap().containsKey(properties.getPaginationSearchIdParam())))
 634    {
 635  2 navigationHref.addParameter(properties.getPaginationSearchIdParam(), paginatedList.getSearchId());
 636    }
 637    }
 638  102 write(this.listHelper.getPageNavigationBar(navigationHref, pageParameter));
 639    }
 640    }
 641   
 642    /**
 643    * Writes the formatted export links section.
 644    */
 645  18 private void writeExportLinks()
 646    {
 647    // Figure out what formats they want to export, make up a little string
 648  18 Href exportHref = (Href) this.baseHref.clone();
 649   
 650  18 StringBuffer buffer = new StringBuffer(200);
 651  18 Iterator iterator = MediaTypeEnum.iterator();
 652   
 653  18 while (iterator.hasNext())
 654    {
 655  122 MediaTypeEnum currentExportType = (MediaTypeEnum) iterator.next();
 656   
 657  122 if (this.properties.getAddExport(currentExportType))
 658    {
 659   
 660  72 if (buffer.length() > 0)
 661    {
 662  54 buffer.append(this.properties.getExportBannerSeparator());
 663    }
 664   
 665  72 exportHref.addParameter(encodeParameter(TableTagParameters.PARAMETER_EXPORTTYPE), currentExportType
 666    .getCode());
 667   
 668    // export marker
 669  72 exportHref.addParameter(TableTagParameters.PARAMETER_EXPORTING, "1");
 670   
 671  72 Anchor anchor = new Anchor(exportHref, this.properties.getExportLabel(currentExportType));
 672  72 buffer.append(anchor.toString());
 673    }
 674    }
 675   
 676  18 String[] exportOptions = {buffer.toString()};
 677  18 write(MessageFormat.format(this.properties.getExportBanner(), exportOptions));
 678    }
 679   
 680    /**
 681    * create the open tag containing all the attributes.
 682    * @return open tag string: <code>%lt;table attribute="value" ... ></code>
 683    */
 684  352 public String getOpenTag()
 685    {
 686   
 687  352 if (this.uid != null && attributeMap.get(TagConstants.ATTRIBUTE_ID) == null)
 688    {
 689    // we need to clone the attribute map in order to "fix" the html id when using only the "uid" attribute
 690  279 Map localAttributeMap = (Map) attributeMap.clone();
 691  279 localAttributeMap.put(TagConstants.ATTRIBUTE_ID, this.uid);
 692   
 693  279 StringBuffer buffer = new StringBuffer();
 694  279 buffer.append(TagConstants.TAG_OPEN).append(TagConstants.TABLE_TAG_NAME);
 695  279 buffer.append(localAttributeMap);
 696  279 buffer.append(TagConstants.TAG_CLOSE);
 697   
 698  279 return buffer.toString();
 699   
 700    }
 701   
 702    // fast, no clone
 703  73 StringBuffer buffer = new StringBuffer();
 704   
 705  73 buffer.append(TagConstants.TAG_OPEN).append(TagConstants.TABLE_TAG_NAME);
 706  73 buffer.append(attributeMap);
 707  73 buffer.append(TagConstants.TAG_CLOSE);
 708   
 709  73 return buffer.toString();
 710    }
 711   
 712    /**
 713    * Utility method.
 714    * @param string String
 715    */
 716  9119 public void write(String string)
 717    {
 718  9119 if (string != null)
 719    {
 720  9045 try
 721    {
 722  9045 out.write(string);
 723    }
 724    catch (IOException e)
 725    {
 726  0 throw new WrappedRuntimeException(getClass(), e);
 727    }
 728    }
 729   
 730    }
 731   
 732  360 public void writeTable(TableModel model, String id) throws JspException
 733    {
 734  360 super.writeTable(model, id);
 735    }
 736   
 737    /**
 738    * Utility method.
 739    * @param string String
 740    */
 741  1059 public void write(Object string)
 742    {
 743  1059 if (string != null)
 744    {
 745  1059 try
 746    {
 747  1059 out.write(string.toString());
 748    }
 749    catch (IOException e)
 750    {
 751  0 throw new WrappedRuntimeException(getClass(), e);
 752    }
 753    }
 754   
 755    }
 756   
 757    }