Source for org.jfree.data.KeyedObjects2D

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
   6:  *
   7:  * Project Info:  http://www.jfree.org/jfreechart/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  *
  27:  * ------------------
  28:  * KeyedObject2D.java
  29:  * ------------------
  30:  * (C) Copyright 2003-2005, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * $Id: KeyedObjects2D.java,v 1.6.2.1 2005/10/25 21:29:13 mungady Exp $
  36:  *
  37:  * Changes
  38:  * -------
  39:  * 05-Feb-2003 : Version 1 (DG);
  40:  * 01-Mar-2004 : Added equals() and clone() methods and implemented 
  41:  *               Serializable (DG);
  42:  *
  43:  */
  44: 
  45: package org.jfree.data;
  46: 
  47: import java.io.Serializable;
  48: import java.util.Collections;
  49: import java.util.Iterator;
  50: import java.util.List;
  51: 
  52: 
  53: /**
  54:  * A data structure that stores zero, one or many objects, where each object is
  55:  * associated with two keys (a 'row' key and a 'column' key).
  56:  */
  57: public class KeyedObjects2D implements Cloneable, Serializable {
  58: 
  59:     /** For serialization. */
  60:     private static final long serialVersionUID = -1015873563138522374L;
  61:     
  62:     /** The row keys. */
  63:     private List rowKeys;
  64: 
  65:     /** The column keys. */
  66:     private List columnKeys;
  67: 
  68:     /** The row data. */
  69:     private List rows;
  70: 
  71:     /**
  72:      * Creates a new instance (initially empty).
  73:      */
  74:     public KeyedObjects2D() {
  75:         this.rowKeys = new java.util.ArrayList();
  76:         this.columnKeys = new java.util.ArrayList();
  77:         this.rows = new java.util.ArrayList();
  78:     }
  79: 
  80:     /**
  81:      * Returns the row count.
  82:      *
  83:      * @return The row count.
  84:      */
  85:     public int getRowCount() {
  86:         return this.rowKeys.size();
  87:     }
  88: 
  89:     /**
  90:      * Returns the column count.
  91:      *
  92:      * @return The column count.
  93:      */
  94:     public int getColumnCount() {
  95:         return this.columnKeys.size();
  96:     }
  97: 
  98:     /**
  99:      * Returns the object for a given row and column.
 100:      *
 101:      * @param row  the row index.
 102:      * @param column  the column index.
 103:      *
 104:      * @return The object.
 105:      */
 106:     public Object getObject(int row, int column) {
 107: 
 108:         Object result = null;
 109:         KeyedObjects rowData = (KeyedObjects) this.rows.get(row);
 110:         if (rowData != null) {
 111:             Comparable columnKey = (Comparable) this.columnKeys.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, 
 210:                           Comparable rowKey, 
 211:                           Comparable columnKey) {
 212:         setObject(object, rowKey, columnKey);
 213:     }
 214: 
 215:     /**
 216:      * Adds or updates an object.
 217:      *
 218:      * @param object  the object.
 219:      * @param rowKey  the row key.
 220:      * @param columnKey  the column key.
 221:      */
 222:     public void setObject(Object object, 
 223:                           Comparable rowKey, 
 224:                           Comparable columnKey) {
 225: 
 226:         KeyedObjects row;
 227:         int rowIndex = this.rowKeys.indexOf(rowKey);
 228:         if (rowIndex >= 0) {
 229:             row = (KeyedObjects) this.rows.get(rowIndex);
 230:         }
 231:         else {
 232:             this.rowKeys.add(rowKey);
 233:             row = new KeyedObjects();
 234:             this.rows.add(row);
 235:         }
 236:         row.setObject(columnKey, object);
 237:         int columnIndex = this.columnKeys.indexOf(columnKey);
 238:         if (columnIndex < 0) {
 239:             this.columnKeys.add(columnKey);
 240:         }
 241: 
 242:     }
 243: 
 244:     /**
 245:      * Removes an object.
 246:      *
 247:      * @param rowKey  the row key.
 248:      * @param columnKey  the column key.
 249:      */
 250:     public void removeObject(Comparable rowKey, Comparable columnKey) {
 251:         setObject(null, rowKey, columnKey);
 252:         // actually, a null value is different to a value that doesn't exist 
 253:         // at all, need to fix this code.
 254:     }
 255: 
 256:     /**
 257:      * Removes a row.
 258:      *
 259:      * @param rowIndex  the row index.
 260:      */
 261:     public void removeRow(int rowIndex) {
 262:         this.rowKeys.remove(rowIndex);
 263:         this.rows.remove(rowIndex);
 264:     }
 265: 
 266:     /**
 267:      * Removes a row.
 268:      *
 269:      * @param rowKey  the row key.
 270:      */
 271:     public void removeRow(Comparable rowKey) {
 272:         removeRow(getRowIndex(rowKey));
 273:     }
 274: 
 275:     /**
 276:      * Removes a column.
 277:      *
 278:      * @param columnIndex  the column index.
 279:      */
 280:     public void removeColumn(int columnIndex) {
 281:         Comparable columnKey = getColumnKey(columnIndex);
 282:         removeColumn(columnKey);
 283:     }
 284: 
 285:     /**
 286:      * Removes a column.
 287:      *
 288:      * @param columnKey  the column key.
 289:      */
 290:     public void removeColumn(Comparable columnKey) {
 291:         Iterator iterator = this.rows.iterator();
 292:         while (iterator.hasNext()) {
 293:             KeyedObjects rowData = (KeyedObjects) iterator.next();
 294:             rowData.removeValue(columnKey);
 295:         }
 296:         this.columnKeys.remove(columnKey);
 297:     }
 298: 
 299:     /**
 300:      * Tests this object for equality with an arbitrary object.
 301:      *
 302:      * @param obj  the object to test (<code>null</code> permitted).
 303:      *
 304:      * @return A boolean.
 305:      */
 306:     public boolean equals(Object obj) {
 307: 
 308:         if (obj == null) {
 309:             return false;
 310:         }
 311:         
 312:         if (obj == this) {
 313:             return true;
 314:         }
 315: 
 316:         if (!(obj instanceof KeyedObjects2D)) {
 317:             return false;
 318:         }
 319:         
 320:         KeyedObjects2D ko2D = (KeyedObjects2D) obj;
 321:         if (!getRowKeys().equals(ko2D.getRowKeys())) {
 322:             return false;
 323:         }
 324:         if (!getColumnKeys().equals(ko2D.getColumnKeys())) {
 325:             return false;
 326:         }
 327:         int rowCount = getRowCount();
 328:         if (rowCount != ko2D.getRowCount()) {
 329:             return false;
 330:         }
 331: 
 332:         int colCount = getColumnCount();
 333:         if (colCount != ko2D.getColumnCount()) {
 334:             return false;
 335:         }
 336: 
 337:         for (int r = 0; r < rowCount; r++) {
 338:             for (int c = 0; c < colCount; c++) {
 339:                 Object v1 = getObject(r, c);
 340:                 Object v2 = ko2D.getObject(r, c);
 341:                 if (v1 == null) {
 342:                     if (v2 != null) {
 343:                         return false;
 344:                     }
 345:                 }
 346:                 else {
 347:                     if (!v1.equals(v2)) {
 348:                         return false;
 349:                     }
 350:                 }
 351:             }
 352:         }
 353:         return true;
 354:     }
 355: 
 356:     /**
 357:      * Returns a hashcode for this object.
 358:      * 
 359:      * @return A hashcode.
 360:      */
 361:     public int hashCode() {
 362:         int result;
 363:         result = this.rowKeys.hashCode();
 364:         result = 29 * result + this.columnKeys.hashCode();
 365:         result = 29 * result + this.rows.hashCode();
 366:         return result;
 367:     }
 368: 
 369:     /**
 370:      * Returns a clone.
 371:      * 
 372:      * @return A clone.
 373:      * 
 374:      * @throws CloneNotSupportedException  this class will not throw this 
 375:      *         exception, but subclasses (if any) might.
 376:      */
 377:     public Object clone() throws CloneNotSupportedException {
 378:         return super.clone();
 379:     }
 380: 
 381: }