KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fr > improve > struts > taglib > layout > sort > SortUtil


1 package fr.improve.struts.taglib.layout.sort;
2
3 import java.io.Serializable JavaDoc;
4 import java.util.ArrayList JavaDoc;
5 import java.util.Collections JavaDoc;
6 import java.util.Enumeration JavaDoc;
7 import java.util.HashMap JavaDoc;
8 import java.util.Iterator JavaDoc;
9 import java.util.List JavaDoc;
10 import java.util.Locale JavaDoc;
11 import java.util.Map JavaDoc;
12 import java.util.MissingResourceException JavaDoc;
13 import java.util.Vector JavaDoc;
14
15 import javax.servlet.http.HttpServletRequest JavaDoc;
16 import javax.servlet.jsp.tagext.Tag JavaDoc;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.apache.struts.Globals;
21 import org.apache.struts.util.RequestUtils;
22
23 import fr.improve.struts.taglib.layout.datagrid.DatagridTag;
24 import fr.improve.struts.taglib.layout.field.AbstractLayoutFieldTag;
25 import fr.improve.struts.taglib.layout.field.DateFieldTag;
26 import fr.improve.struts.taglib.layout.pager.PagerTag;
27 import fr.improve.struts.taglib.layout.skin.Skin;
28 import fr.improve.struts.taglib.layout.tab.TabTag;
29 import fr.improve.struts.taglib.layout.util.LayoutUtils;
30 import fr.improve.struts.taglib.layout.util.ParentFinder;
31 /**
32  * Insert the type's description here.
33  * Creation date: (27/10/2001 13:05:22)
34  *
35  * PENDING: does not work with action chaining.
36  *
37  * @author: Jean-Noel Ribette
38  */

