View Javadoc

1   /***
2    * Copyright (c) 2003 held jointly by the individual authors.            
3    *                                                                          
4    * This library is free software; you can redistribute it and/or modify it    
5    * under the terms of the GNU Lesser General Public License as published      
6    * by the Free Software Foundation; either version 2.1 of the License, or 
7    * (at your option) any later version.                                            
8    *                                                                            
9    * This library is distributed in the hope that it will be useful, but 
10   * WITHOUT ANY WARRANTY; with out even the implied warranty of 
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
12   * GNU Lesser General Public License for more details.                                                  
13   *                                                                           
14   * You should have received a copy of the GNU Lesser General Public License   
15   * along with this library;  if not, write to the Free Software Foundation,   
16   * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.              
17   *                                                                            
18   * > http://www.gnu.org/copyleft/lesser.html                                  
19   * > http://www.opensource.org/licenses/lgpl-license.php
20   */
21  package net.mlw.vlh;
22  
23  import java.io.Serializable;
24  import java.util.ArrayList;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  
33  /***
34   * This bean holds all the information needed to retrieve a ValueList. This information is needed to allow for server side sorting, paging
35   * and focusing.
36   * 
37   * @author Matthew L. Wilson, Andrej Zachar
38   * @version $Revision: 1.20 $ $Date: 2006/03/29 19:47:49 $
39   */
40  public class ValueListInfo implements Serializable, PagingInfo
41  {
42     /***
43      * Comment for <code>serialVersionUID</code>
44      */
45     private static final long serialVersionUID = 3257572797588191543L;
46  
47     /*** The name of the ValueList requested. * */
48     public static final String VALUE_LIST_NAME = "valueListName";
49  
50     /*** Constant for an descending order. */
51     public static final Integer DESCENDING = new Integer(-1);
52  
53     /*** Constant for an ascending order. */
54     public static final Integer ASCENDING = new Integer(1);
55  
56     /*** Constant for an descending order. */
57     private static final String DESCENDING_STRING = "desc";
58  
59     /*** Constant for an ascending order. */
60     private static final String ASCENDING_STRING = "asc";
61  
62     /***
63      * General prefix for paging's parameters.
64      */
65     public static final String PAGING_PARAM_PREFIX = "paging";
66  
67     /*****************************************************************************************************************************************
68      * The string name of the attribute that should be used in Map backed transports, such as a Request Object.
69      ***************************************************************************************************************************************/
70     public static final String PAGING_PAGE = PAGING_PARAM_PREFIX + "Page";
71  
72     /*****************************************************************************************************************************************
73      * The string name of the attribute that should be used in Map backed transports, such as a Request Object.
74      ***************************************************************************************************************************************/
75     public static final String PAGING_NUMBER_PER = PAGING_PARAM_PREFIX + "NumberPer";
76  
77     /***
78      * General prefix for sorting's parameters.
79      */
80     public static final String SORT_PARAM_PREFIX = "sort";
81  
82     /*****************************************************************************************************************************************
83      * The string name of the attribute that should be used in Map backed transports, such as a Request Object.
84      ***************************************************************************************************************************************/
85     public static final String SORT_COLUMN = SORT_PARAM_PREFIX + "Column";
86  
87     /*****************************************************************************************************************************************
88      * The string name of the attribute that should be used in Map backed transports, such as a Request Object.
89      ***************************************************************************************************************************************/
90     public static final String SORT_DIRECTION = SORT_PARAM_PREFIX + "Direction";
91  
92     /*****************************************************************************************************************************************
93      * The string name of the attribute that should be used in Map backed transports, such as a Request Object.
94      ***************************************************************************************************************************************/
95     public static final String DO_FOCUS = "doFocus";
96  
97     /***
98      * General prefix for focus's parameters, DO_FOCUS has different
99      */
100    public static final String FOCUS_PARAM_PREFIX = "focus";
101 
102    /*****************************************************************************************************************************************
103     * The string name of the attribute that should be used in Map backed transports, such as a Request Object.
104     ***************************************************************************************************************************************/
105    public static final String FOCUS_VALUE = FOCUS_PARAM_PREFIX + "Value";
106 
107    /*****************************************************************************************************************************************
108     * The string name of the attribute that should be used in Map backed transports, such as a Request Object.
109     ***************************************************************************************************************************************/
110    public static final String FOCUS_PROPERTY = FOCUS_PARAM_PREFIX + "Property";
111 
112    /***
113     * The number of row in the table of the generated html page, in which is focus value of the focusProperty. Focus property could be
114     * hidden in the generated page.
115     */
116    private int focusedRowNumberInTable = -1;
117 
118    /*** Focus status. */
119    private byte focusStatus = FOCUS_STATUS_NOT_DEFINED;
120 
121    /*** Focus status when is not used. */
122    public static final byte FOCUS_STATUS_NOT_DEFINED = 0;
123 
124    /*** Focus value was founded. */
125    public static final byte FOCUS_FOUND = 1;
126 
127    /*** Focus value was not founded. */
128    public static final byte FOCUS_NOT_FOUND = 2;
129 
130    /*** Focusing is not possible, because in ResultSet are too many items - rows. */
131    public static final byte FOCUS_TOO_MANY_ITEMS = 4;
132 
133    /*** Holds the filters. */
134    private Map filters = null;
135 
136    /*** Total number of pages available. */
137    private int totalNumberOfEntries = 0;
138 
139    /*** Enable or disable valuelist paging. This setting should be used in the adapter in conjunction with DO_PAGE setting. */
140    //private boolean pagingEnabled = true;
141 
142    /*** Logger for logging warnings etc. */
143    private static final Log LOGGER = LogFactory.getLog(ValueListInfo.class);
144 
145    /***
146     * Default constructor.
147     */
148    public ValueListInfo()
149    {
150       filters = new HashMap();
151    }
152 
153    /***
154     * Default constructor.
155     * 
156     * @param parameters
157     *           The filters/parameters to initialize.
158     */
159    public ValueListInfo(Map parameters)
160    {
161       filters = new HashMap(parameters);
162       String sortColumn = getFilterParameterAsString(SORT_COLUMN);
163       if (sortColumn != null)
164       {
165          setPrimarySortColumn(sortColumn);
166       }
167 
168       String direction = getFilterParameterAsString(SORT_DIRECTION);
169       if (direction != null)
170       {
171          setPrimarySortDirection("asc".equals(direction) || "1".equals(direction) ? ASCENDING : DESCENDING);
172       }
173    }
174 
175    /***
176     * Creates a new ValueListInfo that contains sorting information
177     * 
178     * @param primaryColumn
179     *           The column to sort by
180     * @param primaryDirection
181     *           The direction to sort the <CODE>ValueList</CODE> by
182     */
183    public ValueListInfo(String primaryColumn, Integer primaryDirection)
184    {
185       this(primaryColumn, primaryDirection, new HashMap());
186    }
187 
188    /***
189     * Creates a new ValueListInfo that contains sorting information
190     * 
191     * @param primaryColumn
192     *           The column to sort by
193     * @param primaryDirection
194     *           The direction to sort the <CODE>ValueList</CODE> by
195     * @param filters
196     *           The filters of search criteria.
197     */
198    public ValueListInfo(String primaryColumn, Integer primaryDirection, Map filters)
199    {
200       //Set filters first, because the following methods need it.
201       this.filters = (filters == null) ? new HashMap() : filters;
202       setPrimarySortColumn(primaryColumn);
203       setPrimarySortDirection(primaryDirection);
204    }
205 
206    /***
207     * Getter for property filters.
208     * 
209     * @return Value of property filters.
210     */
211    public Map getFilters()
212    {
213       return filters;
214    }
215 
216    /***
217     * Returns an array of column (property) names.
218     * 
219     * @return a String array of column (property) names. null if no sorting information exists.
220     */
221    public String getSortingColumn()
222    {
223       return getFilterParameterAsString(SORT_COLUMN);
224    }
225 
226    public void setPrimarySortColumn(String column)
227    {
228       if (column == null)
229       {
230          filters.remove(SORT_COLUMN);
231       }
232       else
233       {
234          filters.put(SORT_COLUMN, column);
235       }
236 
237    }
238 
239    /***
240     * Returns an array of directions.
241     * 
242     * @return an Integer array of directions. null if no sorting information exists.
243     */
244    public Integer getSortingDirection()
245    {
246       String direction = getFilterParameterAsString(SORT_DIRECTION);
247       return (("asc".equals(direction) || "1".equals(direction)) ? ValueListInfo.ASCENDING : ValueListInfo.DESCENDING);
248    }
249 
250    public void setPrimarySortDirection(Integer direction)
251    {
252       if (direction == null)
253       {
254          filters.remove(SORT_DIRECTION);
255       }
256       else
257       {
258          filters.put(SORT_DIRECTION, ((direction.intValue() > 0) ? "asc" : "desc"));
259       }
260    }
261 
262    /***
263     * Getter for the curent page to display.
264     * 
265     * @return the curent page to display.
266     */
267    public int getPagingPage()
268    {
269       String page = getFilterParameterAsString(PAGING_PAGE);
270 
271       try
272       {
273          return (page == null || page.length() == 0) ? 1 : Integer.parseInt(page);
274       }
275       catch (NumberFormatException e)
276       {
277          return 1;
278       }
279    }
280 
281    /***
282     * Getter for the total number of pages.
283     * 
284     * @return the total number of pages.
285     */
286    public int getTotalNumberOfPages()
287    {
288       return (((totalNumberOfEntries - 1) / getPagingNumberPer()) + 1);
289    }
290 
291    /***
292     * Getter for the total number VOs.
293     * 
294     * @return the total number of VOs.
295     */
296    public int getTotalNumberOfEntries()
297    {
298       return totalNumberOfEntries;
299    }
300 
301    /***
302     * Getter for the number of VOs per page. Integer.MAX_VALUE if it is not set.
303     * 
304     * @return the number of VOs per page.
305     */
306    public int getPagingNumberPer()
307    {
308       String number = getFilterParameterAsString(PAGING_NUMBER_PER);
309 
310       try
311       {
312          int count = (number == null || number.length() == 0) ? Integer.MAX_VALUE : Integer.parseInt(number);
313          if (count > 0)
314          {
315             return count;
316          }
317          else
318          {
319             return Integer.MAX_VALUE;
320          }
321 
322       }
323       catch (NumberFormatException e)
324       {
325          return Integer.MAX_VALUE;
326       }
327    }
328 
329    /***
330     * Sets the total number of items that meet the filter.
331     * 
332     * @param totalNumberOfEntries
333     *           The total number of items that meet the filter.
334     */
335    public void setTotalNumberOfEntries(int totalNumberOfEntries)
336    {
337       this.totalNumberOfEntries = totalNumberOfEntries;
338    }
339 
340    /***
341     * The map to build the query.
342     * 
343     * @param filters
344     *           Map to build the query
345     */
346    public void setFilters(Map filters)
347    {
348       this.filters = filters;
349    }
350 
351    /***
352     * Sets the number of items per page.
353     * 
354     * @param numberPerPage
355     *           The number of line items per page.
356     */
357    public void setPagingNumberPer(int numberPerPage)
358    {
359       filters.put(PAGING_NUMBER_PER, String.valueOf(numberPerPage));
360    }
361 
362    /***
363     * Sets the current page number.
364     * 
365     * @param pageNumber
366     *           The current page number.
367     */
368    public void setPagingPage(int pageNumber)
369    {
370       filters.put(PAGING_PAGE, String.valueOf(pageNumber));
371    }
372 
373    /***
374     * @return Returns the focusValue.
375     */
376    public String getFocusValue()
377    {
378       return getFilterParameterAsString(FOCUS_VALUE);
379    }
380 
381    /***
382     * @param focusValue
383     *           The focusValue to set.
384     */
385    public void setFocusValue(String focusValue)
386    {
387       if (focusValue == null)
388       {
389          filters.remove(FOCUS_VALUE);
390       }
391       else
392       {
393          filters.put(FOCUS_VALUE, focusValue);
394       }
395    }
396 
397    /***
398     * @return Returns the focusProperty.
399     */
400    public String getFocusProperty()
401    {
402       return getFilterParameterAsString(FOCUS_PROPERTY);
403    }
404 
405    /***
406     * Set focusProperty, if null, remove FOCUS_PROPERTY AND FOCUS_VALUE
407     * 
408     * @param focusProperty
409     *           The focusProperty to set.
410     */
411    public void setFocusProperty(String focusProperty)
412    {
413       if ((focusProperty == null || focusProperty.length() == 0))
414       {
415          filters.remove(FOCUS_PROPERTY);
416          filters.remove(FOCUS_VALUE);
417       }
418       else
419       {
420          filters.put(FOCUS_PROPERTY, focusProperty);
421       }
422    }
423 
424    /***
425     * @return true if getFocusProperty is not null
426     */
427    public boolean isFocusEnabled()
428    {
429       return (getFocusProperty() != null);
430    }
431 
432    /***
433     * @return true if is set DoFocus true
434     */
435    public boolean isDoFocus()
436    {
437       String doFocus = getFilterParameterAsString(DO_FOCUS);
438       try
439       {
440          return (doFocus != null) && (doFocus.length() > 0) && Boolean.valueOf(doFocus).booleanValue();
441       }
442       catch (Exception e)
443       {
444          return false;
445       }
446    }
447 
448    /***
449     * Used for generating links, if any errors found, doFocus is set to false for next retrieving of the valueList.
450     * 
451     * @return boolean
452     */
453    public boolean isDoFocusAgain()
454    {
455       return isDoFocus() && (getFocusStatus() == FOCUS_FOUND);
456    }
457 
458    /***
459     * @see net.mlw.vlh.PagingInfo#setFocusSucces(boolean)
460     */
461    public void setDoFocus(boolean enabled)
462    {
463       filters.put(DO_FOCUS, String.valueOf(enabled));
464       focusedRowNumberInTable = -1;
465    }
466 
467    /***
468     * Set the certain row in table to be focused.
469     * 
470     * @param absolutPositionInResultSet
471     */
472    public void setFocusedRowNumberInTable(int absolutPositionInResultSet)
473    {
474       focusedRowNumberInTable = absolutPositionInResultSet % getPagingNumberPer();
475    }
476 
477    /***
478     * @return Returns the focusedRowNumberInTable.
479     */
480    public int getFocusedRowNumberInTable()
481    {
482       if (getFocusStatus() == FOCUS_FOUND)
483       {
484          return focusedRowNumberInTable;
485       }
486       else
487       {
488          return -1;
489       }
490    }
491 
492    /*** The resultSetRowNumber starts from 0. */
493    public void setPagingPageFromRowNumber(int resultSetRowNumber)
494    {
495       setPagingPage(1 + Math.round(resultSetRowNumber / getPagingNumberPer()));
496    }
497 
498    /***
499     * Acceptable values: FOUND, NOT_FOUND, TOO_MANY_ITEMS
500     */
501    public void setFocusStatus(byte status)
502    {
503       focusStatus = status;
504    }
505 
506    /***
507     * @return Returns the focusStatus.
508     */
509    public byte getFocusStatus()
510    {
511       return focusStatus;
512    }
513 
514    /***
515     * @see java.lang.Object#toString()
516     */
517    public String toString()
518    {
519       return "[filters='" + getFilters() + ", totalNumberOfEntries='" + totalNumberOfEntries + "', focusedRowNumberInTable='"
520             + focusedRowNumberInTable + "',focusStatus=" + focusStatus + "']";
521    }
522 
523    public void resetSorting()
524    {
525       List keys = new ArrayList(filters.keySet());
526       for (Iterator iter = keys.iterator(); iter.hasNext();)
527       {
528          String key = (String) iter.next();
529          if (key.startsWith(SORT_COLUMN) || key.startsWith(SORT_DIRECTION))
530          {
531             filters.remove(key);
532          }
533       }
534    }
535 
536    /***
537     * Extracts a value with the given key from filters and converts it to a String.
538     * If it isn't a String a warning is logged and null is returned.
539     * 
540     * @param key
541     * @return The value stored under the key in filters or null if not present or not a String.
542     */
543    protected String getFilterParameterAsString(String key)
544    {
545       Object parameter = filters.get(key);
546 
547       if (parameter != null)
548       {
549          if (parameter instanceof String)
550          {
551             return (String) parameter;
552          }
553          else
554          {
555             if (LOGGER.isWarnEnabled())
556             {
557                LOGGER.warn("Parameters contain the parameter '" + key + "' but it isn't String, as expected. It is a "
558                      + parameter.getClass() + " with the value " + parameter, new ClassCastException());
559             }
560          }
561       }
562       return null;
563    }
564 }