001: package org.swingml.treetablebrowser.ext;
002:
003: import java.util.*;
004:
005: import org.swingml.system.*;
006: import org.swingml.util.*;
007:
008: /**
009: * @author dpitt
010: */
011: public class TableSort {
012:
013: public int columnToSort = -1;
014: TreeTableBrowserModel model = null;
015: BitSet sortDirection = new BitSet(3); // 0 == ascending 1== descending
016: ArrayList sortOrder = new ArrayList();
017: Object[][] subject = null;
018:
019: public void addColumn(int col) {
020: addColumn(new Integer(col));
021: }
022:
023: public void addColumn(Integer col) {
024: sortOrder.add(col);
025: }
026:
027: public void calculateSortFromModel(TreeTableBrowserModel ttbm) {
028: List columns = ttbm.getTreeTableColumns();
029: Map columnsWithSort = new HashMap();
030: for (int columnIndex = 0; columnIndex < columns.size(); columnIndex++) {
031: TreeTableBrowserColumnModel column = (TreeTableBrowserColumnModel) columns
032: .get(columnIndex);
033: if (column.getSortOrder() > 0) {
034: columnsWithSort.put(new Integer(column.getSortOrder()),
035: column);
036: }
037: removeColumn(columnIndex);
038: }
039: for (int sortIndex = 1; sortIndex <= columns.size(); sortIndex++) {
040: TreeTableBrowserColumnModel column = (TreeTableBrowserColumnModel) columnsWithSort
041: .get(new Integer(sortIndex));
042: if (column != null) {
043: int originalIndex = columns.indexOf(column);
044: this .addColumn(originalIndex);
045: if (column.getSortDirection() == 1) {
046: this .setSortDirection(originalIndex);
047: }
048: }
049: }
050: }
051:
052: protected int compare(String keyValue, String pivotValue,
053: Object type) {
054: int result = 0;
055: if (type instanceof String || type == null) {
056: return keyValue.compareToIgnoreCase(pivotValue);
057: } else if (type instanceof DateConverter) {
058: DateConverter converter = (DateConverter) type;
059: try {
060: result = converter.compare(keyValue, pivotValue);
061: return result;
062: } catch (java.text.ParseException e) {
063: SwingMLLogger.getInstance().log(
064: "Error trying to convert dates for sorting "
065: + e);
066: }
067: } else if (type instanceof NumberConverter) {
068: NumberConverter converter = (NumberConverter) type;
069: result = converter.compare(keyValue, pivotValue);
070: }
071: return result;
072: }
073:
074: public boolean direction(int col) {
075: return sortDirection.get(col);
076: }
077:
078: /**
079: * Returns the model.
080: *
081: * @return TreeTableModel
082: */
083: public TreeTableBrowserModel getModel() {
084: return model;
085: }
086:
087: protected String getPivotValue(Object obj) {
088: String result = obj.toString();
089: if (obj instanceof TreeTableBrowserDataModel) {
090: TreeTableBrowserDataModel dm = (TreeTableBrowserDataModel) obj;
091: if (dm.getDisplayValue() != null) {
092: result = dm.getText();
093: }
094: }
095: return result;
096: }
097:
098: /**
099: * Returns the sortOrder.
100: *
101: * @return ArrayList
102: */
103: public ArrayList getSortOrder() {
104: return sortOrder;
105: }
106:
107: /**
108: * Returns the subject.
109: *
110: * @return Object[][]
111: */
112: public Object[][] getSubject() {
113: return subject;
114: }
115:
116: public boolean isSortColumn(int col) {
117: Iterator itr = sortOrder.iterator();
118: while (itr.hasNext()) {
119: Integer i = (Integer) itr.next();
120: if (i.intValue() == col) {
121: return true;
122: }
123: }
124: return false;
125: }
126:
127: public void removeColumn(int col) {
128: removeColumn(new Integer(col));
129: }
130:
131: public void removeColumn(Integer col) {
132: for (int i = 0; i < sortOrder.size(); i++) {
133: Integer value = (Integer) sortOrder.get(i);
134: if (value.intValue() == col.intValue()) {
135: sortOrder.remove(i);
136: }
137: }
138: if (sortOrder.isEmpty()) {
139: columnToSort = -1;
140: }
141: }
142:
143: /**
144: * Sets the model.
145: *
146: * @param model
147: * The model to set
148: */
149: public void setModel(TreeTableBrowserModel model) {
150: this .model = model;
151: }
152:
153: /**
154: * Sets the sortDirection.
155: *
156: * @param sortDirection
157: * The sortDirection to set
158: */
159: public void setSortDirection(int col) {
160: if (sortDirection.get(col)) {
161: sortDirection.clear(col);
162: } else {
163: sortDirection.set(col);
164: }
165: }
166:
167: /**
168: * Sets the sortOrder.
169: *
170: * @param sortOrder
171: * The sortOrder to set
172: */
173: public void setSortOrder(ArrayList sortOrder) {
174: this .sortOrder = sortOrder;
175: }
176:
177: /**
178: * Sets the subject.
179: *
180: * @param subject
181: * The subject to set
182: */
183: public void setSubject(Object[][] subject) {
184: this .subject = subject;
185: }
186:
187: public void sort(Object[][] o) {
188: setSubject(o);
189: columnToSort = 0;
190: if (sortOrder.isEmpty()) {
191: return;
192: }
193: Object[] array = getSortOrder().toArray();
194: int size = array.length;
195: for (int s = 1; s <= size; s++) {
196: columnToSort = ((Integer) array[size - s]).intValue();
197: int[] keys = null;
198: if (sortDirection.get(columnToSort)) {
199: // sort ascending
200: keys = sortDescending();
201: } else {
202: keys = sortAsscending();
203: }
204: if (keys == null) {
205: return;
206: }
207: int length = keys.length;
208: int width = subject[0].length;
209: Object[][] temp = new Object[length][width];
210: for (int i = 0; i < length; i++) {
211: for (int j = 0; j < width; j++) {
212: temp[i][j] = subject[keys[i]][j];
213: }
214: }
215: subject = temp;
216: }
217: }
218:
219: public int[] sortAsscending() {
220: int[] returnValue = sortAsscending(columnToSort);
221: return returnValue;
222: }
223:
224: private int[] sortAsscending(int column) {
225: int length = subject.length;
226: // initialize key list
227: ArrayList keys = new ArrayList();
228: for (int i = 0; i < length; i++) {
229: keys.add(new Integer(i));
230: }
231: int[] sortedKeys = sortKeys(keys, column, sortType(column));
232: return sortedKeys;
233: }
234:
235: public int[] sortDescending() {
236: int[] returnValue = sortDescending(columnToSort);
237: return returnValue;
238: }
239:
240: private int[] sortDescending(int column) {
241: int[] asscendingIndices = sortAsscending(column);
242: if (asscendingIndices == null) {
243: return null;
244: }
245: int length = asscendingIndices.length;
246: int[] descendingIndices = new int[length];
247: int lengthMinusOne = length - 1;
248: for (int i = 0; i < length; i++) {
249: descendingIndices[i] = asscendingIndices[lengthMinusOne - i];
250: }
251: return descendingIndices;
252: }
253:
254: public int[] sortKeys(ArrayList keys, int column, Object type) {
255: if (keys.size() == 0) {
256: return null;
257: }
258: if (keys.size() == 1) {
259: int[] loneKeyArray = new int[1];
260: loneKeyArray[0] = ((Integer) keys.get(0)).intValue();
261: return loneKeyArray;
262: }
263: int pivotKey = ((Integer) keys.get(0)).intValue();
264: String pivotValue = getPivotValue(subject[pivotKey][column]);
265: ArrayList lessThanList = new ArrayList();
266: ArrayList greaterThanList = new ArrayList();
267: ListIterator it = keys.listIterator();
268: // skip the first key that we pulled for a pivot
269: it.next();
270: while (it.hasNext()) {
271: Integer key = ((Integer) it.next());
272: String keyValue = getPivotValue(subject[key.intValue()][column]);
273: int comparisonResult = compare(keyValue, pivotValue, type);
274: if (comparisonResult < 0) {
275: lessThanList.add(key);
276: } else {
277: greaterThanList.add(key);
278: }
279: }
280: int[] lessThan = null;
281: int[] greaterThan = null;
282: if (lessThanList.size() > 0) {
283: lessThan = sortKeys(lessThanList, column, type);
284: }
285: if (greaterThanList.size() > 0) {
286: greaterThan = sortKeys(greaterThanList, column, type);
287: }
288: int ltlen = (lessThan == null ? 0 : lessThan.length);
289: int gtlen = (greaterThan == null ? 0 : greaterThan.length);
290: int totalReturnSize = ltlen + 1 + gtlen;
291: int[] orderedKeys = new int[totalReturnSize];
292: int orderedKeyIndex = 0;
293: for (int i = 0; i < ltlen; i++) {
294: orderedKeys[orderedKeyIndex] = lessThan[i];
295: orderedKeyIndex++;
296: }
297: orderedKeys[orderedKeyIndex] = pivotKey;
298: orderedKeyIndex++;
299: for (int i = 0; i < gtlen; i++) {
300: orderedKeys[orderedKeyIndex] = greaterThan[i];
301: orderedKeyIndex++;
302: }
303: return orderedKeys;
304: }
305:
306: private Object sortType(int column) {
307: if (column >= 0
308: && column <= getModel().getTreeTableColumns().size()) {
309: TreeTableBrowserColumnModel tcm = (TreeTableBrowserColumnModel) getModel()
310: .getTreeTableColumns().get(column);
311: return tcm.getType();
312: }
313: return null;
314: }
315:
316: public void toggleSortDirection(int col) {
317: if (sortDirection.get(col)) {
318: sortDirection.clear(col);
319: } else {
320: sortDirection.set(col);
321: }
322: }
323: }
|