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
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
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 }