1:
53:
54: package ;
55:
56: import ;
57: import ;
58: import ;
59: import ;
60:
61: import ;
62: import ;
63:
64:
69: public class DefaultKeyedValues2D implements KeyedValues2D,
70: PublicCloneable, Cloneable,
71: Serializable {
72:
73:
74: private static final long serialVersionUID = -5514169970951994748L;
75:
76:
77: private List rowKeys;
78:
79:
80: private List columnKeys;
81:
82:
83: private List rows;
84:
85:
86: private boolean sortRowKeys;
87:
88:
91: public DefaultKeyedValues2D() {
92: this(false);
93: }
94:
95:
100: public DefaultKeyedValues2D(boolean sortRowKeys) {
101: this.rowKeys = new java.util.ArrayList();
102: this.columnKeys = new java.util.ArrayList();
103: this.rows = new java.util.ArrayList();
104: this.sortRowKeys = sortRowKeys;
105: }
106:
107:
112: public int getRowCount() {
113: return this.rowKeys.size();
114: }
115:
116:
121: public int getColumnCount() {
122: return this.columnKeys.size();
123: }
124:
125:
133: public Number getValue(int row, int column) {
134: Number result = null;
135: DefaultKeyedValues rowData = (DefaultKeyedValues) this.rows.get(row);
136: if (rowData != null) {
137: Comparable columnKey = (Comparable) this.columnKeys.get(column);
138:
139:
140: int index = rowData.getIndex(columnKey);
141: if (index >= 0) {
142: result = rowData.getValue(index);
143: }
144: }
145: return result;
146: }
147:
148:
155: public Comparable getRowKey(int row) {
156: return (Comparable) this.rowKeys.get(row);
157: }
158:
159:
166: public int getRowIndex(Comparable key) {
167: if (key == null) {
168: throw new IllegalArgumentException("Null 'key' argument.");
169: }
170: if (this.sortRowKeys) {
171: return Collections.binarySearch(this.rowKeys, key);
172: }
173: else {
174: return this.rowKeys.indexOf(key);
175: }
176: }
177:
178:
183: public List getRowKeys() {
184: return Collections.unmodifiableList(this.rowKeys);
185: }
186:
187:
194: public Comparable getColumnKey(int column) {
195: return (Comparable) this.columnKeys.get(column);
196: }
197:
198:
205: public int getColumnIndex(Comparable key) {
206: if (key == null) {
207: throw new IllegalArgumentException("Null 'key' argument.");
208: }
209: return this.columnKeys.indexOf(key);
210: }
211:
212:
217: public List getColumnKeys() {
218: return Collections.unmodifiableList(this.columnKeys);
219: }
220:
221:
231: public Number getValue(Comparable rowKey, Comparable columnKey) {
232: if (rowKey == null) {
233: throw new IllegalArgumentException("Null 'rowKey' argument.");
234: }
235: if (columnKey == null) {
236: throw new IllegalArgumentException("Null 'columnKey' argument.");
237: }
238: int row = getRowIndex(rowKey);
239: if (row >= 0) {
240: DefaultKeyedValues rowData
241: = (DefaultKeyedValues) this.rows.get(row);
242: return rowData.getValue(columnKey);
243: }
244: else {
245: throw new UnknownKeyException("Unrecognised rowKey: " + rowKey);
246: }
247: }
248:
249:
257: public void addValue(Number value, Comparable rowKey,
258: Comparable columnKey) {
259:
260: setValue(value, rowKey, columnKey);
261: }
262:
263:
270: public void setValue(Number value, Comparable rowKey,
271: Comparable columnKey) {
272:
273: DefaultKeyedValues row;
274: int rowIndex = getRowIndex(rowKey);
275:
276: if (rowIndex >= 0) {
277: row = (DefaultKeyedValues) this.rows.get(rowIndex);
278: }
279: else {
280: row = new DefaultKeyedValues();
281: if (this.sortRowKeys) {
282: rowIndex = -rowIndex - 1;
283: this.rowKeys.add(rowIndex, rowKey);
284: this.rows.add(rowIndex, row);
285: }
286: else {
287: this.rowKeys.add(rowKey);
288: this.rows.add(row);
289: }
290: }
291: row.setValue(columnKey, value);
292:
293: int columnIndex = this.columnKeys.indexOf(columnKey);
294: if (columnIndex < 0) {
295: this.columnKeys.add(columnKey);
296: }
297: }
298:
299:
305: public void removeValue(Comparable rowKey, Comparable columnKey) {
306: setValue(null, rowKey, columnKey);
307:
308:
309: boolean allNull = true;
310: int rowIndex = getRowIndex(rowKey);
311: DefaultKeyedValues row = (DefaultKeyedValues) this.rows.get(rowIndex);
312:
313: for (int item = 0, itemCount = row.getItemCount(); item < itemCount;
314: item++) {
315: if (row.getValue(item) != null) {
316: allNull = false;
317: break;
318: }
319: }
320:
321: if (allNull) {
322: this.rowKeys.remove(rowIndex);
323: this.rows.remove(rowIndex);
324: }
325:
326:
327: allNull = true;
328: int columnIndex = getColumnIndex(columnKey);
329:
330: for (int item = 0, itemCount = this.rows.size(); item < itemCount;
331: item++) {
332: row = (DefaultKeyedValues) this.rows.get(item);
333: if (row.getValue(columnIndex) != null) {
334: allNull = false;
335: break;
336: }
337: }
338:
339: if (allNull) {
340: for (int item = 0, itemCount = this.rows.size(); item < itemCount;
341: item++) {
342: row = (DefaultKeyedValues) this.rows.get(item);
343: row.removeValue(columnIndex);
344: }
345: this.columnKeys.remove(columnIndex);
346: }
347: }
348:
349:
354: public void removeRow(int rowIndex) {
355: this.rowKeys.remove(rowIndex);
356: this.rows.remove(rowIndex);
357: }
358:
359:
364: public void removeRow(Comparable rowKey) {
365: removeRow(getRowIndex(rowKey));
366: }
367:
368:
373: public void removeColumn(int columnIndex) {
374: Comparable columnKey = getColumnKey(columnIndex);
375: removeColumn(columnKey);
376: }
377:
378:
383: public void removeColumn(Comparable columnKey) {
384: Iterator iterator = this.rows.iterator();
385: while (iterator.hasNext()) {
386: DefaultKeyedValues rowData = (DefaultKeyedValues) iterator.next();
387: rowData.removeValue(columnKey);
388: }
389: this.columnKeys.remove(columnKey);
390: }
391:
392:
395: public void clear() {
396: this.rowKeys.clear();
397: this.columnKeys.clear();
398: this.rows.clear();
399: }
400:
401:
408: public boolean equals(Object o) {
409:
410: if (o == null) {
411: return false;
412: }
413: if (o == this) {
414: return true;
415: }
416:
417: if (!(o instanceof KeyedValues2D)) {
418: return false;
419: }
420: KeyedValues2D kv2D = (KeyedValues2D) o;
421: if (!getRowKeys().equals(kv2D.getRowKeys())) {
422: return false;
423: }
424: if (!getColumnKeys().equals(kv2D.getColumnKeys())) {
425: return false;
426: }
427: int rowCount = getRowCount();
428: if (rowCount != kv2D.getRowCount()) {
429: return false;
430: }
431:
432: int colCount = getColumnCount();
433: if (colCount != kv2D.getColumnCount()) {
434: return false;
435: }
436:
437: for (int r = 0; r < rowCount; r++) {
438: for (int c = 0; c < colCount; c++) {
439: Number v1 = getValue(r, c);
440: Number v2 = kv2D.getValue(r, c);
441: if (v1 == null) {
442: if (v2 != null) {
443: return false;
444: }
445: }
446: else {
447: if (!v1.equals(v2)) {
448: return false;
449: }
450: }
451: }
452: }
453: return true;
454: }
455:
456:
461: public int hashCode() {
462: int result;
463: result = this.rowKeys.hashCode();
464: result = 29 * result + this.columnKeys.hashCode();
465: result = 29 * result + this.rows.hashCode();
466: return result;
467: }
468:
469:
477: public Object clone() throws CloneNotSupportedException {
478: DefaultKeyedValues2D clone = (DefaultKeyedValues2D) super.clone();
479:
480:
481: clone.columnKeys = new java.util.ArrayList(this.columnKeys);
482: clone.rowKeys = new java.util.ArrayList(this.rowKeys);
483:
484:
485: clone.rows = (List) ObjectUtilities.deepClone(this.rows);
486: return clone;
487: }
488:
489: }