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    }