001 package nl.cwi.sen1.visplugin.table.model; 002 003 import javax.swing.table.DefaultTableModel; 004 005 import nl.cwi.sen1.relationstores.types.IdCon; 006 import nl.cwi.sen1.relationstores.types.RElem; 007 import nl.cwi.sen1.relationstores.types.RElemElements; 008 import nl.cwi.sen1.relationstores.types.RTuple; 009 import nl.cwi.sen1.relationstores.types.RType; 010 import nl.cwi.sen1.relationstores.types.RTypeColumnTypes; 011 012 /** 013 * Table model supporting column sortings. This model is able to work directly 014 * with RTuples and its data should be set using the setRTupleData() function. 015 * The original RElems can then be retrieved for every table row using the 016 * getRElemForRow() function. 017 * 018 * @author Anton Gerdessen 019 * @date 12-03-2007 020 */ 021 public class SortableTableModel extends DefaultTableModel { 022 023 private static final long serialVersionUID = 1L; 024 025 private int[] m_indexes; 026 027 private TableSorter m_sorter; 028 029 private RTuple m_data; 030 031 private IdCon m_rTupleVariable; 032 033 private RType m_rTupleRType; 034 035 public SortableTableModel() { 036 super(); 037 038 m_data = null; 039 } 040 041 /** 042 * Retrieve the value for a given postion (row,col). 043 * 044 * @param row 045 * The (row,col) combination 046 * @param col 047 * The (row,col) combination 048 * @author Anton Gerdessen 049 * @date 12-03-2007 050 */ 051 public Object getValueAt(int row, int col) { 052 int rowIndex = row; 053 if (m_indexes != null) { 054 rowIndex = m_indexes[row]; 055 } 056 return super.getValueAt(rowIndex, col); 057 } 058 059 /** 060 * Set the value for a given postion (row,col). 061 * 062 * @param value 063 * The value to set at the (row,col) combination 064 * @param row 065 * The (row,col) combination 066 * @param col 067 * The (row,col) combination 068 * @author Anton Gerdessen 069 * @date 12-03-2007 070 */ 071 public void setValueAt(Object value, int row, int col) { 072 int rowIndex = row; 073 if (m_indexes != null) { 074 rowIndex = m_indexes[row]; 075 } 076 super.setValueAt(value, rowIndex, col); 077 } 078 079 /** 080 * Retrieve the value for a given postion (row,col). 081 * 082 * @param column 083 * the column to base the sort on 084 * @param isAscent 085 * ascending (true) or or decending (false) order 086 * @author Anton Gerdessen 087 * @date 12-03-2007 088 */ 089 public void sortByColumn(int column, boolean isAscent) { 090 if (m_sorter == null) { 091 m_sorter = new TableSorter(this); 092 } 093 m_sorter.sort(column, isAscent); 094 fireTableDataChanged(); 095 } 096 097 /** 098 * Returns the index mapping on which the current sort is based. 099 * 100 * @return The index mapping as an array. 101 * 102 * @author Anton Gerdessen 103 * @date 12-03-2007 104 */ 105 public int[] getIndexes() { 106 int n = getRowCount(); 107 if (m_indexes != null) { 108 if (m_indexes.length == n) { 109 return m_indexes; 110 } 111 } 112 m_indexes = new int[n]; 113 for (int i = 0; i < n; i++) { 114 m_indexes[i] = i; 115 } 116 return m_indexes; 117 } 118 119 /** 120 * Return the type which is displayed in the given column. 121 * 122 * @param column 123 * The column to retrieve the type from 124 * @author Anton Gerdessen 125 * @date 12-03-2007 126 */ 127 @SuppressWarnings("unchecked") 128 public Class getColumnClass(int column) { 129 // Retrieve the first item of the column and base the type on that. 130 return getValueAt(0, column).getClass(); 131 } 132 133 /** 134 * Sets the data of the table model to the data contained in the RTuple. 135 * 136 * @param data 137 * The RTuple data to put in the table. 138 * 139 */ 140 public void setRTupleData(RTuple data) { 141 try { 142 m_rTupleVariable = data.getVariable(); 143 m_rTupleRType = data.getRtype(); 144 RElem value = data.getValue(); 145 Object[][] dataVector = null; 146 String[] columnIdentifiers = null; 147 148 if (value.isBool() || value.isInt() || value.isLoc() 149 || value.isStr()) { 150 columnIdentifiers = new String[] { "value" }; 151 dataVector = new Object[1][1]; 152 dataVector[0][0] = getValueFromRElem(value); 153 } else if (value.isSet() || value.isBag()) { 154 if (m_rTupleRType.hasColumnTypes()) { 155 RElemElements es = value.getElements(); 156 RTypeColumnTypes columnTypes = m_rTupleRType 157 .getColumnTypes(); 158 columnIdentifiers = convertColumnTypesToStrings(columnTypes); 159 160 int numRows = es.getLength(); 161 int numColumns = columnTypes.getLength(); 162 163 // copies each of the values of the RTuple to the dataVector 164 dataVector = new Object[numRows][numColumns]; 165 for (int r = 0; !es.isEmpty(); es = es.getTail(), r++) { 166 RElem tuple = es.getHead(); 167 RElemElements fs = tuple.getElements(); 168 169 for (int c = 0; !fs.isEmpty(); fs = fs.getTail(), c++) { 170 RElem elem = fs.getHead(); 171 dataVector[r][c] = getValueFromRElem(elem); 172 } 173 } 174 } else if (value.hasElements()) { 175 RElemElements es = value.getElements(); 176 dataVector = new Object[es.getLength()][1]; 177 columnIdentifiers = new String[] { "values" }; 178 179 for (int i = 0; !es.isEmpty(); es = es.getTail(), i++) { 180 RElem val = es.getHead(); 181 dataVector[i][0] = getValueFromRElem(val); 182 } 183 } else { 184 System.err 185 .println("Apparently forgot to implement mapping for " 186 + m_rTupleRType.toTerm().toString()); 187 } 188 } else { 189 System.err 190 .println("Apparently forgot to implement mapping for " 191 + m_rTupleRType.toTerm().toString()); 192 return; 193 } 194 195 setDataVector(dataVector, columnIdentifiers); 196 m_data = data; 197 } catch (Exception exception) { 198 System.err.print(exception.getMessage()); 199 exception.printStackTrace(); 200 } 201 } 202 203 /** 204 * Returns the variable of the set RTuple data. 205 * 206 * @return The RTuple variable. 207 * 208 * @sa setRTupleData() 209 * 210 * @author Anton Gerdessen 211 * @author Arend van Beelen 212 * @data 13-03-2007 213 */ 214 public IdCon getRTupleVariable() { 215 return m_rTupleVariable; 216 } 217 218 /** 219 * Returns the RType of the set RTuple data. 220 * 221 * @return The RTuple RType. 222 * 223 * @sa setRTupleData() 224 * 225 * @author Anton Gerdessen 226 * @author Arend van Beelen 227 * @data 13-03-2007 228 */ 229 public RType getRTupleRType() { 230 return m_rTupleRType; 231 } 232 233 /** 234 * Returns an RElem containing the data for a row. 235 * 236 * @param rowIndex 237 * Index of the row. If sorting is enabled, the index will 238 * automatically adjusted. 239 * @return An RElem from the RTuple data. 240 * 241 * @author Anton Gerdessen 242 * @author Arend van Beelen 243 * @data 13-03-2007 244 */ 245 public RElem getRElemForRow(int rowIndex) { 246 if (m_indexes != null) { 247 rowIndex = m_indexes[rowIndex]; 248 } 249 RElem value = m_data.getValue(); 250 RElemElements valueElements = value.getElements(); 251 return valueElements.getRElemAt(rowIndex); 252 } 253 254 /** 255 * Converts RElem value to an object. It supports only four types (str, int, 256 * bool, loc ) now. 257 * 258 * @param element 259 * @return Object 260 * 261 * @exception Exception 262 * Throws and unknown RElem exception when the element is of 263 * an unknown type. 264 * 265 * @author Srinivasan Tharmarajah 266 * @date 08-03-2007 267 */ 268 private static Object getValueFromRElem(RElem element) throws Exception { 269 Object value = null; 270 271 if (element.isStr()) { 272 value = element.getStrCon(); 273 } else if (element.isInt()) { 274 value = new Integer(element.getInteger().getNatCon()); 275 } else if (element.isBool()) { 276 value = element.getBoolCon(); 277 } else if (element.isLoc()) { 278 value = element.getLocation(); 279 } else { 280 value = element.toTerm().toString(); 281 } 282 283 return value; 284 } 285 286 /** 287 * Converts RTypeColumnTypes to an array of Strings 288 * 289 * @param columnTypes 290 * @return 291 * @author Antoine Savelkoul 292 * @date 08-03-2007 293 */ 294 private static String[] convertColumnTypesToStrings( 295 RTypeColumnTypes columnTypes) { 296 int numColumns = columnTypes.getLength(); 297 String[] columnNames = new String[numColumns]; 298 299 // copies each of the type names to the array 300 for (int columnNum = 0; columnNum < numColumns; columnNum++) { 301 RType columnType = columnTypes.getRTypeAt(columnNum); 302 columnNames[columnNum] = columnType.toString() + " [" + columnNum 303 + "]"; 304 } 305 306 return columnNames; 307 } 308 309 /** 310 * Returns 311 * 312 * @c false so that the table cells are not editable. 313 * 314 * @param rowIndex 315 * Row index of the cell, ignored. 316 * @param columnIndex 317 * Column index of the cell, ignored. 318 * 319 * @return 320 * @c false. 321 * 322 * @author Arend van Beelen 323 * @date 12-03-2007 324 */ 325 public boolean isCellEditable(int rowIndex, int columnIndex) { 326 return false; 327 } 328 }