View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kns.web.struts.form;
17  
18  import org.apache.commons.beanutils.BeanComparator;
19  import org.apache.commons.beanutils.PropertyUtils;
20  import org.apache.commons.lang.StringUtils;
21  import org.kuali.rice.kns.util.TableRenderUtil;
22  
23  import java.util.Collections;
24  import java.util.Comparator;
25  import java.util.Date;
26  import java.util.List;
27  
28  /**
29   * This class holds the metadata necessary to render a table when displaytag is not being used.
30   *
31   * @deprecated KNS Struts deprecated, use KRAD and the Spring MVC framework.
32   */
33  @Deprecated
34  public class KualiTableRenderFormMetadata {
35      private int viewedPageNumber;
36      private int totalNumberOfPages;
37      private int firstRowIndex;
38      private int lastRowIndex;
39      private int switchToPageNumber;
40  
41      /**
42       * The number of rows that match the query criteria
43       */
44      private int resultsActualSize;
45  
46      /**
47       * The number of rows that match the query criteria or
48       *  the max results limit size (if applicable), whichever is less
49       */
50      private int resultsLimitedSize;
51  
52      /**
53       * when the looked results screen was rendered, the index of the column that the results were sorted on.  -1 for unknown, index numbers
54       * starting at 0
55       */
56      private int previouslySortedColumnIndex;
57  
58      /**
59       * Comment for <code>columnToSortIndex</code>
60       */
61      private int columnToSortIndex;
62  
63      /**
64       * If it is not feasible to use an index for lookup, as with mapped properties in an Map<String, String>, it may be necessary to store a string value
65       */
66      private String columnToSortName;
67  
68      /**
69       * When the screen was last rendered, the column name on which it was previously sorted -- this is important for toggling between ascending and descending
70       * sort orders
71       */
72      private String previouslySortedColumnName;
73  
74      private boolean sortDescending;
75  
76      public KualiTableRenderFormMetadata() {
77          sortDescending = false;
78      }
79  
80      /**
81       * Gets the columnToSortIndex attribute.
82       * @return Returns the columnToSortIndex.
83       */
84      public int getColumnToSortIndex() {
85          return columnToSortIndex;
86      }
87  
88      /**
89       * Sets the columnToSortIndex attribute value.
90       * @param columnToSortIndex The columnToSortIndex to set.
91       */
92      public void setColumnToSortIndex(int columnToSortIndex) {
93          this.columnToSortIndex = columnToSortIndex;
94      }
95  
96      /**
97       * Gets the previouslySortedColumnIndex attribute.
98       * @return Returns the previouslySortedColumnIndex.
99       */
100     public int getPreviouslySortedColumnIndex() {
101         return previouslySortedColumnIndex;
102     }
103 
104     /**
105      * Sets the previouslySortedColumnIndex attribute value.
106      * @param previouslySortedColumnIndex The previouslySortedColumnIndex to set.
107      */
108     public void setPreviouslySortedColumnIndex(int previouslySortedColumnIndex) {
109         this.previouslySortedColumnIndex = previouslySortedColumnIndex;
110     }
111 
112     /**
113      * Gets the resultsActualSize attribute.
114      * @return Returns the resultsActualSize.
115      */
116     public int getResultsActualSize() {
117         return resultsActualSize;
118     }
119 
120     /**
121      * Sets the resultsActualSize attribute value.
122      * @param resultsActualSize The resultsActualSize to set.
123      */
124     public void setResultsActualSize(int resultsActualSize) {
125         this.resultsActualSize = resultsActualSize;
126     }
127 
128     /**
129      * Gets the resultsLimitedSize attribute.
130      * @return Returns the resultsLimitedSize.
131      */
132     public int getResultsLimitedSize() {
133         return resultsLimitedSize;
134     }
135 
136     /**
137      * Sets the resultsLimitedSize attribute value.
138      * @param resultsLimitedSize The resultsLimitedSize to set.
139      */
140     public void setResultsLimitedSize(int resultsLimitedSize) {
141         this.resultsLimitedSize = resultsLimitedSize;
142     }
143 
144     /**
145      * Gets the switchToPageNumber attribute.
146      * @return Returns the switchToPageNumber.
147      */
148     public int getSwitchToPageNumber() {
149         return switchToPageNumber;
150     }
151 
152     /**
153      * Sets the switchToPageNumber attribute value.
154      * @param switchToPageNumber The switchToPageNumber to set.
155      */
156     public void setSwitchToPageNumber(int switchToPageNumber) {
157         this.switchToPageNumber = switchToPageNumber;
158     }
159 
160     /**
161      * Gets the viewedPageNumber attribute.
162      * @return Returns the viewedPageNumber.
163      */
164     public int getViewedPageNumber() {
165         return viewedPageNumber;
166     }
167 
168     /**
169      * Sets the viewedPageNumber attribute value.
170      * @param viewedPageNumber The viewedPageNumber to set.
171      */
172     public void setViewedPageNumber(int viewedPageNumber) {
173         this.viewedPageNumber = viewedPageNumber;
174     }
175 
176     /**
177      * Gets the totalNumberOfPages attribute.
178      * @return Returns the totalNumberOfPages.
179      */
180     public int getTotalNumberOfPages() {
181         return totalNumberOfPages;
182     }
183 
184     /**
185      * Sets the totalNumberOfPages attribute value.
186      * @param totalNumberOfPages The totalNumberOfPages to set.
187      */
188     public void setTotalNumberOfPages(int totalNumberOfPages) {
189         this.totalNumberOfPages = totalNumberOfPages;
190     }
191 
192     /**
193      * Gets the firstRowIndex attribute.
194      * @return Returns the firstRowIndex.
195      */
196     public int getFirstRowIndex() {
197         return firstRowIndex;
198     }
199 
200     /**
201      * Sets the firstRowIndex attribute value.
202      * @param firstRowIndex The firstRowIndex to set.
203      */
204     public void setFirstRowIndex(int firstRowIndex) {
205         this.firstRowIndex = firstRowIndex;
206     }
207 
208     /**
209      * Gets the lastRowIndex attribute.
210      * @return Returns the lastRowIndex.
211      */
212     public int getLastRowIndex() {
213         return lastRowIndex;
214     }
215 
216     /**
217      * Sets the lastRowIndex attribute value.
218      * @param lastRowIndex The lastRowIndex to set.
219      */
220     public void setLastRowIndex(int lastRowIndex) {
221         this.lastRowIndex = lastRowIndex;
222     }
223 
224     /**
225      * Gets the sortDescending attribute.
226      * @return Returns the sortDescending.
227      */
228     public boolean isSortDescending() {
229         return sortDescending;
230     }
231 
232     /**
233      * Sets the sortDescending attribute value.
234      * @param sortDescending The sortDescending to set.
235      */
236     public void setSortDescending(boolean sortDescending) {
237         this.sortDescending = sortDescending;
238     }
239 
240 	/**
241 	 * @return the columnToSortName
242 	 */
243 	public String getColumnToSortName() {
244 		return this.columnToSortName;
245 	}
246 
247 	/**
248 	 * @param columnToSortName the columnToSortName to set
249 	 */
250 	public void setColumnToSortName(String columnToSortName) {
251 		this.columnToSortName = columnToSortName;
252 	}
253 
254 	/**
255 	 * @return the previouslySortedColumnName
256 	 */
257 	public String getPreviouslySortedColumnName() {
258 		return this.previouslySortedColumnName;
259 	}
260 
261 	/**
262 	 * @param previouslySortedColumnName the previouslySortedColumnName to set
263 	 */
264 	public void setPreviouslySortedColumnName(String previouslySortedColumnName) {
265 		this.previouslySortedColumnName = previouslySortedColumnName;
266 	}
267 
268 
269     /**
270      * Sets the paging form parameters to go to the first page of the list
271      *
272      * @param listSize size of table being rendered
273      * @param maxRowsPerPage
274      */
275     public void jumpToFirstPage(int listSize, int maxRowsPerPage) {
276         jumpToPage(0, listSize, maxRowsPerPage);
277     }
278 
279     /**
280      * Sets the paging form parameters to go to the last page of the list
281      *
282      * @param listSize size of table being rendered
283      * @param maxRowsPerPage
284      */
285     public void jumpToLastPage(int listSize, int maxRowsPerPage) {
286         jumpToPage(TableRenderUtil.computeTotalNumberOfPages(listSize, maxRowsPerPage) - 1, listSize, maxRowsPerPage);
287     }
288 
289     /**
290      * Sets the paging form parameters to go to the specified page of the list
291      *
292      * @param pageNumber first page is 0, must be non-negative.  If the list is not large enough to have the page specified, then
293      *   this method will be equivalent to calling jumpToLastPage.
294      * @param listSize size of table being rendered
295      * @param maxRowsPerPage
296      *
297      * @see KualiTableRenderFormMetadata#jumpToLastPage(int, int)
298      */
299     public void jumpToPage(int pageNumber, int listSize, int maxRowsPerPage) {
300         int totalPages = TableRenderUtil.computeTotalNumberOfPages(listSize, maxRowsPerPage);
301         setTotalNumberOfPages(totalPages);
302         if (pageNumber >= totalPages) {
303             pageNumber = totalPages - 1;
304         }
305         setViewedPageNumber(pageNumber);
306         setFirstRowIndex(TableRenderUtil.computeStartIndexForPage(pageNumber, listSize, maxRowsPerPage));
307         setLastRowIndex(TableRenderUtil.computeLastIndexForPage(pageNumber, listSize, maxRowsPerPage));
308     }
309 
310     /**
311      * Sorts a list on the form according to the form metadata (sortColumName, previouslySortedColumnName)
312      *
313      * @param memberTableMetadata
314      * @param items
315      * @param maxRowsPerPage
316      * @throws org.kuali.rice.kew.api.exception.WorkflowException
317      */
318     public void sort(List<?> items, int maxRowsPerPage) {
319 
320     	// Don't bother to sort null, empty or singleton lists
321     	if (items == null || items.size() <= 1)
322     		return;
323 
324         String columnToSortOn = getColumnToSortName();
325 
326         // Don't bother to sort if no column to sort on is provided
327         if (StringUtils.isEmpty(columnToSortOn))
328         	return;
329 
330         String previouslySortedColumnName = getPreviouslySortedColumnName();
331 
332         // We know members isn't null or empty from the check above
333     	Object firstItem = items.get(0);
334     	// Need to decide if the comparator is for a bean property or a mapped key on the qualififer attribute set
335     	Comparator comparator = null;
336     	Comparator subComparator = new Comparator<Object>() {
337 
338     		public int compare(Object o1, Object o2) {
339     			if (o1 == null)
340     				return -1;
341     			if (o2 == null)
342     				return 1;
343 
344     			if (o1 instanceof java.util.Date && o2 instanceof java.util.Date) {
345     				Date d1 = (Date)o1;
346     				Date d2 = (Date)o2;
347     				return d1.compareTo(d2);
348     			}
349 
350     			String s1 = o1.toString();
351     			String s2 = o2.toString();
352     			int n1=s1.length(), n2=s2.length();
353     			for (int i1=0, i2=0; i1<n1 && i2<n2; i1++, i2++) {
354     				char c1 = s1.charAt(i1);
355     				char c2 = s2.charAt(i2);
356     				if (c1 != c2) {
357     					c1 = Character.toUpperCase(c1);
358     					c2 = Character.toUpperCase(c2);
359     					if (c1 != c2) {
360     						c1 = Character.toLowerCase(c1);
361     						c2 = Character.toLowerCase(c2);
362     						if (c1 != c2) {
363     							return c1 - c2;
364     						}
365     					}
366     				}
367     			}
368     			return n1 - n2;
369     		}
370     	};
371     	// If the columnName is a readable bean property on the first member, then it's safe to say we need a simple bean property comparator,
372     	// otherwise it's a mapped property -- syntax for BeanComparator is "name" and "name(key)", respectively
373     	if (PropertyUtils.isReadable(firstItem, columnToSortOn))
374     		comparator = new BeanComparator(columnToSortOn, subComparator);
375     	else
376     		comparator = new BeanComparator(new StringBuilder().append("qualifierAsMap(").append(columnToSortOn).append(")").toString(), subComparator);
377 
378 
379         // If the user has decided to resort by the same column that the list is currently sorted by, then assume that s/he wants to reverse the order of the sort
380         if (!StringUtils.isEmpty(columnToSortOn) && !StringUtils.isEmpty(previouslySortedColumnName) && columnToSortOn.equals(previouslySortedColumnName)) {
381             // we're already sorted on the same column that the user clicked on, so we reverse the list
382             if (isSortDescending())
383                 comparator = Collections.reverseOrder(comparator);
384 
385             setSortDescending(!isSortDescending());
386         } else {
387         	// Track which column we're currently sorting, so that the above logic will work on the next sort
388         	setPreviouslySortedColumnName(columnToSortOn);
389         	setSortDescending(true);
390         }
391 
392         //if the user is just going between pages no need to sort
393         if (getSwitchToPageNumber() == getViewedPageNumber()) {
394             Collections.sort(items, comparator);
395         }
396 
397 		jumpToFirstPage(items.size(), maxRowsPerPage);
398     }
399 
400 }