001: /* ListitemComparator.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Thu May 25 21:25:55 2006, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2006 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zul;
020:
021: import java.util.List;
022: import java.util.Comparator;
023:
024: /**
025: * A comparator used to compare {@link Listitem}, if not live data,
026: * or the data themselves, if live data.
027: *
028: * @author tomyeh
029: */
030: public class ListitemComparator implements Comparator {
031: /** The listheader (optinal). */
032: private final Listheader _header;
033: /** Column index. */
034: private int _index;
035: /** Ascending. */
036: private final boolean _asc;
037: /** Ignore case. */
038: private boolean _igcase;
039: /** Compares by value (instead of label) */
040: private boolean _byval;
041: /** Whether to treat null as the maximum value. */
042: private boolean _maxnull;
043:
044: /** Compares with {@link Listitem#getValue}.
045: *
046: * <p>It assumes the value returned by {@link Listitem#getValue}
047: * implements Comparable.
048: *
049: * <p>Note: It assumes the ascending order and case-insensitive.
050: * If not, use {@link #ListitemComparator(int, boolean, boolean)}
051: * instead.
052: */
053: public ListitemComparator() {
054: this (-1, true, true, false, false);
055: }
056:
057: /** Compares with the column of the specified index.
058: *
059: * <p>0 for the first column, 1 for the second and so on
060: *
061: * <p>Note: -1 for {@link Listitem#getValue} and it assumes
062: * the value implements Comparable.
063: *
064: * <p>Note: It assumes the ascending order, case-insensitive and
065: * comparing the returned values of {@link Listcell#getLabel}.
066: * If not, use {@link #ListitemComparator(int, boolean, boolean, boolean)}
067: * instead.
068: *
069: * <p>A null value is considered as the minimum value.
070: *
071: * @param index which column to compare. If -1, {@link Listitem#getValue}
072: * is used.
073: */
074: public ListitemComparator(int index) {
075: this (index, true, true, false, false);
076: }
077:
078: /** Compares with the column of the specified index.
079: *
080: * <p>0 for the first column, 1 for the second and so on
081: *
082: * <p>Note: -1 for {@link Listitem#getValue} and it assumes
083: * the value implements Comparable.
084: *
085: * <p>Note: it compares the returned value of {@link Listcell#getLabel}.
086: * If you want to compare {@link Listcell#getValue}.,
087: * use {@link #ListitemComparator(int, boolean, boolean, boolean)}
088: * instead.
089: *
090: * <p>A null value is considered as the minimum value.
091: *
092: * @param index which column to compare. If -1, {@link Listitem#getValue}
093: * is used.
094: * @param ascending whether to sort as ascending (or descending).
095: * @param ignoreCase whether to sort case-insensitive
096: */
097: public ListitemComparator(int index, boolean ascending,
098: boolean ignoreCase) {
099: this (index, ascending, ignoreCase, false, false);
100: }
101:
102: /** Compares with the column of the specified index.
103: *
104: * <p>0 for the first column, 1 for the second and so on
105: *
106: * <p>Note: -1 for {@link Listitem#getValue} and it assumes
107: * the value implements Comparable.
108: *
109: * <p>A null value is considered as the minimum value.
110: *
111: * @param index which column to compare. If -1, {@link Listitem#getValue}
112: * is used.
113: * @param ascending whether to sort as ascending (or descending).
114: * @param ignoreCase whether to sort case-insensitive
115: * @param byValue whether to compare {@link Listcell#getValue}.
116: * If false, it compares {@link Listcell#getLabel}.
117: * If true, it assumes the value returned by {@link Listcell#getValue}
118: * implements Comparable.
119: * It is ignored if the index is -1.
120: */
121: public ListitemComparator(int index, boolean ascending,
122: boolean ignoreCase, boolean byValue) {
123: this (index, ascending, ignoreCase, byValue, false);
124: }
125:
126: /** Compares with the column of the specified index.
127: *
128: * <p>0 for the first column, 1 for the second and so on
129: *
130: * <p>Note: -1 for {@link Listitem#getValue} and it assumes
131: * the value implements Comparable.
132: *
133: * @param index which column to compare. If -1, {@link Listitem#getValue}
134: * is used.
135: * @param ascending whether to sort as ascending (or descending).
136: * @param ignoreCase whether to sort case-insensitive
137: * @param byValue whether to compare {@link Listcell#getValue}.
138: * If false, it compares {@link Listcell#getLabel}.
139: * If true, it assumes the value returned by {@link Listcell#getValue}
140: * implements Comparable.
141: * It is ignored if the index is -1.
142: * @param nullAsMax whether to consider null as the maximum value.
143: * If false, null is considered as the minimum value.
144: */
145: public ListitemComparator(int index, boolean ascending,
146: boolean ignoreCase, boolean byValue, boolean nullAsMax) {
147: _header = null;
148: _index = index;
149: _asc = ascending;
150: _igcase = ignoreCase;
151: _byval = byValue;
152: _maxnull = nullAsMax;
153: }
154:
155: /** Compares with the column which the list header is at.
156: *
157: * <p>Note: it compares the returned value of {@link Listcell#getLabel}.
158: * If you want to compare {@link Listcell#getValue}.,
159: * use {@link #ListitemComparator(Listheader, boolean, boolean, boolean)}
160: * instead.
161: *
162: * <p>A null value is considered as the minimum value.
163: *
164: * @param ascending whether to sort as ascending (or descending).
165: * @param ignoreCase whether to sort case-insensitive
166: */
167: public ListitemComparator(Listheader header, boolean ascending,
168: boolean ignoreCase) {
169: this (header, ascending, ignoreCase, false, false);
170: }
171:
172: /** Compares with the column which the list header is at.
173: *
174: * <p>A null value is considered as the minimum value.
175: *
176: * @param ascending whether to sort as ascending (or descending).
177: * @param ignoreCase whether to sort case-insensitive
178: * @param byValue whether to compare {@link Listcell#getValue}.
179: * If false, it compares {@link Listcell#getLabel}.
180: */
181: public ListitemComparator(Listheader header, boolean ascending,
182: boolean ignoreCase, boolean byValue) {
183: this (header, ascending, ignoreCase, byValue, false);
184: }
185:
186: /** Compares with the column which the list header is at.
187: *
188: * @param ascending whether to sort as ascending (or descending).
189: * @param ignoreCase whether to sort case-insensitive
190: * @param byValue whether to compare {@link Listcell#getValue}.
191: * If false, it compares {@link Listcell#getLabel}.
192: * @param nullAsMax whether to consider null as the maximum value.
193: * If false, null is considered as the minimum value.
194: */
195: public ListitemComparator(Listheader header, boolean ascending,
196: boolean ignoreCase, boolean byValue, boolean nullAsMax) {
197: _header = header;
198: _index = -1; //not decided yet
199: _asc = ascending;
200: _igcase = ignoreCase;
201: _byval = byValue;
202: _maxnull = nullAsMax;
203: }
204:
205: /** Returns the listheader that this comparator is associated with, or null
206: * if not available.
207: */
208: public Listheader getListheader() {
209: return _header;
210: }
211:
212: /** Returns whether the order is ascending.
213: */
214: public boolean isAscending() {
215: return _asc;
216: }
217:
218: /** Returns whether to ignore case.
219: */
220: public boolean shallIgnoreCase() {
221: return _igcase;
222: }
223:
224: /** Returns whether to compare the returned value of {@link Listcell#getValue}
225: */
226: public boolean byValue() {
227: return _byval;
228: }
229:
230: //Comparator//
231: public int compare(Object o1, Object o2) {
232: final int index = _index < 0 && _header != null ? _header
233: .getColumnIndex() : _index;
234:
235: Object v1, v2;
236: if (o1 instanceof Listitem) { //not live data
237: final Listitem li1 = (Listitem) o1, li2 = (Listitem) o2;
238: if (index < 0) {
239: v1 = handleCase((Comparable) li1.getValue());
240: v2 = handleCase((Comparable) li2.getValue());
241: } else {
242: List lcs1 = li1.getChildren();
243: if (index >= lcs1.size())
244: v1 = null;
245: else {
246: final Listcell lc = (Listcell) lcs1.get(index);
247: v1 = handleCase(_byval ? lc.getValue() : lc
248: .getLabel());
249: }
250: List lcs2 = li2.getChildren();
251: if (index >= lcs2.size())
252: v2 = null;
253: else {
254: final Listcell lc = (Listcell) lcs2.get(index);
255: v2 = handleCase(_byval ? lc.getValue() : lc
256: .getLabel());
257: }
258: }
259: } else { //live data
260: v1 = handleCase(o1);
261: v2 = handleCase(o2);
262: }
263:
264: if (v1 == null)
265: return v2 == null ? 0 : _maxnull ? 1 : -1;
266: if (v2 == null)
267: return _maxnull ? -1 : 1;
268: final int v = ((Comparable) v1).compareTo(v2);
269: return _asc ? v : -v;
270: }
271:
272: private Object handleCase(Object c) {
273: if (_igcase) {
274: if (c instanceof String)
275: return ((String) c).toUpperCase();
276: if (c instanceof Character)
277: return new Character(Character
278: .toUpperCase(((Character) c).charValue()));
279: }
280: return c;
281: }
282:
283: public boolean equals(Object o) {
284: if (!(o instanceof ListitemComparator))
285: return false;
286: final ListitemComparator c = (ListitemComparator) o;
287: return c._index == _index && c._asc == _asc
288: && c._igcase == _igcase;
289: }
290:
291: public int hashCode() {
292: return _index ^ (_asc ? 1 : 5) ^ (_igcase ? 9 : 3);
293: }
294:
295: public String toString() {
296: return "[Comparator " + _index + "-th col, asc:" + _asc + ']';
297: }
298: }
|