1:
44:
45: package ;
46:
47: import ;
48: import ;
49: import ;
50: import ;
51:
52:
56: public class KeyedObjects2D implements Cloneable, Serializable {
57:
58:
59: private static final long serialVersionUID = -1015873563138522374L;
60:
61:
62: private List rowKeys;
63:
64:
65: private List columnKeys;
66:
67:
68: private List rows;
69:
70:
73: public KeyedObjects2D() {
74: this.rowKeys = new java.util.ArrayList();
75: this.columnKeys = new java.util.ArrayList();
76: this.rows = new java.util.ArrayList();
77: }
78:
79:
86: public int getRowCount() {
87: return this.rowKeys.size();
88: }
89:
90:
97: public int getColumnCount() {
98: return this.columnKeys.size();
99: }
100:
101:
111: public Object getObject(int row, int column) {
112: Object result = null;
113: KeyedObjects rowData = (KeyedObjects) this.rows.get(row);
114: if (rowData != null) {
115: Comparable columnKey = (Comparable) this.columnKeys.get(column);
116: if (columnKey != null) {
117: int index = rowData.getIndex(columnKey);
118: if (index >= 0) {
119: result = rowData.getObject(columnKey);
120: }
121: }
122: }
123: return result;
124: }
125:
126:
135: public Comparable getRowKey(int row) {
136: return (Comparable) this.rowKeys.get(row);
137: }
138:
139:
149: public int getRowIndex(Comparable key) {
150: if (key == null) {
151: throw new IllegalArgumentException("Null 'key' argument.");
152: }
153: return this.rowKeys.indexOf(key);
154: }
155:
156:
163: public List getRowKeys() {
164: return Collections.unmodifiableList(this.rowKeys);
165: }
166:
167:
176: public Comparable getColumnKey(int column) {
177: return (Comparable) this.columnKeys.get(column);
178: }
179:
180:
190: public int getColumnIndex(Comparable key) {
191: if (key == null) {
192: throw new IllegalArgumentException("Null 'key' argument.");
193: }
194: return this.columnKeys.indexOf(key);
195: }
196:
197:
204: public List getColumnKeys() {
205: return Collections.unmodifiableList(this.columnKeys);
206: }
207:
208:
221: public Object getObject(Comparable rowKey, Comparable columnKey) {
222: if (rowKey == null) {
223: throw new IllegalArgumentException("Null 'rowKey' argument.");
224: }
225: if (columnKey == null) {
226: throw new IllegalArgumentException("Null 'columnKey' argument.");
227: }
228: int row = this.rowKeys.indexOf(rowKey);
229: if (row < 0) {
230: throw new UnknownKeyException("Row key (" + rowKey
231: + ") not recognised.");
232: }
233: int column = this.columnKeys.indexOf(columnKey);
234: if (column < 0) {
235: throw new UnknownKeyException("Column key (" + columnKey
236: + ") not recognised.");
237: }
238: KeyedObjects rowData = (KeyedObjects) this.rows.get(row);
239: int index = rowData.getIndex(columnKey);
240: if (index >= 0) {
241: return rowData.getObject(index);
242: }
243: else {
244: return null;
245: }
246: }
247:
248:
255: public void addObject(Object object, Comparable rowKey,
256: Comparable columnKey) {
257: setObject(object, rowKey, columnKey);
258: }
259:
260:
267: public void setObject(Object object, Comparable rowKey,
268: Comparable columnKey) {
269:
270: if (rowKey == null) {
271: throw new IllegalArgumentException("Null 'rowKey' argument.");
272: }
273: if (columnKey == null) {
274: throw new IllegalArgumentException("Null 'columnKey' argument.");
275: }
276: KeyedObjects row;
277: int rowIndex = this.rowKeys.indexOf(rowKey);
278: if (rowIndex >= 0) {
279: row = (KeyedObjects) this.rows.get(rowIndex);
280: }
281: else {
282: this.rowKeys.add(rowKey);
283: row = new KeyedObjects();
284: this.rows.add(row);
285: }
286: row.setObject(columnKey, object);
287: int columnIndex = this.columnKeys.indexOf(columnKey);
288: if (columnIndex < 0) {
289: this.columnKeys.add(columnKey);
290: }
291:
292: }
293:
294:
304: public void removeObject(Comparable rowKey, Comparable columnKey) {
305: int rowIndex = getRowIndex(rowKey);
306: if (rowIndex < 0) {
307: throw new UnknownKeyException("Row key (" + rowKey
308: + ") not recognised.");
309: }
310: int columnIndex = getColumnIndex(columnKey);
311: if (columnIndex < 0) {
312: throw new UnknownKeyException("Column key (" + columnKey
313: + ") not recognised.");
314: }
315: setObject(null, rowKey, columnKey);
316:
317:
318: boolean allNull = true;
319: KeyedObjects row = (KeyedObjects) this.rows.get(rowIndex);
320:
321: for (int item = 0, itemCount = row.getItemCount(); item < itemCount;
322: item++) {
323: if (row.getObject(item) != null) {
324: allNull = false;
325: break;
326: }
327: }
328:
329: if (allNull) {
330: this.rowKeys.remove(rowIndex);
331: this.rows.remove(rowIndex);
332: }
333:
334:
335: allNull = true;
336:
337: for (int item = 0, itemCount = this.rows.size(); item < itemCount;
338: item++) {
339: row = (KeyedObjects) this.rows.get(item);
340: int colIndex = row.getIndex(columnKey);
341: if (colIndex >= 0 && row.getObject(colIndex) != null) {
342: allNull = false;
343: break;
344: }
345: }
346:
347: if (allNull) {
348: for (int item = 0, itemCount = this.rows.size(); item < itemCount;
349: item++) {
350: row = (KeyedObjects) this.rows.get(item);
351: int colIndex = row.getIndex(columnKey);
352: if (colIndex >= 0) {
353: row.removeValue(colIndex);
354: }
355: }
356: this.columnKeys.remove(columnKey);
357: }
358: }
359:
360:
367: public void removeRow(int rowIndex) {
368: this.rowKeys.remove(rowIndex);
369: this.rows.remove(rowIndex);
370: }
371:
372:
381: public void removeRow(Comparable rowKey) {
382: int index = getRowIndex(rowKey);
383: if (index < 0) {
384: throw new UnknownKeyException("Row key (" + rowKey
385: + ") not recognised.");
386: }
387: removeRow(index);
388: }
389:
390:
397: public void removeColumn(int columnIndex) {
398: Comparable columnKey = getColumnKey(columnIndex);
399: removeColumn(columnKey);
400: }
401:
402:
411: public void removeColumn(Comparable columnKey) {
412: int index = getColumnIndex(columnKey);
413: if (index < 0) {
414: throw new UnknownKeyException("Column key (" + columnKey
415: + ") not recognised.");
416: }
417: Iterator iterator = this.rows.iterator();
418: while (iterator.hasNext()) {
419: KeyedObjects rowData = (KeyedObjects) iterator.next();
420: int i = rowData.getIndex(columnKey);
421: if (i >= 0) {
422: rowData.removeValue(i);
423: }
424: }
425: this.columnKeys.remove(columnKey);
426: }
427:
428:
433: public void clear() {
434: this.rowKeys.clear();
435: this.columnKeys.clear();
436: this.rows.clear();
437: }
438:
439:
446: public boolean equals(Object obj) {
447: if (obj == this) {
448: return true;
449: }
450: if (!(obj instanceof KeyedObjects2D)) {
451: return false;
452: }
453:
454: KeyedObjects2D that = (KeyedObjects2D) obj;
455: if (!getRowKeys().equals(that.getRowKeys())) {
456: return false;
457: }
458: if (!getColumnKeys().equals(that.getColumnKeys())) {
459: return false;
460: }
461: int rowCount = getRowCount();
462: if (rowCount != that.getRowCount()) {
463: return false;
464: }
465: int colCount = getColumnCount();
466: if (colCount != that.getColumnCount()) {
467: return false;
468: }
469: for (int r = 0; r < rowCount; r++) {
470: for (int c = 0; c < colCount; c++) {
471: Object v1 = getObject(r, c);
472: Object v2 = that.getObject(r, c);
473: if (v1 == null) {
474: if (v2 != null) {
475: return false;
476: }
477: }
478: else {
479: if (!v1.equals(v2)) {
480: return false;
481: }
482: }
483: }
484: }
485: return true;
486: }
487:
488:
493: public int hashCode() {
494: int result;
495: result = this.rowKeys.hashCode();
496: result = 29 * result + this.columnKeys.hashCode();
497: result = 29 * result + this.rows.hashCode();
498: return result;
499: }
500:
501:
509: public Object clone() throws CloneNotSupportedException {
510: KeyedObjects2D clone = (KeyedObjects2D) super.clone();
511: clone.columnKeys = new java.util.ArrayList(this.columnKeys);
512: clone.rowKeys = new java.util.ArrayList(this.rowKeys);
513: clone.rows = new java.util.ArrayList(this.rows.size());
514: Iterator iterator = this.rows.iterator();
515: while (iterator.hasNext()) {
516: KeyedObjects row = (KeyedObjects) iterator.next();
517: clone.rows.add(row.clone());
518: }
519: return clone;
520: }
521:
522: }