39 public class SortUtil implements Serializable JavaDoc {
40     /**
41      * Log
42      */

43     private static final Log LOG = LogFactory.getLog(SortUtil.class);
44
45     /**
46      * Implementation class for SortUtil
47      */

48     public static final String JavaDoc SORT_UTIL_CLASS = "sortutil.class";
49     
50     /**
51      * Name of this object in the session.
52      */

53     public static final String JavaDoc SORTUTIL_KEY =
54         "fr.improve.struts.taglib.layout.sort.SortUtil";
55
56     /**
57      * Name of the parameter containing the number of the collection to sort.
58      */

59     public static final String JavaDoc SORTUTIL_COLLECTION = "layoutCollection";
60
61     /**
62      * Name of the parameter containing the property to sort the collection by.
63      */

64     public static final String JavaDoc SORTUTIL_PROPERTY = "layoutCollectionProperty";
65     
66     /**
67      * Name of the sort action property.
68      */

69     public static final String JavaDoc SORT_UTIL_ACTION = "sortutil.action";
70
71     /**
72      * Vector of the collections
73      */

74     protected Vector JavaDoc collections = new Vector JavaDoc();
75     
76     /**
77      * Sorted state for a collection.
78      */

79     protected Map JavaDoc sortState = new HashMap JavaDoc();
80
81     /**
82      * Old request attributes.
83      */

84     protected Map JavaDoc attributes = new HashMap JavaDoc();
85
86     /**
87      * Old request parameters.
88      */

89     protected Map JavaDoc parameters = new HashMap JavaDoc();
90
91     /**
92      * Original url.
93      */

94     protected String JavaDoc url;
95
96     /**
97      * index when displaying the sorted collection.
98      */

99     protected int index = 0;
100     
101     /**
102      * Sort rules.
103      */

104     protected SortRules sortRules;
105
106     protected int hashCode;
107     
108     /**
109      * Return the sort state of the current collection for the specified property.
110      * 0 : no sort for this property
111      * 1 : sort ascending for this property
112      * -1 : sort descending for this property
113      */

114     public static short getSortState(HttpServletRequest JavaDoc in_request, String JavaDoc in_property) {
115         SortUtil lc_util = (SortUtil) in_request.getAttribute(SORTUTIL_KEY);
116         if (lc_util==null || lc_util.sortState.isEmpty()) {
117             return 0;
118         } else {
119             Object JavaDoc[] lc_sort = (Object JavaDoc[]) lc_util.sortState.values().iterator().next();
120             if (in_property.equals(lc_sort[0])) {
121                 return ((Integer JavaDoc)lc_sort[1]).shortValue();
122             } else {
123                 return 0;
124             }
125         }
126     }
127
128 public void initSortUtil(HttpServletRequest JavaDoc in_request, String JavaDoc in_url) {
129     
130     // Copy the parameters.
131
// (only if it is not already in the url)
132
Enumeration JavaDoc lc_enumeration = in_request.getParameterNames();
133     boolean hasUrlParameter = in_url.indexOf('?')!=-1;
134     parameters.clear();
135     while (lc_enumeration.hasMoreElements()) {
136         String JavaDoc lc_key = (String JavaDoc) lc_enumeration.nextElement();
137         if (!hasUrlParameter || in_url.indexOf(lc_key + "=") ==-1) {
138             parameters.put(lc_key, in_request.getParameter(lc_key));
139         }
140     }
141     
142     // Copy the attributes.
143
lc_enumeration = in_request.getAttributeNames();
144     attributes.clear();
145     while (lc_enumeration.hasMoreElements()) {
146         Object JavaDoc lc_key = lc_enumeration.nextElement();
147         Object JavaDoc lc_value = in_request.getAttribute(lc_key.toString());
148         if (lc_value instanceof Tag JavaDoc) {
149             // Tags are not useful here, and are not serializable
150
LOG.debug("Skipping JSP tag " + lc_key + " : " + lc_value);
151             continue;
152         }
153         if (ParentFinder.TAGS_KEY.equals(lc_key)) {
154             // The tag stack is not useful here.
155
LOG.debug("Skipping JSP tags stack");
156             continue;
157         }
158         if (DateFieldTag.CALENDAR_KEY.equals(lc_key)) {
159             // The javascript calendar code must be added each time.
160
LOG.debug("Skipping calendar code");
161             continue;
162         }
163         if (DatagridTag.LOADED.equals(lc_key)) {
164             // The javascript datagrid code must be added each time.
165
LOG.debug("Skipping datagrid code");
166             continue;
167         }
168         
169         if (AbstractLayoutFieldTag.FIRST_ERROR_FIELD_FOCUS.equals(lc_key)) {
170             LOG.debug("Skipping first field in error focus");
171             continue;
172         }
173         
174         if (((String JavaDoc)lc_key).startsWith("javax.servlet")) {
175             // Skip servlet information.
176
LOG.debug("Skipping servlet information " + lc_key);
177             continue;
178         }
179         
180         if (((String JavaDoc)lc_key).startsWith("atg.servlet")) {
181             // Skip Dynamo information.
182
LOG.debug("Skipping dynamo information " + lc_key);
183             continue;
184         }
185         
186         if (((String JavaDoc)lc_key).startsWith("_")) {
187             if (lc_value!=null && lc_value.getClass().getName().indexOf("atg.")!=-1) {
188                 // Skip Dynamo information.
189
LOG.debug("Skipping unsafe atg data " + lc_key);
190                 continue;
191             }
192         }
193         
194         if (((String JavaDoc)lc_key).equals(Globals.ERROR_KEY) && !LayoutUtils.getSkin(in_request.getSession()).getSortKeepErrorMessage()) {
195             // Skip error message, for example if they are only displayed once in a popup.
196
LOG.debug("Skipping Struts error messages " + lc_key);
197             continue;
198         }
199         
200         if (((String JavaDoc)lc_key).startsWith(TabTag.ATG_FIX_KEY)) {
201             // Skip ATG Dynamo cookie bug fix.
202
LOG.debug("Skipping dynamo tabs cookie bug fix");
203             continue;
204         }
205         
206         LOG.debug("Adding " + lc_key + " : " + lc_value);
207         attributes.put(lc_key, lc_value);
208     }
209
210     // Save the url.
211
url = in_url;
212     
213     // Copy the sort state.
214
//SortUtil oldSort = (SortUtil) in_request.getAttribute(SORTUTIL_KEY);
215
//if (oldSort!=null) {
216
// sortState = oldSort.sortState;
217
//}
218
}
219
220 public static void addCollection(
221     Object JavaDoc in_list,
222     HttpServletRequest JavaDoc in_request) {
223
224     // Get a sort util.
225
SortUtil lc_sortUtil =
226         (SortUtil) in_request.getSession().getAttribute(SORTUTIL_KEY);
227     if (lc_sortUtil==null || in_request.getAttribute(SORTUTIL_KEY + "aaa")==null) {
228         lc_sortUtil = createSortUtil(in_request);
229         in_request.getSession().setAttribute(SORTUTIL_KEY, lc_sortUtil);
230         in_request.setAttribute(SORTUTIL_KEY + "aaa", "aaa");
231     }
232     lc_sortUtil.collections.add(in_list);
233 }
234 /**
235  * Put all the saved attributes back in the request.
236  */

237 protected void buildRequest(HttpServletRequest JavaDoc in_request) {
238     Iterator JavaDoc lc_iterator = attributes.keySet().iterator();
239     while (lc_iterator.hasNext()) {
240         Object JavaDoc lc_key = lc_iterator.next();
241         in_request.setAttribute(lc_key.toString(), attributes.get(lc_key));
242     }
243 }
244
245 /**
246  * Fix the current page for the pager.
247  */

248 protected void setCurrentPage(HttpServletRequest JavaDoc in_request) {
249     String JavaDoc lc_name = in_request.getParameter(PagerTag.PAGER_SESSION_KEY);
250     String JavaDoc lc_value = in_request.getParameter(PagerTag.PAGE_NUMBER_KEY);
251     if (lc_name!=null && lc_value!=null && in_request.getSession().getAttribute(lc_name)!=null) {
252         in_request.getSession().setAttribute(lc_name, lc_value);
253     }
254 }
255
256
257 /**
258  * Put all the saved parameters back in the request.
259  */

260 protected String JavaDoc buildURL(HttpServletRequest JavaDoc in_request) {
261     Iterator JavaDoc lc_iterator = parameters.keySet().iterator();
262     StringBuffer JavaDoc lc_url = new StringBuffer JavaDoc(url);
263     boolean hasParameter = url.indexOf('?')!=-1;
264     while (lc_iterator.hasNext()) {
265         Object JavaDoc lc_key = lc_iterator.next();
266         if (!PagerTag.PAGE_NUMBER_KEY.equals(lc_key)) {
267         if (hasParameter) {
268             lc_url.append("&");
269         } else {
270             lc_url.append("?");
271             hasParameter = true;
272         }
273         lc_url.append(LayoutUtils.encodeURL(lc_key.toString()));
274         lc_url.append("=");
275     
276         Object JavaDoc lc_param = parameters.get(lc_key);
277         if (lc_param!=null) {
278             lc_url.append(LayoutUtils.encodeURL(lc_param.toString()));
279         }
280         }
281     }
282     return lc_url.toString();
283 }
284 protected List JavaDoc getCollectionToSort(HttpServletRequest JavaDoc in_request) throws SortException {
285     String JavaDoc lc_indexAsString = in_request.getParameter(SORTUTIL_COLLECTION);
286     int lc_index;
287     try {
288         lc_index = Integer.parseInt(lc_indexAsString);
289     } catch (NumberFormatException JavaDoc e) {
290         throw new SortException("Impossible to find the collection to sort");
291     }
292     List JavaDoc lc_list = null;
293     if (lc_index>=0) {
294         try {
295             lc_list = (List JavaDoc) collections.get(lc_index);
296         } catch (ClassCastException JavaDoc e) {
297             throw new SortException("Impossible to sort a bean of type " + collections.get(lc_index).getClass());
298         }
299     }
300     return lc_list;
301 }
302 protected String JavaDoc getPropertyToSort(HttpServletRequest JavaDoc in_request) throws SortException {
303     return in_request.getParameter(SORTUTIL_PROPERTY);
304 }
305     public List JavaDoc getSortedCollection() {
306         List JavaDoc lc_list = (List JavaDoc) collections.get(index);
307         index++;
308         return lc_list;
309     }
310 /**
311  * Method called by the collection tag.
312  */

313 public static String JavaDoc getURLForCollection(
314     String JavaDoc in_property,
315     HttpServletRequest JavaDoc in_request) {
316
317     // Get a sort util.
318
SortUtil lc_sortUtil = (SortUtil) in_request.getSession().getAttribute(SORTUTIL_KEY);
319     if (lc_sortUtil==null || in_request.getAttribute(SORTUTIL_KEY + "aaa")==null) {
320         lc_sortUtil = createSortUtil(in_request);
321         in_request.getSession().setAttribute(SORTUTIL_KEY, lc_sortUtil);
322         in_request.setAttribute(SORTUTIL_KEY + "aaa", "aaa");
323     }
324
325     // Get the sort action.
326
String JavaDoc lc_action = null;
327     try {
328         lc_action = LayoutUtils.getSkin(in_request.getSession()).getProperty(SORT_UTIL_ACTION);
329     } catch (MissingResourceException JavaDoc e) {
330         lc_action = "sort.do";
331     }
332     
333     // Returns the url.
334
StringBuffer JavaDoc lc_buffer = new StringBuffer JavaDoc(in_request.getContextPath());
335     lc_buffer.append("/");
336     lc_buffer.append(lc_action);
337     lc_buffer.append("?");
338     lc_buffer.append(SORTUTIL_COLLECTION);
339     lc_buffer.append('=');
340     lc_buffer.append(lc_sortUtil.collections.size()-1);
341     lc_buffer.append("&");
342     lc_buffer.append(SORTUTIL_PROPERTY);
343     lc_buffer.append('=');
344     lc_buffer.append(in_property);
345     lc_buffer.append("&");
346     lc_buffer.append("layoutCollectionState");
347     lc_buffer.append('=');
348     lc_buffer.append(getRequestState(in_request));
349     return lc_buffer.toString();
350 }
351 public String JavaDoc sort(HttpServletRequest JavaDoc in_request) throws SortException {
352     // Check if we are in a legal state.
353
validateRequest(in_request);
354     
355     // Get the collection to sort.
356
List JavaDoc lc_collection = getCollectionToSort(in_request);
357
358     // Get the property to sort the collection by.
359
String JavaDoc lc_property = getPropertyToSort(in_request);
360
361     // Sort the collection.
362
sortCollection(lc_collection, lc_property);
363     
364     // Build the request.
365
buildRequest(in_request);
366     
367     // Deal with pagination issue.
368
setCurrentPage(in_request);
369
370     // Remove the sort util from the session, and put it in the request.
371
in_request.getSession().removeAttribute(SORTUTIL_KEY);
372     in_request.setAttribute(SORTUTIL_KEY, this);
373     
374     // Update the sort collection state.
375

376     return buildURL(in_request);
377 }
378 protected void sortCollection(List JavaDoc in_collection, String JavaDoc in_property) {
379     // If property is valid, sort according to this property.
380
if (in_property!=null && in_property.length()!=0) {
381         
382         // Create a copy of the collection. This allows to determine the sort order.
383
List JavaDoc copy = new ArrayList JavaDoc(in_collection);
384         
385         // Sort the collection.
386
Collections.sort(in_collection, new BeanComparator(in_property, sortRules));
387         int order = 1; // default order is 1, ascending.
388

389         
390         if (copy.equals(in_collection)) {
391             // The list was already sorted in this order, reverse the order.
392
Collections.reverse(in_collection);
393             order = -1;
394         }
395         
396         // Update the sort order state.
397
int index = collections.indexOf(in_collection);
398         sortState.put(new Integer JavaDoc(index), new Object JavaDoc[]{in_property, new Integer JavaDoc(order)});
399     }
400 }
401
402
403 /**
404  * Get the session state to generate a valid sort request.
405  */

406 private static final String JavaDoc getRequestState(HttpServletRequest JavaDoc in_request) {
407     Integer JavaDoc lc_value = (Integer JavaDoc) in_request.getSession().getAttribute(SORTUTIL_KEY + "bbb");
408     if (lc_value==null) {
409         lc_value = new Integer JavaDoc(0);
410         in_request.getSession().setAttribute(SORTUTIL_KEY + "bbb", lc_value);
411     }
412     return lc_value.toString();
413 }
414
415 /**
416  * Throws an exception if it is illegal to sort a collection.
417  * This is the case if the back button is used.
418  */

419 protected final void validateRequest(HttpServletRequest JavaDoc in_request) throws SortException {
420     // Get the session value.
421
Integer JavaDoc lc_integer = (Integer JavaDoc) in_request.getSession().getAttribute(SORTUTIL_KEY + "bbb");
422     if (lc_integer == null) {
423         throw new SortException("session state unknown");
424     }
425     
426     // Get the request value.
427
String JavaDoc lc_value = in_request.getParameter("layoutCollectionState");
428     if (lc_value == null) {
429         throw new SortException("bad request");
430     }
431     
432     // If the session value is greater than the request value, throw an exception.
433
// Unless the skin is configured to not check the state.
434
Skin lc_skin = LayoutUtils.getSkin(in_request.getSession());
435     Integer JavaDoc lc_integerValue = new Integer JavaDoc(lc_value);
436     
437     if (lc_skin.isSortTokenRequired() && lc_integer.compareTo(lc_integerValue)>0) {
438         throw new SortException("bad session state");
439     }
440     
441     // Ok, update the session state.
442
in_request.getSession().setAttribute(SORTUTIL_KEY + "bbb", new Integer JavaDoc(lc_integer.intValue()+1));
443 }
444
445 /**
446  * Build a new sort util.
447  * PENDING: problems with array of parameters and include that will give bad url.
448  */

449 public static SortUtil createSortUtil(HttpServletRequest JavaDoc in_request) {
450     
451     SortUtil lc_sortUtil;
452     try {
453         // Get SortUtil class from Skin configuration.
454
String JavaDoc lc_sortUtilClass = LayoutUtils.getSkin(in_request.getSession()).getProperty(SORT_UTIL_CLASS);
455         try {
456             // Instanciate SortUtil.
457
lc_sortUtil = (SortUtil) RequestUtils.applicationInstance(lc_sortUtilClass);
458         } catch (Exception JavaDoc e) {
459             e.printStackTrace();
460             lc_sortUtil = new SortUtil();
461         }
462     } catch (MissingResourceException JavaDoc mre) {
463         lc_sortUtil = new SortUtil();
464     }
465     
466     // Set SortUtil String comparator.
467
lc_sortUtil.sortRules = getRules(in_request);
468     
469     // Initialize SortUtil
470
lc_sortUtil.initSortUtil(in_request, in_request.getServletPath());
471     return lc_sortUtil;
472 }
473
474     /**
475      * Get String sorting rules.
476      */

477     private static SortRules getRules(HttpServletRequest JavaDoc in_request) {
478         Locale JavaDoc locale = LayoutUtils.getLocale(in_request);
479         return LayoutUtils.getSkin(in_request.getSession()).getSortRules(locale);
480     }
481
482 }
483
Popular Tags