View Javadoc

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.model;
13  
14  import java.util.ArrayList;
15  import java.util.Collections;
16  import java.util.List;
17  
18  import org.apache.commons.lang.builder.ToStringBuilder;
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  import org.displaytag.decorator.TableDecorator;
22  import org.displaytag.properties.TableProperties;
23  import org.displaytag.util.ShortToStringStyle;
24  
25  
26  /***
27   * Table Model. Holds table data for presentation.
28   * @author Fabrizio Giustina
29   * @version $Revision: 1.17 $ ($Author: fgiust $)
30   */
31  public class TableModel
32  {
33  
34      /***
35       * logger.
36       */
37      private static Log log = LogFactory.getLog(TableModel.class);
38  
39      /***
40       * list of HeaderCell.
41       */
42      private List headerCellList;
43  
44      /***
45       * full list (contains Row objects).
46       */
47      private List rowListFull;
48  
49      /***
50       * list of data to be displayed in page.
51       */
52      private List rowListPage;
53  
54      /***
55       * sort order = ascending?
56       */
57      private boolean sortOrderAscending = true;
58  
59      /***
60       * sort full List? (false sort only displayed page).
61       */
62      private boolean sortFullTable = true;
63  
64      /***
65       * index of the sorted column (-1 if the table is not sorted).
66       */
67      private int sortedColumn = -1;
68  
69      /***
70       * Table decorator.
71       */
72      private TableDecorator tableDecorator;
73  
74      /***
75       * id inherited from the TableTag (needed only for logging).
76       */
77      private String id;
78  
79      /***
80       * configurable table properties.
81       */
82      private TableProperties properties;
83  
84      /***
85       * Starting offset for elements in the viewable list.
86       */
87      private int pageOffset;
88  
89      /***
90       * Response encoding.
91       */
92      private String encoding;
93  
94      /***
95       * Constructor for TableModel.
96       * @param tableProperties table properties
97       * @param charEncoding response encoding
98       */
99      public TableModel(TableProperties tableProperties, String charEncoding)
100     {
101         this.rowListFull = new ArrayList(20);
102         this.headerCellList = new ArrayList(20);
103         this.properties = tableProperties;
104         this.encoding = charEncoding;
105     }
106 
107     /***
108      * Sets the starting offset for elements in the viewable list.
109      * @param offset The page offset to set.
110      */
111     public void setPageOffset(int offset)
112     {
113         this.pageOffset = offset;
114     }
115 
116     /***
117      * Setter for the tablemodel id.
118      * @param tableId same id of table tag, needed for logging
119      */
120     public void setId(String tableId)
121     {
122         this.id = tableId;
123     }
124 
125     /***
126      * get the full list.
127      * @return the full list containing Row objects
128      */
129     public List getRowListFull()
130     {
131         return this.rowListFull;
132     }
133 
134     /***
135      * gets the partial (paginated) list.
136      * @return the partial list to display in page (contains Row objects)
137      */
138     public List getRowListPage()
139     {
140         return this.rowListPage;
141     }
142 
143     /***
144      * adds a Row object to the table.
145      * @param row Row
146      */
147     public void addRow(Row row)
148     {
149         row.setParentTable(this);
150 
151         if (log.isDebugEnabled())
152         {
153             log.debug("[" + this.id + "] adding row " + row);
154         }
155         this.rowListFull.add(row);
156     }
157 
158     /***
159      * sets the sort full table property. If true the full list is sorted, if false sorting is applied only to the
160      * displayed sublist.
161      * @param sortFull boolean
162      */
163     public void setSortFullTable(boolean sortFull)
164     {
165         this.sortFullTable = sortFull;
166     }
167 
168     /***
169      * return the sort full table property.
170      * @return boolean true if sorting is applied to the full list
171      */
172     public boolean isSortFullTable()
173     {
174         return this.sortFullTable;
175     }
176 
177     /***
178      * return the sort order of the page.
179      * @return true if sort order is ascending
180      */
181     public boolean isSortOrderAscending()
182     {
183         return this.sortOrderAscending;
184 
185     }
186 
187     /***
188      * set the sort order of the list.
189      * @param isSortOrderAscending true to sort in ascending order
190      */
191     public void setSortOrderAscending(boolean isSortOrderAscending)
192     {
193         this.sortOrderAscending = isSortOrderAscending;
194     }
195 
196     /***
197      * @param rowList - the new value for this.rowListPage
198      */
199     public void setRowListPage(List rowList)
200     {
201         this.rowListPage = rowList;
202     }
203 
204     /***
205      * getter for the Table Decorator.
206      * @return TableDecorator
207      */
208     public TableDecorator getTableDecorator()
209     {
210         return this.tableDecorator;
211     }
212 
213     /***
214      * setter for the table decorator.
215      * @param decorator - the TableDecorator object
216      */
217     public void setTableDecorator(TableDecorator decorator)
218     {
219         this.tableDecorator = decorator;
220     }
221 
222     /***
223      * returns true if the table is sorted.
224      * @return boolean true if the table is sorted
225      */
226     public boolean isSorted()
227     {
228         return this.sortedColumn != -1;
229     }
230 
231     /***
232      * returns the HeaderCell for the sorted column.
233      * @return HeaderCell
234      */
235     public HeaderCell getSortedColumnHeader()
236     {
237         if (this.sortedColumn < 0 || (this.sortedColumn > (this.headerCellList.size() - 1)))
238         {
239             return null;
240         }
241         return (HeaderCell) this.headerCellList.get(this.sortedColumn);
242     }
243 
244     /***
245      * return the number of columns in the table.
246      * @return int number of columns
247      */
248     public int getNumberOfColumns()
249     {
250         return this.headerCellList.size();
251     }
252 
253     /***
254      * return true is the table has no columns.
255      * @return boolean
256      */
257     public boolean isEmpty()
258     {
259         return this.headerCellList.size() == 0;
260     }
261 
262     /***
263      * return the index of the sorted column.
264      * @return index of the sorted column or -1 if the table is not sorted
265      */
266     public int getSortedColumnNumber()
267     {
268         return this.sortedColumn;
269     }
270 
271     /***
272      * set the sorted column index.
273      * @param sortIndex - the index of the sorted column
274      */
275     public void setSortedColumnNumber(int sortIndex)
276     {
277         this.sortedColumn = sortIndex;
278     }
279 
280     /***
281      * Adds a column header (HeaderCell object).
282      * @param headerCell HeaderCell
283      */
284     public void addColumnHeader(HeaderCell headerCell)
285     {
286         if (this.sortedColumn == this.headerCellList.size())
287         {
288             headerCell.setAlreadySorted();
289         }
290         headerCell.setColumnNumber(this.headerCellList.size());
291 
292         this.headerCellList.add(headerCell);
293     }
294 
295     /***
296      * List containing headerCell objects.
297      * @return List containing headerCell objects
298      */
299     public List getHeaderCellList()
300     {
301         return this.headerCellList;
302     }
303 
304     /***
305      * returns a RowIterator on the requested (full|page) list.
306      * @return RowIterator
307      * @param full if <code>true</code> returns an iterator on te full list, if <code>false</code> only on the
308      * viewable part.
309      * @see org.displaytag.model.RowIterator
310      */
311     public RowIterator getRowIterator(boolean full)
312     {
313         RowIterator iterator = new RowIterator(
314             full ? this.rowListFull : this.rowListPage,
315             this.headerCellList,
316             this.tableDecorator,
317             this.pageOffset);
318         // copy id for logging
319         iterator.setId(this.id);
320         return iterator;
321     }
322 
323     /***
324      * sorts the given list of Rows. The method is called internally by sortFullList() and sortPageList().
325      * @param list List
326      */
327     private void sortRowList(List list)
328     {
329         if (isSorted())
330         {
331             HeaderCell sortedHeaderCell = getSortedColumnHeader();
332 
333             if (sortedHeaderCell != null)
334             {
335                 // If it is an explicit value, then sort by that, otherwise sort by the property...
336                 if (sortedHeaderCell.getBeanPropertyName() != null
337                     || (this.sortedColumn != -1 && this.sortedColumn < this.headerCellList.size()))
338                 {
339                     if (sortedHeaderCell.getSortProperty() != null)
340                     {
341                         Collections.sort(list, new RowSorter(
342                             this.sortedColumn,
343                             sortedHeaderCell.getSortProperty(),
344                             getTableDecorator(),
345                             this.sortOrderAscending));
346                     }
347                     else
348                     {
349                         Collections.sort(list, new RowSorter(
350                             this.sortedColumn,
351                             sortedHeaderCell.getBeanPropertyName(),
352                             getTableDecorator(),
353                             this.sortOrderAscending));
354                     }
355                 }
356             }
357 
358         }
359 
360     }
361 
362     /***
363      * sort the list displayed in page.
364      */
365     public void sortPageList()
366     {
367         if (log.isDebugEnabled())
368         {
369             log.debug("[" + this.id + "] sorting page list");
370         }
371         sortRowList(this.rowListPage);
372 
373     }
374 
375     /***
376      * sort the full list of data.
377      */
378     public void sortFullList()
379     {
380         if (log.isDebugEnabled())
381         {
382             log.debug("[" + this.id + "] sorting full data");
383         }
384         sortRowList(this.rowListFull);
385     }
386 
387     /***
388      * Returns the table properties.
389      * @return the configured table properties.
390      */
391     public TableProperties getProperties()
392     {
393         return this.properties;
394     }
395 
396     /***
397      * Getter for character encoding.
398      * @return Returns the encoding used for response.
399      */
400     public String getEncoding()
401     {
402         return encoding;
403     }
404 
405     /***
406      * @see java.lang.Object#toString()
407      */
408     public String toString()
409     {
410         return new ToStringBuilder(this, ShortToStringStyle.SHORT_STYLE) //
411             .append("rowListFull", this.rowListFull) //$NON-NLS-1$
412             .append("rowListPage", this.rowListPage) //$NON-NLS-1$
413             .append("properties", this.properties) //$NON-NLS-1$
414             .append("empty", this.isEmpty()) //$NON-NLS-1$
415             .append("encoding", this.encoding) //$NON-NLS-1$
416             .append("numberOfColumns", this.getNumberOfColumns()) //$NON-NLS-1$
417             .append("headerCellList", this.headerCellList) //$NON-NLS-1$
418             .append("sortFullTable", this.sortFullTable) //$NON-NLS-1$
419             .append("sortedColumnNumber", this.getSortedColumnNumber()) //$NON-NLS-1$
420             .append("sortOrderAscending", this.sortOrderAscending) //$NON-NLS-1$
421             .append("sortedColumnHeader", this.getSortedColumnHeader()) //$NON-NLS-1$
422             .append("sorted", this.isSorted()) //$NON-NLS-1$
423             .append("tableDecorator", this.tableDecorator) //$NON-NLS-1$
424             .toString();
425     }
426 }