/** * 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.model; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.servlet.jsp.PageContext; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.displaytag.decorator.TableDecorator; import org.displaytag.properties.MediaTypeEnum; import org.displaytag.properties.TableProperties; import org.displaytag.render.TableTotaler; /** * Table Model. Holds table data for presentation. * @author Fabrizio Giustina * @version $Revision$ ($Author$) */ public class TableModel { /** * logger. */ private static Log log = LogFactory.getLog(TableModel.class); /** * list of HeaderCell. */ private List<HeaderCell> headerCellList; /** * full list (contains Row objects). */ private List<Row> rowListFull; /** * list of data to be displayed in page. */ private List<Row> rowListPage; /** * Name of the column currently sorted (only used when sort=external). */ private String sortedColumnName; /** * sort order = ascending? */ private boolean sortOrderAscending = true; /** * sort full List? (false sort only displayed page). */ private boolean sortFullTable = true; /** * index of the sorted column (-1 if the table is not sorted). */ private int sortedColumn = -1; /** * Table decorator. */ private TableDecorator tableDecorator; /** * id inherited from the TableTag (needed only for logging). */ private String id; /** * configurable table properties. */ private TableProperties properties; /** * Starting offset for elements in the viewable list. */ private int pageOffset; /** * Response encoding. */ private String encoding; /** * Are we sorting locally? (Default True) */ private boolean localSort = true; /** * Table caption. */ private String caption; /** * Table footer. */ private String footer; /** * Jsp page context. */ private PageContext pageContext; /** * Current media. */ private MediaTypeEnum media; /** * Uses post for links. */ private String form; private TableTotaler totaler; /** * Constructor for TableModel. * @param tableProperties table properties * @param charEncoding response encoding */ public TableModel(TableProperties tableProperties, String charEncoding, PageContext pageContext) { this.rowListFull = new ArrayList<Row>(20); this.headerCellList = new ArrayList<HeaderCell>(20); this.properties = tableProperties; this.encoding = charEncoding; this.pageContext = pageContext; } /** * Returns the jsp page context. * @return page context */ protected PageContext getPageContext() { return this.pageContext; } /** * Gets the current media type. * @return current media (html, pdf ...) */ public MediaTypeEnum getMedia() { return this.media; } /** * sets the current media type. * @param media current media (html, pdf ...) */ public void setMedia(MediaTypeEnum media) { this.media = media; } /** * Sets whether the table performs local in memory sorting of the data. * @param localSort */ public void setLocalSort(boolean localSort) { this.localSort = localSort; } /** * @return sorting in local memory */ public boolean isLocalSort() { return localSort; } /** * Getter for <code>form</code>. * @return Returns the form. */ public String getForm() { return this.form; } /** * Setter for <code>form</code>. * @param form The form to set. */ public void setForm(String form) { this.form = form; } /** * Getter for <code>pageOffset</code> * @return Returns the page offset. */ public int getPageOffset() { return this.pageOffset; } /** * Sets the starting offset for elements in the viewable list. * @param offset The page offset to set. */ public void setPageOffset(int offset) { this.pageOffset = offset; } /** * Setter for the tablemodel id. * @param tableId same id of table tag, needed for logging */ public void setId(String tableId) { this.id = tableId; } /** * get the table id. * @return table id */ public String getId() { return this.id; } /** * get the full list. * @return the full list containing Row objects */ public List<Row> getRowListFull() { return this.rowListFull; } /** * gets the partial (paginated) list. * @return the partial list to display in page (contains Row objects) */ public List<Row> getRowListPage() { return this.rowListPage; } /** * adds a Row object to the table. * @param row Row */ public void addRow(Row row) { row.setParentTable(this); if (log.isDebugEnabled()) { log.debug("[" + this.id + "] adding row " + row); } this.rowListFull.add(row); } /** * sets the name of the currently sorted column * @param sortedColumnName */ public void setSortedColumnName(String sortedColumnName) { this.sortedColumnName = sortedColumnName; } /** * sets the sort full table property. If true the full list is sorted, if false sorting is applied only to the * displayed sublist. * @param sortFull boolean */ public void setSortFullTable(boolean sortFull) { this.sortFullTable = sortFull; } /** * return the sort full table property. * @return boolean true if sorting is applied to the full list */ public boolean isSortFullTable() { return this.sortFullTable; } /** * return the sort order of the page. * @return true if sort order is ascending */ public boolean isSortOrderAscending() { return this.sortOrderAscending; } /** * set the sort order of the list. * @param isSortOrderAscending true to sort in ascending order */ public void setSortOrderAscending(boolean isSortOrderAscending) { this.sortOrderAscending = isSortOrderAscending; } /** * @param rowList - the new value for this.rowListPage */ public void setRowListPage(List<Row> rowList) { this.rowListPage = rowList; } /** * getter for the Table Decorator. * @return TableDecorator */ public TableDecorator getTableDecorator() { return this.tableDecorator; } /** * setter for the table decorator. * @param decorator - the TableDecorator object */ public void setTableDecorator(TableDecorator decorator) { this.tableDecorator = decorator; } /** * returns true if the table is sorted. * @return boolean true if the table is sorted */ public boolean isSorted() { return this.sortedColumn != -1; } /** * returns the HeaderCell for the sorted column. * @return HeaderCell */ public HeaderCell getSortedColumnHeader() { if (this.sortedColumn < 0 || (this.sortedColumn > (this.headerCellList.size() - 1))) { return null; } return this.headerCellList.get(this.sortedColumn); } /** * return the number of columns in the table. * @return int number of columns */ public int getNumberOfColumns() { return this.headerCellList.size(); } /** * return true is the table has no columns. * @return boolean */ public boolean isEmpty() { return this.headerCellList.size() == 0; } /** * return the index of the sorted column. * @return index of the sorted column or -1 if the table is not sorted */ public int getSortedColumnNumber() { return this.sortedColumn; } /** * set the sorted column index. * @param sortIndex - the index of the sorted column */ public void setSortedColumnNumber(int sortIndex) { this.sortedColumn = sortIndex; } /** * Adds a column header (HeaderCell object). * @param headerCell HeaderCell */ public void addColumnHeader(HeaderCell headerCell) { if (this.sortedColumnName == null) { if (this.sortedColumn == this.headerCellList.size()) { headerCell.setAlreadySorted(); } } else { // the sorted parameter was a string so try and find that column name and set it as sorted if (this.sortedColumnName.equals(headerCell.getSortName())) { headerCell.setAlreadySorted(); } } headerCell.setColumnNumber(this.headerCellList.size()); this.headerCellList.add(headerCell); } /** * List containing headerCell objects. * @return List containing headerCell objects */ public List<HeaderCell> getHeaderCellList() { return this.headerCellList; } /** * returns a RowIterator on the requested (full|page) list. * @return RowIterator * @param full if <code>true</code> returns an iterator on te full list, if <code>false</code> only on the viewable * part. * @see org.displaytag.model.RowIterator */ public RowIterator getRowIterator(boolean full) { RowIterator iterator = new RowIterator( full ? this.rowListFull : this.rowListPage, this.headerCellList, this.tableDecorator, this.pageOffset); // copy id for logging iterator.setId(this.id); return iterator; } /** * sorts the given list of Rows. The method is called internally by sortFullList() and sortPageList(). * @param list List */ private void sortRowList(List<Row> list) { if (isSorted()) { HeaderCell sortedHeaderCell = getSortedColumnHeader(); if (sortedHeaderCell != null) { // If it is an explicit value, then sort by that, otherwise sort by the property... if (sortedHeaderCell.getBeanPropertyName() != null || (this.sortedColumn != -1 && this.sortedColumn < this.headerCellList.size())) { String sorted = (sortedHeaderCell.getSortProperty() != null) ? sortedHeaderCell.getSortProperty() : sortedHeaderCell.getBeanPropertyName(); Collections.sort(list, new RowSorter( this.sortedColumn, sorted, getTableDecorator(), this.sortOrderAscending, sortedHeaderCell.getComparator())); } } } } /** * sort the list displayed in page. */ public void sortPageList() { if (log.isDebugEnabled()) { log.debug("[" + this.id + "] sorting page list"); } sortRowList(this.rowListPage); } /** * sort the full list of data. */ public void sortFullList() { if (log.isDebugEnabled()) { log.debug("[" + this.id + "] sorting full data"); } sortRowList(this.rowListFull); } /** * Returns the table properties. * @return the configured table properties. */ public TableProperties getProperties() { return this.properties; } /** * Getter for character encoding. * @return Returns the encoding used for response. */ public String getEncoding() { return encoding; } /** * Obtain this table's caption. * @return This table's caption. */ public String getCaption() { return this.caption; } /** * Set this table's caption. * @param caption This table's caption. */ public void setCaption(String caption) { this.caption = caption; } /** * Obtain this table's footer. * @return This table's footer. */ public String getFooter() { return this.footer; } /** * Set this table's footer. * @param footer This table's footer. */ public void setFooter(String footer) { this.footer = footer; } /** * @see java.lang.Object#toString() */ public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) // .append("rowListFull", this.rowListFull) //$NON-NLS-1$ .append("rowListPage", this.rowListPage) //$NON-NLS-1$ .append("properties", this.properties) //$NON-NLS-1$ .append("empty", this.isEmpty()) //$NON-NLS-1$ .append("encoding", this.encoding) //$NON-NLS-1$ .append("numberOfColumns", this.getNumberOfColumns()) //$NON-NLS-1$ .append("headerCellList", this.headerCellList) //$NON-NLS-1$ .append("sortFullTable", this.sortFullTable) //$NON-NLS-1$ .append("sortedColumnNumber", this.getSortedColumnNumber()) //$NON-NLS-1$ .append("sortOrderAscending", this.sortOrderAscending) //$NON-NLS-1$ .append("sortedColumnHeader", this.getSortedColumnHeader()) //$NON-NLS-1$ .append("sorted", this.isSorted()) //$NON-NLS-1$ .append("tableDecorator", this.tableDecorator) //$NON-NLS-1$ .append("caption", this.caption) //$NON-NLS-1 .append("footer", this.footer) //$NON-NLS-1 .append("media", this.media) //$NON-NLS-1 .toString(); } public TableTotaler getTotaler() { return totaler; } public void setTotaler(TableTotaler totaler) { this.totaler = totaler; } public void reset() { totaler.reset(); totaler.init(this); } }