001: /* ===========================================================
002: * JFreeChart : a free chart library for the Java(tm) platform
003: * ===========================================================
004: *
005: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006: *
007: * Project Info: http://www.jfree.org/jfreechart/index.html
008: *
009: * This library is free software; you can redistribute it and/or modify it
010: * under the terms of the GNU Lesser General Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but
015: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017: * License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022: * USA.
023: *
024: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025: * in the United States and other countries.]
026: *
027: * ------------------
028: * KeyedObject2D.java
029: * ------------------
030: * (C) Copyright 2003-2005, by Object Refinery Limited.
031: *
032: * Original Author: David Gilbert (for Object Refinery Limited);
033: * Contributor(s): -;
034: *
035: * $Id: KeyedObjects2D.java,v 1.6.2.1 2005/10/25 21:29:13 mungady Exp $
036: *
037: * Changes
038: * -------
039: * 05-Feb-2003 : Version 1 (DG);
040: * 01-Mar-2004 : Added equals() and clone() methods and implemented
041: * Serializable (DG);
042: *
043: */
044:
045: package org.jfree.data;
046:
047: import java.io.Serializable;
048: import java.util.Collections;
049: import java.util.Iterator;
050: import java.util.List;
051:
052: /**
053: * A data structure that stores zero, one or many objects, where each object is
054: * associated with two keys (a 'row' key and a 'column' key).
055: */
056: public class KeyedObjects2D implements Cloneable, Serializable {
057:
058: /** For serialization. */
059: private static final long serialVersionUID = -1015873563138522374L;
060:
061: /** The row keys. */
062: private List rowKeys;
063:
064: /** The column keys. */
065: private List columnKeys;
066:
067: /** The row data. */
068: private List rows;
069:
070: /**
071: * Creates a new instance (initially empty).
072: */
073: public KeyedObjects2D() {
074: this .rowKeys = new java.util.ArrayList();
075: this .columnKeys = new java.util.ArrayList();
076: this .rows = new java.util.ArrayList();
077: }
078:
079: /**
080: * Returns the row count.
081: *
082: * @return The row count.
083: */
084: public int getRowCount() {
085: return this .rowKeys.size();
086: }
087:
088: /**
089: * Returns the column count.
090: *
091: * @return The column count.
092: */
093: public int getColumnCount() {
094: return this .columnKeys.size();
095: }
096:
097: /**
098: * Returns the object for a given row and column.
099: *
100: * @param row the row index.
101: * @param column the column index.
102: *
103: * @return The object.
104: */
105: public Object getObject(int row, int column) {
106:
107: Object result = null;
108: KeyedObjects rowData = (KeyedObjects) this .rows.get(row);
109: if (rowData != null) {
110: Comparable columnKey = (Comparable) this .columnKeys
111: .get(column);
112: if (columnKey != null) {
113: result = rowData.getObject(columnKey);
114: }
115: }
116: return result;
117:
118: }
119:
120: /**
121: * Returns the key for a given row.
122: *
123: * @param row the row index (zero based).
124: *
125: * @return The row index.
126: */
127: public Comparable getRowKey(int row) {
128: return (Comparable) this .rowKeys.get(row);
129: }
130:
131: /**
132: * Returns the row index for a given key.
133: *
134: * @param key the key.
135: *
136: * @return The row index.
137: */
138: public int getRowIndex(Comparable key) {
139: return this .rowKeys.indexOf(key);
140: }
141:
142: /**
143: * Returns the row keys.
144: *
145: * @return The row keys (never <code>null</code>).
146: */
147: public List getRowKeys() {
148: return Collections.unmodifiableList(this .rowKeys);
149: }
150:
151: /**
152: * Returns the key for a given column.
153: *
154: * @param column the column.
155: *
156: * @return The key.
157: */
158: public Comparable getColumnKey(int column) {
159: return (Comparable) this .columnKeys.get(column);
160: }
161:
162: /**
163: * Returns the column index for a given key.
164: *
165: * @param key the key.
166: *
167: * @return The column index.
168: */
169: public int getColumnIndex(Comparable key) {
170: return this .columnKeys.indexOf(key);
171: }
172:
173: /**
174: * Returns the column keys.
175: *
176: * @return The column keys (never <code>null</code>).
177: */
178: public List getColumnKeys() {
179: return Collections.unmodifiableList(this .columnKeys);
180: }
181:
182: /**
183: * Returns the object for the given row and column keys.
184: *
185: * @param rowKey the row key.
186: * @param columnKey the column key.
187: *
188: * @return The object.
189: */
190: public Object getObject(Comparable rowKey, Comparable columnKey) {
191:
192: Object result = null;
193: int row = this .rowKeys.indexOf(rowKey);
194: if (row >= 0) {
195: KeyedObjects rowData = (KeyedObjects) this .rows.get(row);
196: result = rowData.getObject(columnKey);
197: }
198: return result;
199:
200: }
201:
202: /**
203: * Adds an object to the table. Performs the same function as setObject().
204: *
205: * @param object the object.
206: * @param rowKey the row key.
207: * @param columnKey the column key.
208: */
209: public void addObject(Object object, Comparable rowKey,
210: Comparable columnKey) {
211: setObject(object, rowKey, columnKey);
212: }
213:
214: /**
215: * Adds or updates an object.
216: *
217: * @param object the object.
218: * @param rowKey the row key.
219: * @param columnKey the column key.
220: */
221: public void setObject(Object object, Comparable rowKey,
222: Comparable columnKey) {
223:
224: KeyedObjects row;
225: int rowIndex = this .rowKeys.indexOf(rowKey);
226: if (rowIndex >= 0) {
227: row = (KeyedObjects) this .rows.get(rowIndex);
228: } else {
229: this .rowKeys.add(rowKey);
230: row = new KeyedObjects();
231: this .rows.add(row);
232: }
233: row.setObject(columnKey, object);
234: int columnIndex = this .columnKeys.indexOf(columnKey);
235: if (columnIndex < 0) {
236: this .columnKeys.add(columnKey);
237: }
238:
239: }
240:
241: /**
242: * Removes an object.
243: *
244: * @param rowKey the row key.
245: * @param columnKey the column key.
246: */
247: public void removeObject(Comparable rowKey, Comparable columnKey) {
248: setObject(null, rowKey, columnKey);
249: // actually, a null value is different to a value that doesn't exist
250: // at all, need to fix this code.
251: }
252:
253: /**
254: * Removes a row.
255: *
256: * @param rowIndex the row index.
257: */
258: public void removeRow(int rowIndex) {
259: this .rowKeys.remove(rowIndex);
260: this .rows.remove(rowIndex);
261: }
262:
263: /**
264: * Removes a row.
265: *
266: * @param rowKey the row key.
267: */
268: public void removeRow(Comparable rowKey) {
269: removeRow(getRowIndex(rowKey));
270: }
271:
272: /**
273: * Removes a column.
274: *
275: * @param columnIndex the column index.
276: */
277: public void removeColumn(int columnIndex) {
278: Comparable columnKey = getColumnKey(columnIndex);
279: removeColumn(columnKey);
280: }
281:
282: /**
283: * Removes a column.
284: *
285: * @param columnKey the column key.
286: */
287: public void removeColumn(Comparable columnKey) {
288: Iterator iterator = this .rows.iterator();
289: while (iterator.hasNext()) {
290: KeyedObjects rowData = (KeyedObjects) iterator.next();
291: rowData.removeValue(columnKey);
292: }
293: this .columnKeys.remove(columnKey);
294: }
295:
296: /**
297: * Tests this object for equality with an arbitrary object.
298: *
299: * @param obj the object to test (<code>null</code> permitted).
300: *
301: * @return A boolean.
302: */
303: public boolean equals(Object obj) {
304:
305: if (obj == null) {
306: return false;
307: }
308:
309: if (obj == this ) {
310: return true;
311: }
312:
313: if (!(obj instanceof KeyedObjects2D)) {
314: return false;
315: }
316:
317: KeyedObjects2D ko2D = (KeyedObjects2D) obj;
318: if (!getRowKeys().equals(ko2D.getRowKeys())) {
319: return false;
320: }
321: if (!getColumnKeys().equals(ko2D.getColumnKeys())) {
322: return false;
323: }
324: int rowCount = getRowCount();
325: if (rowCount != ko2D.getRowCount()) {
326: return false;
327: }
328:
329: int colCount = getColumnCount();
330: if (colCount != ko2D.getColumnCount()) {
331: return false;
332: }
333:
334: for (int r = 0; r < rowCount; r++) {
335: for (int c = 0; c < colCount; c++) {
336: Object v1 = getObject(r, c);
337: Object v2 = ko2D.getObject(r, c);
338: if (v1 == null) {
339: if (v2 != null) {
340: return false;
341: }
342: } else {
343: if (!v1.equals(v2)) {
344: return false;
345: }
346: }
347: }
348: }
349: return true;
350: }
351:
352: /**
353: * Returns a hashcode for this object.
354: *
355: * @return A hashcode.
356: */
357: public int hashCode() {
358: int result;
359: result = this .rowKeys.hashCode();
360: result = 29 * result + this .columnKeys.hashCode();
361: result = 29 * result + this .rows.hashCode();
362: return result;
363: }
364:
365: /**
366: * Returns a clone.
367: *
368: * @return A clone.
369: *
370: * @throws CloneNotSupportedException this class will not throw this
371: * exception, but subclasses (if any) might.
372: */
373: public Object clone() throws CloneNotSupportedException {
374: return super.clone();
375: }
376:
377: }
|