1:
31: package ;
32:
33: import ;
34: import ;
35: import ;
36: import ;
37: import ;
38:
39: public class JoiningTableModel extends AbstractTableModel
40: {
41: private static class TablePosition
42: {
43: private TableModel tableModel;
44: private String prefix;
45: private int tableOffset;
46: private int columnOffset;
47:
48: private TablePosition (final TableModel tableModel,
49: final String prefix)
50: {
51: if (tableModel == null)
52: {
53: throw new NullPointerException("Model must not be null");
54: }
55: if (prefix == null)
56: {
57: throw new NullPointerException("Prefix must not be null.");
58: }
59: this.tableModel = tableModel;
60: this.prefix = prefix;
61: }
62:
63: public void updateOffsets (final int tableOffset, final int columnOffset)
64: {
65: this.tableOffset = tableOffset;
66: this.columnOffset = columnOffset;
67: }
68:
69: public String getPrefix ()
70: {
71: return prefix;
72: }
73:
74: public int getColumnOffset ()
75: {
76: return columnOffset;
77: }
78:
79: public TableModel getTableModel ()
80: {
81: return tableModel;
82: }
83:
84: public int getTableOffset ()
85: {
86: return tableOffset;
87: }
88: }
89:
90: private class TableChangeHandler implements TableModelListener
91: {
92: private TableChangeHandler ()
93: {
94: }
95:
96:
100: public void tableChanged (final TableModelEvent e)
101: {
102: if (e.getType() == TableModelEvent.HEADER_ROW)
103: {
104: updateStructure();
105: }
106: else if (e.getType() == TableModelEvent.INSERT ||
107: e.getType() == TableModelEvent.DELETE)
108: {
109: updateRowCount();
110: }
111: else
112: {
113: updateData();
114: }
115: }
116: }
117:
118:
119: private String[] columnNames;
120:
121: private Class[] columnTypes;
122:
123: private ArrayList models;
124: private TableChangeHandler changeHandler;
125: private int rowCount;
126: public static final String TABLE_PREFIX_COLUMN = "TablePrefix";
127:
128: public JoiningTableModel ()
129: {
130: models = new ArrayList();
131: changeHandler = new TableChangeHandler();
132: }
133:
134: public synchronized void addTableModel (final String prefix, final TableModel model)
135: {
136: models.add(new TablePosition(model, prefix));
137: model.addTableModelListener(changeHandler);
138: updateStructure();
139: }
140:
141: public synchronized void removeTableModel (final TableModel model)
142: {
143: for (int i = 0; i < models.size(); i++)
144: {
145: final TablePosition position = (TablePosition) models.get(i);
146: if (position.getTableModel() == model)
147: {
148: models.remove(model);
149: model.removeTableModelListener(changeHandler);
150: updateStructure();
151: return;
152: }
153: }
154: }
155:
156: public synchronized int getTableModelCount ()
157: {
158: return models.size();
159: }
160:
161: public synchronized TableModel getTableModel (final int pos)
162: {
163: final TablePosition position = (TablePosition) models.get(pos);
164: return position.getTableModel();
165: }
166:
167: protected synchronized void updateStructure()
168: {
169: final ArrayList columnNames = new ArrayList();
170: final ArrayList columnTypes = new ArrayList();
171:
172: columnNames.add(TABLE_PREFIX_COLUMN);
173: columnTypes.add(String.class);
174:
175: int columnOffset = 1;
176: int rowOffset = 0;
177: for (int i = 0; i < models.size(); i++)
178: {
179: final TablePosition pos = (TablePosition) models.get(i);
180: pos.updateOffsets(rowOffset, columnOffset);
181: final TableModel tableModel = pos.getTableModel();
182: rowOffset += tableModel.getRowCount();
183: columnOffset += tableModel.getColumnCount();
184: for (int c = 0; c < tableModel.getColumnCount(); c++)
185: {
186: columnNames.add(pos.getPrefix() + "." + tableModel.getColumnName(c));
187: columnTypes.add(tableModel.getColumnClass(c));
188: }
189: }
190: this.columnNames = (String[]) columnNames.toArray(new String[columnNames.size()]);
191: this.columnTypes = (Class[]) columnTypes.toArray(new Class[columnTypes.size()]);
192: this.rowCount = rowOffset;
193: fireTableStructureChanged();
194: }
195:
196: protected synchronized void updateRowCount()
197: {
198: int rowOffset = 0;
199: int columnOffset = 1;
200: for (int i = 0; i < models.size(); i++)
201: {
202: final TablePosition model = (TablePosition) models.get(i);
203: model.updateOffsets(rowOffset, columnOffset);
204: rowOffset += model.getTableModel().getRowCount();
205: columnOffset += model.getTableModel().getColumnCount();
206: }
207: fireTableStructureChanged();
208: }
209:
210: protected void updateData()
211: {
212:
213: fireTableDataChanged();
214: }
215:
216:
222: public synchronized Class getColumnClass (final int columnIndex)
223: {
224: return columnTypes[columnIndex];
225: }
226:
227:
234: public synchronized String getColumnName (final int column)
235: {
236: return columnNames[column];
237: }
238:
239:
246: public final boolean isCellEditable (final int rowIndex, final int columnIndex)
247: {
248: return false;
249: }
250:
251:
260: public synchronized int getColumnCount ()
261: {
262: return columnNames.length;
263: }
264:
265:
274: public synchronized int getRowCount ()
275: {
276: return rowCount;
277: }
278:
279:
286: public synchronized Object getValueAt (final int rowIndex, final int columnIndex)
287: {
288:
289: final TablePosition pos = getTableModelForRow(rowIndex);
290: if (pos == null)
291: {
292: return null;
293: }
294:
295: if (columnIndex == 0)
296: {
297: return pos.getPrefix();
298: }
299:
300: final int columnOffset = pos.getColumnOffset();
301: if (columnIndex < columnOffset)
302: {
303: return null;
304: }
305:
306: final TableModel tableModel = pos.getTableModel();
307: if (columnIndex >= (columnOffset + tableModel.getColumnCount()))
308: {
309: return null;
310: }
311: return tableModel.getValueAt
312: (rowIndex - pos.getTableOffset(), columnIndex - columnOffset);
313: }
314:
315: private TablePosition getTableModelForRow (final int row)
316: {
317:
318: for (int i = 0; i < models.size(); i++)
319: {
320: final TablePosition pos = (TablePosition) models.get(i);
321: final int maxRow = pos.getTableOffset() + pos.getTableModel().getRowCount();
322: if (row < maxRow)
323: {
324: return pos;
325: }
326: }
327: return null;
328: }
329: }