1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package coras.table;
22
23 import java.beans.PropertyChangeListener;
24 import java.beans.PropertyChangeSupport;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31
32 import javax.swing.table.AbstractTableModel;
33
34 import no.sintef.xml.XmlHelper;
35
36 import org.apache.log4j.Logger;
37
38 import coras.table.columnchoices.jaxb.ChoiceType;
39 import coras.table.columnchoices.jaxb.ColumnChoicesType;
40 import coras.table.columnchoices.jaxb.ColumnType;
41 import coras.table.jaxb.CellType;
42 import coras.table.jaxb.ColumnDefType;
43 import coras.table.jaxb.RowType;
44 import coras.table.jaxb.TableType;
45 import coras.table.jaxb.impl.CellTypeImpl;
46 import coras.table.jaxb.impl.ColumnDefTypeImpl;
47 import coras.table.jaxb.impl.RowTypeImpl;
48
49 /***
50 * @author fvr
51 *
52 * To change the template for this generated type comment go to
53 * Window - Preferences - Java - Code Generation - Code and Comments
54 */
55 public class CorasTableModel extends AbstractTableModel {
56
57 public static final String DIRTY = "dirty";
58 private static final Logger LOGGER = Logger.getLogger(CorasTableModel.class);
59
60 private TableType table = null;
61 private Map columnChoicesMap = new HashMap();
62
63 private boolean dirty = false;
64 private PropertyChangeSupport propertyChangeHandler = new PropertyChangeSupport(this);
65
66 public TableType getTable() {
67 return table;
68 }
69
70 public void setTable(TableType table) {
71 this.table = table;
72 fireTableChanged(null);
73 }
74
75 public boolean isFixedStructure() {
76 return table == null || table.isFixedStructure();
77 }
78
79 public boolean isDirty() {
80 return dirty;
81 }
82
83 private void setDirty(boolean newDirty) {
84 boolean oldDirty = dirty;
85 dirty = newDirty;
86 if (oldDirty != newDirty) {
87 propertyChangeHandler.firePropertyChange(DIRTY, oldDirty, newDirty);
88 }
89 }
90
91 public void makeClean() {
92 setDirty(false);
93 }
94
95 private void makeDirty() {
96 setDirty(true);
97 }
98
99
100
101
102 public int getColumnCount() {
103 if (table == null) {
104 return 0;
105 } else {
106 return getVisibleColumnDefs().size();
107 }
108 }
109
110
111
112
113 public int getRowCount() {
114 if (table == null) {
115 return 0;
116 } else {
117 return table.getRows().getRow().size();
118 }
119 }
120
121
122
123
124 public Object getValueAt(int rowIndex, int columnIndex) {
125 CellType cell = getCell(rowIndex, columnIndex);
126 if (cell != null)
127 return cell.getValue();
128 else
129 return "";
130 }
131
132
133
134
135 public String getColumnName(int columnIndex) {
136 if (table == null) {
137 return null;
138 }
139
140 ColumnDefType columnDef = getColumnDef(columnIndex);
141 if (columnDef == null) {
142 return null;
143 }
144
145
146
147 String tableType = getTable().getType();
148 String columnId = columnDef.getId();
149 String key = tableType.replaceAll("//s", "_") + "." + columnId;
150 String name = Messages.getColumnName(key);
151 if (name.equals('!' + key + '!')) {
152 key = columnId;
153 name = Messages.getColumnName(key);
154 }
155 if (name.equals('!' + key + '!')) {
156 name = null;
157 }
158 if (name != null) {
159 return name;
160 } else {
161 return columnDef.getName();
162 }
163 }
164
165
166
167
168 public String getColumnDescription(int columnIndex) {
169 if (table == null) {
170 return null;
171 }
172
173
174
175 String tableType = getTable().getType();
176 String columnId = getColumnId(columnIndex);
177 String key = tableType.replaceAll("//s", "_") + "." + columnId;
178 String description = Messages.getColumnDescription(key);
179 if (description.equals('!' + key + '!')) {
180 key = columnId;
181 description = Messages.getColumnDescription(key);
182 }
183 if (description.equals('!' + key + '!')) {
184 description = null;
185 }
186 return description;
187 }
188
189
190
191
192 public Class getColumnClass(int columnIndex) {
193 return String.class;
194 }
195
196
197
198
199 public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
200 if (aValue instanceof String) {
201 if (!isValidValue(aValue, rowIndex, columnIndex)) {
202 System.err.println("invalid cell value: " + aValue);
203 Thread.dumpStack();
204 return;
205 }
206 CellType cell = getCell(rowIndex, columnIndex);
207 if (cell == null) {
208 System.err.println("This should never happen: cell is null");
209 Thread.dumpStack();
210 return;
211 }
212 if (aValue.equals(cell.getValue())) {
213 return;
214 }
215 cell.setValue((String) aValue);
216 makeDirty();
217 fireTableCellUpdated(rowIndex, columnIndex);
218 } else {
219 System.err.println("Unsupported cell value type: " + aValue + (aValue != null ? " [" + aValue.getClass() + "]" : ""));
220 Thread.dumpStack();
221 }
222 }
223
224
225
226
227 public boolean isCellEditable(int rowIndex, int columnIndex) {
228 ColumnDefType columnDef = getColumnDef(columnIndex);
229 return columnDef != null && columnDef.isEditable();
230 }
231
232 /***
233 *
234 */
235 public void addRow(int rowIndex) {
236 if (table == null) {
237 return;
238 }
239 if (table.isFixedStructure()) {
240 return;
241 }
242 List rows = table.getRows().getRow();
243 LOGGER.debug("addRow(" + rowIndex + ") of " + rows.size());
244 if (rowIndex < 0 || rowIndex > rows.size())
245 return;
246 RowType row = new RowTypeImpl();
247 List cells = row.getCell();
248 for (Iterator i = getColumnDefs().iterator(); i.hasNext(); ) {
249 ColumnDefType columnDef = (ColumnDefType) i.next();
250 CellType cell = new CellTypeImpl();
251 cell.setColumnId(columnDef.getId());
252 cell.setValue("");
253 cells.add(cell);
254 }
255 rows.add(rowIndex, row);
256 makeDirty();
257 fireTableRowsInserted(rowIndex, rowIndex);
258
259 }
260
261 public void deleteRow(int rowIndex) {
262 if (table == null) {
263 return;
264 }
265 if (table.isFixedStructure()) {
266 return;
267 }
268 List rows = table.getRows().getRow();
269 if (rows.size() <= 1) {
270 return;
271 }
272 if (rowIndex < 0 || rowIndex >= rows.size()) {
273 return;
274 }
275 rows.remove(rowIndex);
276 makeDirty();
277 fireTableRowsDeleted(rowIndex, rowIndex);
278 }
279
280
281 /***
282 * @param columnChoices
283 */
284 public void setColumnChoices(ColumnChoicesType columnChoices) {
285 columnChoicesMap = createColumnChoicesMap(columnChoices);
286 }
287
288 public void addPropertyChangeListener(PropertyChangeListener listener) {
289 propertyChangeHandler.addPropertyChangeListener(listener);
290 }
291
292 public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
293 propertyChangeHandler.addPropertyChangeListener(propertyName, listener);
294 }
295
296 public void removePropertyChangeListener(PropertyChangeListener listener) {
297 propertyChangeHandler.removePropertyChangeListener(listener);
298 }
299
300 public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
301 propertyChangeHandler.removePropertyChangeListener(propertyName, listener);
302 }
303
304 protected boolean isValidValue(Object aValue, int rowIndex, int columnIndex) {
305 if (isUserEditable(columnIndex)) {
306 return true;
307 }
308 Collection choices = getColumnChoices(columnIndex);
309 if (choices == null || choices.size() == 0) {
310 return true;
311 }
312 for (Iterator i = choices.iterator(); i.hasNext();) {
313 ChoiceType choice = (ChoiceType) i.next();
314 if (choice.getValue().equals(aValue)) {
315 return true;
316 }
317 }
318 return false;
319 }
320
321 protected Collection getColumnChoices(int col) {
322 String columnId = getColumnId(col);
323
324 ColumnType column = (ColumnType) columnChoicesMap.get(columnId);
325 return column != null ? column.getChoice() : null;
326 }
327
328 /***
329 * @param column
330 * @return
331 */
332 protected boolean isUserEditable(int col) {
333 String columnId = getColumnId(col);
334
335 ColumnType column = (ColumnType) columnChoicesMap.get(columnId);
336 return column != null ? column.isUserEditable() : false;
337 }
338
339 /***
340 * @param string
341 * @return
342 */
343 private String getColumnId(int columnIndex) {
344 if (table == null) {
345 return null;
346 }
347 ColumnDefType columnDef = getColumnDef(columnIndex);
348 if (columnDef != null)
349 return columnDef.getId();
350 else
351 return null;
352 }
353
354 private CellType getCell(int rowIndex, int columnIndex) {
355 if (table == null) {
356 return null;
357 }
358 List rows = table.getRows().getRow();
359 if (rowIndex >= rows.size()) {
360 return null;
361 }
362 RowType row = (RowType) rows.get(rowIndex);
363 ColumnDefType columnDef = getColumnDef(columnIndex);
364 if (row == null || columnDef == null) {
365 return null;
366 }
367 String columnId = columnDef.getId();
368 List cells = row.getCell();
369 for (Iterator i = cells.iterator(); i.hasNext(); ) {
370 CellType cell = (CellType) i.next();
371 if (columnId.equals(cell.getColumnId()))
372 return cell;
373 }
374
375 CellType cell = new CellTypeImpl();
376 cell.setColumnId(columnId);
377 cell.setValue("");
378 cells.add(cell);
379 return cell;
380 }
381
382 /***
383 * @param includeHidden TODO
384 * @return
385 */
386 private List getVisibleColumnDefs() {
387 return getColumnDefs(true, false);
388 }
389
390 public List getHiddenColumnDefs() {
391 return getColumnDefs(false, true);
392 }
393
394 private List getColumnDefs() {
395 return getColumnDefs(true, true);
396 }
397
398 private List getColumnDefs(boolean visible, boolean hidden) {
399 List defs = table.getColumnDefs().getColumnDef();
400 List result = new ArrayList();
401 for (Iterator i = defs.iterator(); i.hasNext();) {
402 ColumnDefType def = (ColumnDefType) i.next();
403 if ((hidden && def.isHidden()) || (visible && !def.isHidden())) {
404 result.add(def);
405 }
406 }
407 return result;
408 }
409
410 /***
411 * @param columnIndex
412 * @return
413 */
414 private ColumnDefType getColumnDef(int columnIndex) {
415 ColumnDefType columnDef = (ColumnDefType) getVisibleColumnDefs().get(columnIndex);
416 return columnDef;
417 }
418
419 private ColumnDefType getColumnDef(String columnId) {
420 if (columnId == null) {
421 return null;
422 }
423 List defs = table.getColumnDefs().getColumnDef();
424 for (Iterator i = defs.iterator(); i.hasNext();) {
425 ColumnDefType col = (ColumnDefType) i.next();
426 if (columnId.equals(col.getId())) {
427 return col;
428 }
429 }
430 return null;
431 }
432
433 /***
434 * @param columnChoices
435 * @return
436 */
437 private Map createColumnChoicesMap(ColumnChoicesType columnChoices) {
438 Map map = new HashMap();
439 if (columnChoices == null)
440 return map;
441 List columns = columnChoices.getColumn();
442 for (Iterator i = columns.iterator(); i.hasNext(); ) {
443 ColumnType column = (ColumnType) i.next();
444 map.put(column.getId(), column);
445 }
446 return map;
447 }
448
449 public boolean canHideColumn(int columnIndex) {
450 return getVisibleColumnDefs().size() > 1;
451 }
452
453 /***
454 * @param selectedColumn
455 */
456 public void hideColumn(int columnIndex) {
457 if (canHideColumn(columnIndex)) {
458 return;
459 }
460 ColumnDefType columnDef = getColumnDef(columnIndex);
461 columnDef.setHidden(true);
462 fireTableStructureChanged();
463 }
464
465 public void showColumn(String columnId) {
466 ColumnDefType columnDef = getColumnDef(columnId);
467 columnDef.setHidden(false);
468 fireTableStructureChanged();
469 }
470
471 public void addColumn(int columnIndex, String name) {
472 if (table.isFixedStructure()) {
473 return;
474 }
475 List columnDefs = table.getColumnDefs().getColumnDef();
476 int realIndex = getColumnDefIndex(columnIndex, columnDefs);
477 if (realIndex == -1) {
478 realIndex = columnDefs.size();
479 } else if (realIndex < -1) {
480 return;
481 }
482 ColumnDefType newColumnDef = new ColumnDefTypeImpl();
483 newColumnDef.setId(XmlHelper.genID());
484 newColumnDef.setName(name);
485 columnDefs.add(realIndex, newColumnDef);
486
487 fireTableStructureChanged();
488 }
489
490 public void deleteColumn(int columnIndex) {
491 if (table.isFixedStructure()) {
492 return;
493 }
494 List columnDefs = table.getColumnDefs().getColumnDef();
495 int realIndex = getColumnDefIndex(columnIndex, columnDefs);
496 if (realIndex < 0) {
497 return;
498 }
499 ColumnDefType columnDef = (ColumnDefType) columnDefs.remove(realIndex);
500 String columnId = columnDef.getId();
501 List rows = table.getRows().getRow();
502 for (Iterator i = rows.iterator(); i.hasNext();) {
503 RowType row = (RowType) i.next();
504 List cells = row.getCell();
505 int j = 0;
506 boolean found = false;
507 while (!found && j < cells.size()) {
508 CellType cell = (CellType) cells.get(j);
509 if (columnId.equals(cell.getColumnId())) {
510 cells.remove(j);
511 found = true;
512 } else {
513 j++;
514 }
515 }
516 }
517 fireTableStructureChanged();
518 }
519
520 public void fireTableStructureChanged() {
521 super.fireTableStructureChanged();
522 makeDirty();
523 }
524
525 /***
526 * @param columnIndex
527 * @param columnDefs
528 * @return
529 */
530 private int getColumnDefIndex(int columnIndex, List columnDefs) {
531 int realIndex = 0;
532 while (realIndex < columnDefs.size() && ((ColumnDefType)columnDefs.get(realIndex)).isHidden()) {
533 realIndex++;
534 }
535 while (columnIndex > 0 && realIndex < columnDefs.size()) {
536 ColumnDefType columnDef = (ColumnDefType) columnDefs.get(realIndex);
537 if (!columnDef.isHidden()) {
538 columnIndex--;
539 }
540 realIndex++;
541 }
542 return columnIndex == 0 ? realIndex : -columnIndex;
543 }
544
545 }