[displaytag-cvs] displaytag/src/main/java/org/displaytag/render HtmlTableWriter.java,NONE,1.1 TableW
Brought to you by:
fgiust
|
From: fabrizio g. <fg...@us...> - 2005-10-16 20:35:01
|
Update of /cvsroot/displaytag/displaytag/src/main/java/org/displaytag/render In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18315/src/main/java/org/displaytag/render Added Files: HtmlTableWriter.java TableWriterTemplate.java TableWriterAdapter.java ItextTableWriter.java Log Message: committing DISPL-245 WYSIWYG Exports - from Jorge L. Barroso + some changes and fixes --- NEW FILE: HtmlTableWriter.java --- /** * Licensed under the Artistic License; you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://displaytag.sourceforge.net/license.html * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ package org.displaytag.render; import javax.servlet.jsp.JspWriter; import org.displaytag.exception.DecoratorException; import org.displaytag.exception.ObjectLookupException; import org.displaytag.model.Column; import org.displaytag.model.Row; import org.displaytag.model.TableModel; import org.displaytag.tags.CaptionTag; import org.displaytag.tags.TableTag; import org.displaytag.util.TagConstants; /** * A table writer that formats a table in HTML and writes it to a JSP page. (Background: this code was factored from * TableTag.writeHTMLData) * @author Jorge L. Barroso * @version $Revision$ ($Author$) * @see org.displaytag.render.TableWriterTemplate */ public class HtmlTableWriter extends TableWriterAdapter { /** * <code>TableTag</code> callback instance. */ private TableTag tableTag; /** * Output destination. */ private JspWriter out; /** * This table writer uses a <code>TableTag</code> and a <code>JspWriter</code> to do its work. * @param tableTag <code>TableTag</code> instance called back by this writer. * @param out The output destination. */ public HtmlTableWriter(TableTag tableTag, JspWriter out) { this.tableTag = tableTag; this.out = out; } /** * Writes a banner containing search result and paging navigation above an HTML table to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeTopBanner(org.displaytag.model.TableModel) */ protected void writeTopBanner(TableModel model) { this.tableTag.writeSearchResultAndNavigation(); } /** * Writes an HTML table's opening tags to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeTableOpener(org.displaytag.model.TableModel) */ protected void writeTableOpener(TableModel model) { this.write(this.tableTag.getOpenTag(), this.out); } /** * Writes an HTML table's caption to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeCaption(org.displaytag.model.TableModel) */ protected void writeCaption(TableModel model) { CaptionTag captionTag = this.tableTag.getCaptionTag(); this.write(captionTag.getOpenTag() + model.getCaption() + captionTag.getCloseTag(), this.out); } /** * Writes an HTML table's column header to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeTableHeader(org.displaytag.model.TableModel) */ protected void writeTableHeader(TableModel model) { // thead this.tableTag.writeTableHeader(); } /** * Writes an HTML table's footer to a JSP page; HTML requires tfoot to appear before tbody. * @see org.displaytag.render.TableWriterTemplate#writeFooter(org.displaytag.model.TableModel) */ protected void writePreBodyFooter(TableModel model) { this.write(TagConstants.TAG_TFOOTER_OPEN, this.out); this.write(model.getFooter(), this.out); this.write(TagConstants.TAG_TFOOTER_CLOSE, this.out); // reset footer this.tableTag.setFooter(null); } /** * Writes the start of an HTML table's body to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeTableBodyOpener(org.displaytag.model.TableModel) */ protected void writeTableBodyOpener(TableModel model) { this.write(TagConstants.TAG_TBODY_OPEN, this.out); } /** * Writes the end of an HTML table's body to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeTableBodyCloser(org.displaytag.model.TableModel) */ protected void writeTableBodyCloser(TableModel model) { this.write(TagConstants.TAG_TBODY_CLOSE, this.out); } /** * Writes the closing structure of an HTML table to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeTableCloser(org.displaytag.model.TableModel) */ protected void writeTableCloser(TableModel model) { this.write(this.tableTag.getCloseTag(), this.out); } /** * Writes a banner containing search result, paging navigation, and export links below an HTML table to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeBottomBanner(org.displaytag.model.TableModel) */ protected void writeBottomBanner(TableModel model) { this.tableTag.writeNavigationAndExportLinks(); } /** * @see org.displaytag.render.TableWriterTemplate#writeDecoratedTableFinish(org.displaytag.model.TableModel) */ protected void writeDecoratedTableFinish(TableModel model) { model.getTableDecorator().finish(); } /** * @see org.displaytag.render.TableWriterTemplate#writeDecoratedRowStart(org.displaytag.model.TableModel) */ protected void writeDecoratedRowStart(TableModel model) { String stringStartRow = model.getTableDecorator().startRow(); if (stringStartRow != null) { this.write(stringStartRow, this.out); } } /** * Writes an HTML table's row-opening tag to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeRowOpener(org.displaytag.model.Row) */ protected void writeRowOpener(Row row) { this.write(row.getOpenTag(), this.out); } /** * Writes an HTML table's column-opening tag to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeColumnOpener(org.displaytag.model.Column) */ protected void writeColumnOpener(Column column) throws ObjectLookupException, DecoratorException { this.write(column.getOpenTag(), this.out); } /** * Writes an HTML table's column-closing tag to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeColumnCloser(org.displaytag.model.Column) */ protected void writeColumnCloser(Column column) { this.write(column.getCloseTag(), this.out); } /** * Writes to a JSP page an HTML table row that has no columns. * @see org.displaytag.render.TableWriterTemplate#writeRowWithNoColumns(java.lang.String) */ protected void writeRowWithNoColumns(String rowValue) { this.write(TagConstants.TAG_TD_OPEN, this.out); this.write(rowValue, this.out); this.write(TagConstants.TAG_TD_CLOSE, this.out); } /** * Writes an HTML table's row-closing tag to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeRowCloser(org.displaytag.model.Row) */ protected void writeRowCloser(Row row) { this.write(row.getCloseTag(), this.out); } /** * @see org.displaytag.render.TableWriterTemplate#writeDecoratedRowFinish(org.displaytag.model.TableModel) */ protected void writeDecoratedRowFinish(TableModel model) { String endRow = model.getTableDecorator().finishRow(); if (endRow != null) { this.write(endRow, this.out); } } /** * Writes an HTML message to a JSP page explaining that the table model contains no data. * @see org.displaytag.render.TableWriterTemplate#writeEmptyListMessage(java.lang.String) */ protected void writeEmptyListMessage(String emptyListMessage) { this.write(emptyListMessage, out); } /** * Writes a HTML table column value to a JSP page. * @see org.displaytag.render.TableWriterTemplate#writeColumnValue(java.lang.String,org.displaytag.model.Column) */ protected void writeColumnValue(String value, Column column) { this.write(value, out); } /** * Writes an HTML message to a JSP page explaining that the row contains no data. * @see org.displaytag.render.TableWriterTemplate#writeEmptyListRowMessage(java.lang.String) */ protected void writeEmptyListRowMessage(String message) { this.write(message, out); } /** * Utility method. Write a string to the given JspWriter * @param string String * @param out JspWriter */ private void write(String string, JspWriter out) { this.tableTag.write(string, out); } } --- NEW FILE: TableWriterAdapter.java --- /** * Licensed under the Artistic License; you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://displaytag.sourceforge.net/license.html * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ package org.displaytag.render; import org.displaytag.model.Column; import org.displaytag.model.Row; import org.displaytag.model.TableModel; /** * Convenience abstract adapter for constructing a table view; contains only stub implementations. This class exists as * a convenience for creating table-writer objects. Extend this class to create a table writer and override the methods * of interest. This class also protects subclasses from future additions to TableWriterTemplate they may not be * interested in. * @author Jorge L. Barroso * @version $Revision$ ($Author$) */ public abstract class TableWriterAdapter extends TableWriterTemplate { /** * @see org.displaytag.render.TableWriterTemplate#writeEmptyListMessage(java.lang.String) */ protected void writeEmptyListMessage(String emptyListMessage) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeTopBanner(org.displaytag.model.TableModel) */ protected void writeTopBanner(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeTableOpener(org.displaytag.model.TableModel) */ protected void writeTableOpener(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeCaption(org.displaytag.model.TableModel) */ protected void writeCaption(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeTableHeader(org.displaytag.model.TableModel) */ protected void writeTableHeader(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writePreBodyFooter(org.displaytag.model.TableModel) */ protected void writePreBodyFooter(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeTableBodyOpener(org.displaytag.model.TableModel) */ protected void writeTableBodyOpener(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeTableBodyCloser(org.displaytag.model.TableModel) */ protected void writeTableBodyCloser(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writePostBodyFooter(org.displaytag.model.TableModel) */ protected void writePostBodyFooter(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeTableCloser(org.displaytag.model.TableModel) */ protected void writeTableCloser(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeBottomBanner(org.displaytag.model.TableModel) */ protected void writeBottomBanner(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeDecoratedTableFinish(org.displaytag.model.TableModel) */ protected void writeDecoratedTableFinish(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeDecoratedRowStart(org.displaytag.model.TableModel) */ protected void writeDecoratedRowStart(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeRowOpener(org.displaytag.model.Row) */ protected void writeRowOpener(Row row) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeColumnOpener(org.displaytag.model.Column) */ protected void writeColumnOpener(Column column) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeColumnValue(java.lang.String,org.displaytag.model.Column) */ protected void writeColumnValue(String value, Column column) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeColumnCloser(org.displaytag.model.Column) */ protected void writeColumnCloser(Column column) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeRowWithNoColumns(java.lang.String) */ protected void writeRowWithNoColumns(String string) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeRowCloser(org.displaytag.model.Row) */ protected void writeRowCloser(Row row) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeDecoratedRowFinish(org.displaytag.model.TableModel) */ protected void writeDecoratedRowFinish(TableModel model) throws Exception { } /** * @see org.displaytag.render.TableWriterTemplate#writeEmptyListRowMessage(java.lang.String) */ protected void writeEmptyListRowMessage(String message) throws Exception { } } --- NEW FILE: ItextTableWriter.java --- /** * Licensed under the Artistic License; you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://displaytag.sourceforge.net/license.html * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ package org.displaytag.render; import java.awt.Color; import java.util.Iterator; import org.apache.commons.lang.StringUtils; import org.displaytag.decorator.TableDecorator; import org.displaytag.decorator.itext.DecoratesItext; import org.displaytag.exception.DecoratorException; import org.displaytag.exception.ObjectLookupException; import org.displaytag.model.Column; import org.displaytag.model.HeaderCell; import org.displaytag.model.TableModel; import com.lowagie.text.BadElementException; import com.lowagie.text.Cell; import com.lowagie.text.Chunk; import com.lowagie.text.Document; import com.lowagie.text.DocumentException; import com.lowagie.text.Element; import com.lowagie.text.Font; import com.lowagie.text.FontFactory; import com.lowagie.text.Paragraph; import com.lowagie.text.Rectangle; import com.lowagie.text.Table; /** * A table writer that formats table as and writes it to an iText document. * @author Jorge L. Barroso * @version $Revision$ ($Author$) * @see org.displaytag.render.TableWriterTemplate */ public class ItextTableWriter extends TableWriterAdapter { /** * iText representation of the table. */ private Table table; /** * iText document to which the table is written. */ private Document document; /** * The default font used in the document. */ private Font defaultFont; /** * This table writer uses an iText table and document to do its work. * @param table iText representation of the table. * @param document iText document to which the table is written. */ public ItextTableWriter(Table table, Document document) { this.table = table; this.document = document; } /** * Initialize the main info holder table, like the appropriate number of columns. * @param model The table being represented as iText. * @see org.displaytag.render.TableWriterTemplate#writeTableOpener(org.displaytag.model.TableModel) */ protected void writeTableOpener(TableModel model) { this.table.setDefaultVerticalAlignment(Element.ALIGN_TOP); this.table.setCellsFitPage(true); this.table.setWidth(100); this.table.setPadding(2); this.table.setSpacing(0); this.table.setBorder(Rectangle.NO_BORDER); this.defaultFont = this.getTableFont(); } /** * Obtain the font used to render text in the table; Meant to be overriden if a different font is desired. * @return The font used to render text in the table. */ protected Font getTableFont() { return FontFactory.getFont(FontFactory.HELVETICA, 10, Font.NORMAL, new Color(0x00, 0x00, 0x00)); } /** * Write the table's caption to a iText document. * @see org.displaytag.render.TableWriterTemplate#writeCaption(org.displaytag.model.TableModel) */ protected void writeCaption(TableModel model) throws Exception { this.decorateCaption(model); } /** * Writes the table caption according to a set style. * @param model The table model containing the caption. * @throws DocumentException If an error occurrs while decorating the caption. */ private void decorateCaption(TableModel model) throws DocumentException { Paragraph caption = new Paragraph(new Chunk(model.getCaption(), this.getCaptionFont())); caption.setAlignment(this.getCaptionHorizontalAlignment()); this.document.add(caption); } /** * Obtain the caption font; Meant to be overriden if a different style is desired. * @return The caption font. */ protected Font getCaptionFont() { return FontFactory.getFont(FontFactory.HELVETICA, 17, Font.BOLD, new Color(0x00, 0x00, 0x00)); } /** * Obtain the caption horizontal alignment; Meant to be overriden if a different style is desired. * @return The caption horizontal alignment. */ protected int getCaptionHorizontalAlignment() { return Element.ALIGN_CENTER; } /** * Write the table's header columns to an iText document. * @see org.displaytag.render.TableWriterTemplate#writeTableHeader(org.displaytag.model.TableModel) * @throws BadElementException if an error occurs while writing header. */ protected void writeTableHeader(TableModel model) throws BadElementException { Iterator iterator = model.getHeaderCellList().iterator(); float[] widths = new float[model.getNumberOfColumns()]; for (int i = 0; iterator.hasNext(); i++) { HeaderCell headerCell = (HeaderCell) iterator.next(); widths[i] = this.getCellWidth(headerCell); String columnHeader = headerCell.getTitle(); if (columnHeader == null) { columnHeader = StringUtils.capitalize(headerCell.getBeanPropertyName()); } Cell hdrCell = this.getHeaderCell(columnHeader); this.table.addCell(hdrCell); } this.table.setWidths(widths); this.table.endHeaders(); } /** * Returns the maximum size of all values in this column. * @param headerCell Header cell for this column. * @return The maximum size of all values in this column. */ private float getCellWidth(HeaderCell headerCell) { int maxWidth = headerCell.getMaxLength(); return (maxWidth > 0) ? maxWidth : headerCell.getTitle().length(); } /** * @see org.displaytag.render.TableWriterTemplate#writePostBodyFooter(org.displaytag.model.TableModel) * @throws DocumentException if an error occurs while writing post-body footer. */ protected void writePostBodyFooter(TableModel model) throws DocumentException { Chunk cellContent = new Chunk(model.getFooter(), this.getFooterFont()); this.setFooterFontStyle(cellContent); Cell cell = new Cell(cellContent); cell.setLeading(8); cell.setBackgroundColor(this.getFooterBackgroundColor()); cell.setHorizontalAlignment(this.getFooterHorizontalAlignment()); cell.setColspan(model.getNumberOfColumns()); table.addCell(cell); } /** * Obtain the footer background color; Meant to be overriden if a different style is desired. * @return The footer background color. */ protected Color getFooterBackgroundColor() { return new Color(0xce, 0xcf, 0xce); } /** * Obtain the footer horizontal alignment; Meant to be overriden if a different style is desired. * @return The footer horizontal alignment. */ protected int getFooterHorizontalAlignment() { return Element.ALIGN_LEFT; } /** * Set the font style used to render the header text; Meant to be overridden if a different header style is desired. * @param cellContent The header content whose font will be modified. */ protected void setFooterFontStyle(Chunk cellContent) { this.setBoldStyle(cellContent, this.getFooterFontColor()); } /** * Obtain the footer font color; Meant to be overriden if a different style is desired. * @return The footer font color. */ protected Color getFooterFontColor() { return new Color(0x00, 0x00, 0x00); } /** * Obtain the footer font; Meant to be overriden if a different style is desired. * @return The footer font. */ protected Font getFooterFont() { return FontFactory.getFont(FontFactory.HELVETICA, 10); } /** * @see org.displaytag.render.TableWriterTemplate#writeDecoratedRowStart(org.displaytag.model.TableModel) */ protected void writeDecoratedRowStart(TableModel model) { DecoratesItext decorator = (DecoratesItext) model.getTableDecorator(); decorator.setTable(this.table); decorator.setFont(this.defaultFont); ((TableDecorator) decorator).startRow(); } /** * @see org.displaytag.render.TableWriterTemplate#writeDecoratedRowFinish(org.displaytag.model.TableModel) */ protected void writeDecoratedRowFinish(TableModel model) throws Exception { model.getTableDecorator().finishRow(); } /** * Write a column's opening structure to an iText document. * @see org.displaytag.render.TableWriterTemplate#writeColumnOpener(org.displaytag.model.Column) */ protected void writeColumnOpener(Column column) throws ObjectLookupException, DecoratorException { column.getOpenTag(); // has side effect, setting its stringValue, which affects grouping logic. } /** * Write a column's value to a iText document. * @see org.displaytag.render.TableWriterTemplate#writeColumnValue(java.lang.String,org.displaytag.model.Column) */ protected void writeColumnValue(String value, Column column) throws BadElementException { this.table.addCell(getCell(value)); } /** * @see org.displaytag.render.TableWriterTemplate#writeDecoratedTableFinish(org.displaytag.model.TableModel) */ protected void writeDecoratedTableFinish(TableModel model) { model.getTableDecorator().finish(); } /** * Returns a formatted cell for the given value. (Background: factored from PdfView) * @param value cell value * @return Cell * @throws BadElementException if errors occurs while generating content. */ private Cell getCell(String value) throws BadElementException { Cell cell = new Cell(new Chunk(StringUtils.trimToEmpty(value), this.defaultFont)); cell.setVerticalAlignment(Element.ALIGN_TOP); cell.setLeading(8); return cell; } /** * Obtain a header cell. * @param value Cell content. * @return A header cell with the given content. * @throws BadElementException if errors occurs while generating content. */ private Cell getHeaderCell(String value) throws BadElementException { Chunk cellContent = new Chunk(value, this.getHeaderFont()); setHeaderFontStyle(cellContent); Cell cell = new Cell(cellContent); cell.setLeading(8); cell.setHeader(true); cell.setHorizontalAlignment(this.getHeaderHorizontalAlignment()); cell.setBackgroundColor(this.getHeaderBackgroundColor()); return cell; } /** * Obtain the font used to render the header text; Meant to be overridden if a different header font is desired. * @return The font used to render the header text. */ protected Font getHeaderFont() { return this.defaultFont; } /** * Obtain the background color used to render the header; Meant to be overridden if a different header background * color is desired. * @return The backgrounc color used to render the header. */ protected Color getHeaderBackgroundColor() { return new Color(0xee, 0xee, 0xee); } /** * Set the font style used to render the header text; Meant to be overridden if a different header style is desired. * @param cellContent The header content whose font will be modified. */ protected void setHeaderFontStyle(Chunk cellContent) { setBoldStyle(cellContent, this.getHeaderFontColor()); } /** * Set the font color used to render the header text; Meant to be overridden if a different header style is desired. * @return The font color used to render the header text. */ protected Color getHeaderFontColor() { return new Color(0x00, 0x00, 0x00); } /** * Obtain the horizontal alignment used to render header text; Meant to be overridden if a different alignment is * desired. * @return The horizontal alignment used to render header text; */ protected int getHeaderHorizontalAlignment() { return Element.ALIGN_CENTER; } /** * Makes chunk content bold. * @param chunk The chunk whose content is to be rendered bold. * @param color The font color desired. */ private void setBoldStyle(Chunk chunk, Color color) { Font font = chunk.font(); chunk.setFont(FontFactory.getFont(font.getFamilyname(), font.size(), Font.BOLD, color)); } } --- NEW FILE: TableWriterTemplate.java --- /** * Licensed under the Artistic License; you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://displaytag.sourceforge.net/license.html * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ package org.displaytag.render; import java.text.MessageFormat; import java.util.Hashtable; import java.util.Map; import javax.servlet.jsp.JspException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.displaytag.model.Column; import org.displaytag.model.ColumnIterator; import org.displaytag.model.Row; import org.displaytag.model.RowIterator; import org.displaytag.model.TableModel; import org.displaytag.properties.TableProperties; import org.displaytag.util.TagConstants; /** * A template that encapsulates and drives the construction of a table based on a given table model and configuration. * This class is meant to be extended by classes that build tables sharing the same structure, sorting, and grouping, * but that write them in different formats and to various destinations. Subclasses must provide the format- and * destination-specific implementations of the abstract methods this class calls to build a table. (Background: This * class came about because our users wanted to export tables to Excel and PDF just as they were presented in HTML. It * originates with the TableTagData.writeHTMLData method, factoring its logic so that it can be re-used by classes that * write the tables as PDF, Excel, RTF and other formats. TableTagData.writeHTMLData now calls an HTML extension of this * class to write tables in HTML format to a JSP page.) * @author Jorge L. Barroso * @version $Revision$ ($Author$) */ public abstract class TableWriterTemplate { /** * logger. */ private static Log log = LogFactory.getLog(TableWriterTemplate.class); /** * Holds the previous row columns values. */ private Map previousRow; /** * Holds the next row columns values. */ private Map nextRow; /** * Table unique id. */ private String id; /** * Given a table model, this method creates a table, sorting and grouping it per its configuration, while delegating * where and how it writes the table to subclass objects. (Background: This method refactors * TableTagData.writeHTMLData method. See above.) * @param model The table model used to build the table. * @param id This table's page id. * @throws JspException if any exception thrown while constructing the tablei, it is caught and rethrown as a * JspException. Extension classes may throw all sorts of exceptions, depending on their respective formats and * destinations. */ public void writeTable(TableModel model, String id) throws JspException { try { // table id used for logging this.id = id; TableProperties properties = model.getProperties(); if (log.isDebugEnabled()) { log.debug("[" + this.id + "] writeTable called for table [" + this.id + "]"); } // Handle empty table boolean noItems = model.getRowListPage().size() == 0; if (noItems && !properties.getEmptyListShowTable()) { writeEmptyListMessage(properties.getEmptyListMessage()); return; } // variables to hold the previous row columns values. this.previousRow = new Hashtable(10); // variables to hold next row column values. this.nextRow = new Hashtable(10); // Put the page stuff there if it needs to be there... if (properties.getAddPagingBannerTop()) { // search result and navigation bar writeTopBanner(model); } // open table writeTableOpener(model); // render caption if (model.getCaption() != null) { writeCaption(model); } // render headers if (model.getProperties().getShowHeader()) { writeTableHeader(model); } // render footer prior to body if (model.getFooter() != null) { writePreBodyFooter(model); } // open table body writeTableBodyOpener(model); // render table body writeTableBody(model); // close table body writeTableBodyCloser(model); // render footer after body if (model.getFooter() != null) { writePostBodyFooter(model); } // close table writeTableCloser(model); if (model.getTableDecorator() != null) { writeDecoratedTableFinish(model); } writeBottomBanner(model); if (log.isDebugEnabled()) { log.debug("[" + this.id + "] writeTable end"); } } catch (Exception e) { throw new JspException(e); } } /* * writeTable callback methods */ /** * Called by writeTable to write a message explaining that the table model contains no data. * @param emptyListMessage A message explaining that the table model contains no data. * @throws Exception if it encounters an error while writing. */ protected abstract void writeEmptyListMessage(String emptyListMessage) throws Exception; /** * Called by writeTable to write a summary of the search result this table reports and the table's pagination * interface. * @param model The table model for which the banner is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeTopBanner(TableModel model) throws Exception; /** * Called by writeTable to write the start of the table structure. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeTableOpener(TableModel model) throws Exception; /** * Called by writeTable to write the table's caption. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeCaption(TableModel model) throws Exception; /** * Called by writeTable to write the table's header columns. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeTableHeader(TableModel model) throws Exception; /** * Called by writeTable to write table footer before table body. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writePreBodyFooter(TableModel model) throws Exception; /** * Called by writeTable to write the start of the table's body. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeTableBodyOpener(TableModel model) throws Exception; // protected abstract void writeTableBody(TableModel model); /** * Called by writeTable to write the end of the table's body. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeTableBodyCloser(TableModel model) throws Exception; /** * Called by writeTable to write table footer after table body. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writePostBodyFooter(TableModel model) throws Exception; /** * Called by writeTable to write the end of the table's structure. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeTableCloser(TableModel model) throws Exception; /** * Called by writeTable to decorate the table. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeDecoratedTableFinish(TableModel model) throws Exception; /** * Called by writeTable to write the table's footer. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeBottomBanner(TableModel model) throws Exception; /** * Given a table model, writes the table body content, sorting and grouping it per its configuration, while * delegating where and how it writes to subclass objects. (Background: This method refactors * TableTagData.writeTableBody method. See above.) * @param model The table model used to build the table body. * @throws Exception if an error is encountered while writing the table body. */ private void writeTableBody(TableModel model) throws Exception { // Ok, start bouncing through our list (only the visible part) RowIterator rowIterator = model.getRowIterator(false); // iterator on rows while (rowIterator.hasNext()) { Row row = rowIterator.next(); if (log.isDebugEnabled()) { log.debug("[" + this.id + "] rowIterator.next()=" + row); } // decorate row start if (model.getTableDecorator() != null) { writeDecoratedRowStart(model); } // open row writeRowOpener(row); // iterator on columns if (log.isDebugEnabled()) { log.debug("[" + this.id + "] creating ColumnIterator on " + model.getHeaderCellList()); } ColumnIterator columnIterator = row.getColumnIterator(model.getHeaderCellList()); while (columnIterator.hasNext()) { Column column = columnIterator.nextColumn(); // open column writeColumnOpener(column); // get the value to be displayed for the column String value = column.getChoppedAndLinkedValue(); // check if column is grouped if (column.getGroup() != -1) { value = this.groupColumns(value, column.getGroup()); } // render column value writeColumnValue(value, column); // close column writeColumnCloser(column); } // no columns? if (model.isEmpty()) { if (log.isDebugEnabled()) { log.debug("[" + this.id + "] table has no columns"); } // render empty row writeRowWithNoColumns(row.getObject().toString()); } // close row writeRowCloser(row); // decorate row finish if (model.getTableDecorator() != null) { writeDecoratedRowFinish(model); } } // render empty list message if (model.getRowListPage().size() == 0) { writeEmptyListRowMessage(MessageFormat.format( model.getProperties().getEmptyListRowMessage(), new Object[]{new Integer(model.getNumberOfColumns())})); } } /* * writeTableBody callback methods */ /** * Called by writeTableBody to write to decorate the table. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeDecoratedRowStart(TableModel model) throws Exception; /** * Called by writeTableBody to write the start of the row structure. * @param row The table row for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeRowOpener(Row row) throws Exception; /** * Called by writeTableBody to write the start of the column structure. * @param column The table column for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeColumnOpener(Column column) throws Exception; /** * Called by writeTableBody to write a column's value. * @param value The column value. * @param column The table column for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeColumnValue(String value, Column column) throws Exception; /** * Called by writeTableBody to write the end of the column structure. * @param column The table column for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeColumnCloser(Column column) throws Exception; /** * Called by writeTableBody to write a row that has no columns. * @param value The row value. * @throws Exception if it encounters an error while writing. */ protected abstract void writeRowWithNoColumns(String value) throws Exception; /** * Called by writeTableBody to write the end of the row structure. * @param row The table row for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeRowCloser(Row row) throws Exception; /** * Called by writeTableBody to decorate the table. * @param model The table model for which the content is written. * @throws Exception if it encounters an error while writing. */ protected abstract void writeDecoratedRowFinish(TableModel model) throws Exception; /** * Called by writeTableBody to write a message explaining that the row contains no data. * @param message The message explaining that the row contains no data. * @throws Exception if it encounters an error while writing. */ protected abstract void writeEmptyListRowMessage(String message) throws Exception; /** * Given a column value and grouping index, this method groups the column and returns the appropriate string back to * the caller. (Background: This method refactors TableTagData.writeTableBody method. See above.) * @param value String * @param group int * @return String */ private String groupColumns(String value, int group) { if ((group == 1) && this.nextRow.size() > 0) { // we are at the begining of the next row so copy the contents from nextRow to the previousRow. this.previousRow.clear(); this.previousRow.putAll(this.nextRow); this.nextRow.clear(); } if (!this.nextRow.containsKey(new Integer(group))) { // Key not found in the nextRow so adding this key now... // remember all the old values. this.nextRow.put(new Integer(group), value); } // Start comparing the value we received, along with the grouping index. // if no matching value is found in the previous row then return the value. // if a matching value is found then this value should not get printed out // so return an empty String if (this.previousRow.containsKey(new Integer(group))) { for (int j = 1; j <= group; j++) { if (!((String) this.previousRow.get(new Integer(j))).equals((this.nextRow.get(new Integer(j))))) { // no match found so return this value back to the caller. return value; } } } // This is used, for when there is no data in the previous row, // It gets used only the first time. if (this.previousRow.size() == 0) { return value; } // There is corresponding value in the previous row // this value doesn't need to be printed, return an empty String return TagConstants.EMPTY_STRING; } } |