1
2
3
4
5 package org.rcfaces.core.internal.tools;
6
7 import java.util.ArrayList;
8 import java.util.Comparator;
9 import java.util.Date;
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15
16 import javax.faces.FacesException;
17 import javax.faces.component.UIColumn;
18 import javax.faces.component.UIComponent;
19 import javax.faces.component.ValueHolder;
20 import javax.faces.context.FacesContext;
21 import javax.faces.event.FacesListener;
22 import javax.faces.model.DataModel;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.rcfaces.core.component.capability.ISortEventCapability;
27 import org.rcfaces.core.event.SortEvent;
28 import org.rcfaces.core.internal.capability.IGridComponent;
29 import org.rcfaces.core.internal.listener.IScriptListener;
30 import org.rcfaces.core.internal.listener.SortActionListener;
31 import org.rcfaces.core.model.IRangeDataModel;
32 import org.rcfaces.core.model.ISortedComponent;
33
34
35
36
37
38 public final class GridServerSort {
39 private static final String REVISION = "$Revision: 1.4.10.1 $";
40
41 private static final Log LOG = LogFactory.getLog(GridServerSort.class);
42
43 private static final Long LONG_0 = new Long(0l);
44
45 private static final Double DOUBLE_0 = new Double(0.0);
46
47 private static final Map SORT_ALIASES = new HashMap(8);
48
49 static {
50 SORT_ALIASES.put(ISortEventCapability.SORT_INTEGER, new SortLong());
51 SORT_ALIASES.put(ISortEventCapability.SORT_NUMBER, new SortDouble());
52 SORT_ALIASES.put(ISortEventCapability.SORT_ALPHA, new SortAlpha());
53 SORT_ALIASES.put(ISortEventCapability.SORT_ALPHA_IGNORE_CASE,
54 new SortAlphaIgnoreCase());
55 SORT_ALIASES.put(ISortEventCapability.SORT_TIME, new SortDate());
56 SORT_ALIASES.put(ISortEventCapability.SORT_DATE, new SortDate());
57 }
58
59 public static int[] computeSortedTranslation(FacesContext facesContext,
60 IGridComponent data, DataModel dataModel,
61 ISortedComponent sortedComponents[]) {
62
63 ISortMethod sortMethods[] = new ISortMethod[sortedComponents.length];
64
65 for (int i = 0; i < sortMethods.length; i++) {
66 UIColumn columnComponent = (UIColumn) sortedComponents[i]
67 .getComponent();
68
69 if ((columnComponent instanceof ISortEventCapability) == false) {
70 continue;
71 }
72
73 sortMethods[i] = getSortMethod(
74 (ISortEventCapability) columnComponent, data);
75 }
76
77 int rowCount = data.getRowCount();
78
79 List datas[] = new List[sortedComponents.length];
80 for (int i = 0; i < datas.length; i++) {
81 if (rowCount > 0) {
82 datas[i] = new ArrayList(rowCount);
83
84 } else {
85 datas[i] = new ArrayList();
86 }
87 }
88
89 if (dataModel instanceof IRangeDataModel) {
90
91 ((IRangeDataModel) dataModel).setRowRange(0, rowCount);
92 }
93
94 try {
95 for (int rowIndex = 0;; rowIndex++) {
96 data.setRowIndex(rowIndex);
97
98 if (data.isRowAvailable() == false) {
99 break;
100 }
101
102 Object rowData = null;
103 boolean rowDataInitialized = false;
104
105 for (int i = 0; i < datas.length; i++) {
106 UIComponent column = sortedComponents[i].getComponent();
107
108 Object value = null;
109
110 if (column instanceof ValueHolder) {
111 value = ValuesTools.getValue(column);
112 }
113
114 ISortMethod sortMethod = sortMethods[i];
115 value = sortMethod
116 .convertValue(facesContext, column, value);
117
118 if (value == null) {
119 if (rowDataInitialized == false) {
120 rowDataInitialized = true;
121
122 rowData = data.getRowData();
123 }
124
125
126 if (rowData instanceof Comparable) {
127 value = rowData;
128 }
129 }
130
131 datas[i].add(value);
132 }
133 }
134 } finally {
135 data.setRowIndex(-1);
136 }
137
138 int translations[] = new int[datas[0].size()];
139 for (int i = 0; i < translations.length; i++) {
140 translations[i] = i;
141 }
142 if (translations.length < 2) {
143 return translations;
144 }
145
146 Object ds[][] = new Object[datas.length][];
147 Comparator comparators[] = new Comparator[datas.length];
148 boolean sortOrders[] = new boolean[datas.length];
149 for (int i = 0; i < ds.length; i++) {
150 ds[i] = datas[i].toArray();
151
152 ISortMethod sortMethod = sortMethods[i];
153 if (sortMethod == null) {
154 throw new FacesException("No sort method #" + i + " for grid '"
155 + ((UIComponent) data).getId() + "' of view '"
156 + facesContext.getViewRoot().getViewId() + "'");
157 }
158
159 comparators[i] = sortMethod.getComparator();
160 sortOrders[i] = sortedComponents[i].isAscending();
161 }
162
163 for (int i = 0; i < translations.length; i++) {
164
165 next_element: for (int j = i; j > 0; j--) {
166 int j0 = translations[j - 1];
167 int j1 = translations[j];
168
169 for (int k = 0; k < sortMethods.length; k++) {
170 Object o1 = ds[k][j0];
171 Object o2 = ds[k][j1];
172
173 if (comparators[k] == null) {
174 continue;
175 }
176
177 int order = comparators[k].compare(o1, o2);
178 if (order == 0) {
179 continue;
180 }
181
182 if (sortOrders[k]) {
183 if (order < 0) {
184 break next_element;
185 }
186 } else if (order > 0) {
187 break next_element;
188 }
189
190 translations[j] = j0;
191 translations[j - 1] = j1;
192 continue next_element;
193 }
194 }
195 }
196
197 if (LOG.isDebugEnabled()) {
198 Set set2 = new HashSet(translations.length);
199 LOG.debug("Valid SORT translation ...");
200 for (int i = 0; i < translations.length; i++) {
201 if (set2.add(new Integer(translations[i])) == false) {
202
203 LOG.debug("*** INVALID TRANSLATION ***");
204 continue;
205 }
206 }
207 }
208
209 return translations;
210 }
211
212 private static ISortMethod getSortMethod(
213 ISortEventCapability columnComponent, IGridComponent gridComponent) {
214
215 FacesListener facesListeners[] = columnComponent.listSortListeners();
216
217 for (int j = 0; j < facesListeners.length; j++) {
218 FacesListener facesListener = facesListeners[j];
219
220
221
222 if (facesListener instanceof SortActionListener) {
223 return new SortAction((SortActionListener) facesListener,
224 (UIComponent) columnComponent, gridComponent);
225 }
226
227 if ((facesListener instanceof IScriptListener) == false) {
228 continue;
229 }
230
231 IScriptListener scriptListener = (IScriptListener) facesListener;
232
233 ISortMethod sortMethod = (ISortMethod) SORT_ALIASES
234 .get(scriptListener.getCommand());
235 if (sortMethod == null) {
236 continue;
237 }
238
239 return sortMethod;
240 }
241
242 return null;
243 }
244
245
246
247
248
249
250 private interface ISortMethod {
251
252 Comparator getComparator();
253
254 Object convertValue(FacesContext facesContext, UIComponent component,
255 Object value);
256
257 }
258
259
260
261
262
263
264 private static abstract class AbstractSortMethod implements ISortMethod,
265 Comparator {
266 private static final String REVISION = "$Revision: 1.4.10.1 $";
267
268 public Comparator getComparator() {
269 return this;
270 }
271
272 public int compare(Object o1, Object o2) {
273 if (o1 == null) {
274 return (o2 == null) ? 0 : -1;
275
276 } else if (o2 == null) {
277 return 1;
278 }
279
280 return ((Comparable) o1).compareTo(o2);
281 }
282 }
283
284
285
286
287
288
289 private static class SortLong extends AbstractSortMethod {
290
291 private static final String REVISION = "$Revision: 1.4.10.1 $";
292
293 public Object convertValue(FacesContext facesContext,
294 UIComponent component, Object value) {
295 if (value == null) {
296 return LONG_0;
297 }
298
299 if (value instanceof Number) {
300 return value;
301 }
302
303 if (value instanceof String) {
304 String s = (String) value;
305 if (s.length() < 1) {
306 return LONG_0;
307 }
308
309 long l = Long.parseLong(s);
310 if (l == 0l) {
311 return LONG_0;
312 }
313
314 return new Long(l);
315 }
316
317 return LONG_0;
318 }
319 }
320
321
322
323
324
325
326 private static class SortDouble extends AbstractSortMethod {
327 private static final String REVISION = "$Revision: 1.4.10.1 $";
328
329 public Object convertValue(FacesContext facesContext,
330 UIComponent component, Object value) {
331 if (value == null) {
332 return DOUBLE_0;
333 }
334
335 if (value instanceof Number) {
336 return value;
337 }
338
339 if (value instanceof String) {
340 String s = (String) value;
341 if (s.length() < 1) {
342 return DOUBLE_0;
343 }
344
345 double d = Double.parseDouble(s);
346 if (d == 0.0) {
347 return DOUBLE_0;
348 }
349
350 return new Double(d);
351 }
352
353 return DOUBLE_0;
354 }
355 }
356
357
358
359
360
361
362 private static class SortAlpha extends AbstractSortMethod {
363 private static final String REVISION = "$Revision: 1.4.10.1 $";
364
365 public Object convertValue(FacesContext facesContext,
366 UIComponent component, Object value) {
367 if (value == null) {
368 return "";
369 }
370
371 if (value instanceof String) {
372 return value;
373 }
374
375 value = ValuesTools.valueToString(value, component, facesContext);
376
377 if (value == null) {
378 return "";
379 }
380
381 return value;
382 }
383 }
384
385
386
387
388
389
390 private static class SortAlphaIgnoreCase extends AbstractSortMethod {
391 private static final String REVISION = "$Revision: 1.4.10.1 $";
392
393 public Object convertValue(FacesContext facesContext,
394 UIComponent component, Object value) {
395 if (value == null) {
396 return "";
397 }
398
399 if (value instanceof String) {
400 return ((String) value).toLowerCase();
401 }
402
403 value = ValuesTools.valueToString(value, component, facesContext);
404 if (value == null) {
405 return "";
406 }
407
408 return ((String) value).toLowerCase();
409 }
410 }
411
412
413
414
415
416
417 private static class SortDate extends AbstractSortMethod {
418 private static final String REVISION = "$Revision: 1.4.10.1 $";
419
420 public Object convertValue(FacesContext facesContext,
421 UIComponent component, Object value) {
422 if (value == null) {
423 return null;
424 }
425
426 if (value instanceof Date) {
427 return value;
428 }
429
430 throw new FacesException(
431 "Invalid Date for \"date\" sort method ! (class="
432 + value.getClass() + " object=" + value + ")");
433 }
434 }
435
436
437
438
439
440
441 private static class SortAction extends AbstractSortMethod {
442 private static final String REVISION = "$Revision: 1.4.10.1 $";
443
444 private final Comparator comparator;
445
446 private final SortEvent.ISortConverter converter;
447
448 public SortAction(SortActionListener listener,
449 UIComponent dataColumnComponent, IGridComponent dataModel) {
450 SortEvent sortEvent = new SortEvent(dataColumnComponent, dataModel);
451
452 listener.processSort(sortEvent);
453
454 comparator = sortEvent.getSortComparator();
455 if (comparator == null) {
456 throw new FacesException("Comparator of sortEvent is NULL !");
457 }
458
459 converter = sortEvent.getSortConverter();
460 }
461
462 public Object convertValue(FacesContext facesContext,
463 UIComponent component, Object value) {
464 if (converter == null) {
465 return value;
466 }
467
468 return converter.convertValue(facesContext, component, value);
469 }
470
471 public Comparator getComparator() {
472 return comparator;
473 }
474 }
475 }