001 package nl.cwi.sen1.visplugin.table.model;
002
003
004 /**
005 * Table sorter. Sorts a table using comparators
006 *
007 * @author Anton Gerdessen
008 * @date 12-03-2007
009 */
010 public class TableSorter {
011 SortableTableModel model;
012
013 /**
014 * Constructor.
015 *
016 * @param model The model to sort
017 * @author Anton Gerdessen
018 * @date 12-03-2007
019 */
020 public TableSorter(SortableTableModel model) {
021 this.model = model;
022 }
023
024 /**
025 * Sort the table on a given column and an order.
026 *
027 * @param column the column to sort on
028 * @param isAscent ascending (true) or or decending (false) order
029 * @author Anton Gerdessen
030 * @date 12-03-2007
031 */
032 public void sort(int column, boolean isAscent) {
033 int rowCount = model.getRowCount();
034 int[] indexes = model.getIndexes();
035
036 // Quicksort
037 for (int rowCounter = 0; rowCounter < rowCount - 1; rowCounter++) {
038 int row1 = rowCounter;
039 for (int row2 = rowCounter + 1; row2 < rowCount; row2++) {
040 // Sort ascending.
041 if (isAscent) {
042 if (compare(column, row2, row1) < 0) {
043 row1 = row2;
044 }
045 // Sort decending.
046 } else {
047 if (compare(column, row2, row1) > 0) {
048 row1 = row2;
049 }
050 }
051 }
052 int tmp = indexes[rowCounter];
053 indexes[rowCounter] = indexes[row1];
054 indexes[row1] = tmp;
055 }
056 }
057
058 /**
059 * Compare two values in one column, these two values are the values
060 * at (column, row1) and (column, row2).
061 *
062 * @param column the column to sort on
063 * @param row1 The numbers to compare
064 * @param row2 The numbers to compare
065 * @author Anton Gerdessen
066 * @date 12-03-2007
067 */
068 private int compare(int column, int row1, int row2) {
069 Object o1 = model.getValueAt(row1, column);
070 Object o2 = model.getValueAt(row2, column);
071
072 // Check for null values, of a null is detected the 'other' is always greater
073 // if both are null return equal
074 if (o1 == null && o2 == null) {
075 return 0;
076 } else if (o1 == null) {
077 return -1;
078 } else if (o2 == null) {
079 return 1;
080 }
081
082 // Determine the data type used in the column and call the compare for that type.
083 // Default is the string compareTo.
084 Class<?> type = model.getColumnClass(column);
085 if (type.getSuperclass() == Number.class) {
086 return compare((Number) o1, (Number) o2);
087 } else if (type == String.class) {
088 return ((String) o1).compareTo((String) o2);
089 } else {
090 return (o1.toString().compareTo(o2.toString()));
091 }
092 }
093
094 /**
095 * Number comparator based on doubles. Return -1 if num2
096 * is greater, 1 if num1 is greater, else 0.
097 *
098 * @param num1 The numbers to compare
099 * @param num2 The numbers to compare
100 * @author Anton Gerdessen
101 * @date 12-03-2007
102 */
103 private int compare(Number num1, Number num2) {
104 double n1 = num1.doubleValue();
105 double n2 = num2.doubleValue();
106
107 if (n1 < n2) {
108 return -1;
109 } else if (n1 > n2) {
110 return 1;
111 } else {
112 return 0;
113 }
114 }
115
116
117
118 }