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 }