Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2007, 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: * KeyedObjects.java 29: * ----------------- 30: * (C) Copyright 2003-2007, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * Changes: 36: * -------- 37: * 31-Oct-2002 : Version 1 (DG); 38: * 11-Jan-2005 : Minor tidy up (DG); 39: * 28-Sep-2007 : Clean up equals() method (DG); 40: * 03-Oct-2007 : Make method behaviour consistent with DefaultKeyedValues (DG); 41: * 42: */ 43: 44: package org.jfree.data; 45: 46: import java.io.Serializable; 47: import java.util.Iterator; 48: import java.util.List; 49: 50: import org.jfree.util.PublicCloneable; 51: 52: /** 53: * A collection of (key, object) pairs. 54: */ 55: public class KeyedObjects implements Cloneable, PublicCloneable, Serializable { 56: 57: /** For serialization. */ 58: private static final long serialVersionUID = 1321582394193530984L; 59: 60: /** Storage for the data. */ 61: private List data; 62: 63: /** 64: * Creates a new collection (initially empty). 65: */ 66: public KeyedObjects() { 67: this.data = new java.util.ArrayList(); 68: } 69: 70: /** 71: * Returns the number of items (values) in the collection. 72: * 73: * @return The item count. 74: */ 75: public int getItemCount() { 76: return this.data.size(); 77: } 78: 79: /** 80: * Returns an object from the list. 81: * 82: * @param item the item index (zero-based). 83: * 84: * @return The object (possibly <code>null</code>). 85: * 86: * @throws IndexOutOfBoundsException if <code>item</code> is out of bounds. 87: */ 88: public Object getObject(int item) { 89: Object result = null; 90: KeyedObject kobj = (KeyedObject) this.data.get(item); 91: if (kobj != null) { 92: result = kobj.getObject(); 93: } 94: return result; 95: } 96: 97: /** 98: * Returns the key at the specified position in the list. 99: * 100: * @param index the item index (zero-based). 101: * 102: * @return The row key. 103: * 104: * @throws IndexOutOfBoundsException if <code>item</code> is out of bounds. 105: * 106: * @see #getIndex(Comparable) 107: */ 108: public Comparable getKey(int index) { 109: Comparable result = null; 110: KeyedObject item = (KeyedObject) this.data.get(index); 111: if (item != null) { 112: result = item.getKey(); 113: } 114: return result; 115: } 116: 117: /** 118: * Returns the index for a given key, or <code>-1</code>. 119: * 120: * @param key the key (<code>null</code> not permitted). 121: * 122: * @return The index, or <code>-1</code> if the key is unrecognised. 123: * 124: * @see #getKey(int) 125: */ 126: public int getIndex(Comparable key) { 127: if (key == null) { 128: throw new IllegalArgumentException("Null 'key' argument."); 129: } 130: int i = 0; 131: Iterator iterator = this.data.iterator(); 132: while (iterator.hasNext()) { 133: KeyedObject ko = (KeyedObject) iterator.next(); 134: if (ko.getKey().equals(key)) { 135: return i; 136: } 137: i++; 138: } 139: return -1; 140: } 141: 142: /** 143: * Returns a list containing all the keys in the list. 144: * 145: * @return The keys (never <code>null</code>). 146: */ 147: public List getKeys() { 148: List result = new java.util.ArrayList(); 149: Iterator iterator = this.data.iterator(); 150: while (iterator.hasNext()) { 151: KeyedObject ko = (KeyedObject) iterator.next(); 152: result.add(ko.getKey()); 153: } 154: return result; 155: } 156: 157: /** 158: * Returns the object for a given key. If the key is not recognised, the 159: * method should return <code>null</code>. 160: * 161: * @param key the key. 162: * 163: * @return The object (possibly <code>null</code>). 164: * 165: * @see #addObject(Comparable, Object) 166: */ 167: public Object getObject(Comparable key) { 168: int index = getIndex(key); 169: if (index < 0) { 170: throw new UnknownKeyException("The key (" + key 171: + ") is not recognised."); 172: } 173: return getObject(index); 174: } 175: 176: /** 177: * Adds a new object to the collection, or overwrites an existing object. 178: * This is the same as the {@link #setObject(Comparable, Object)} method. 179: * 180: * @param key the key. 181: * @param object the object. 182: * 183: * @see #getObject(Comparable) 184: */ 185: public void addObject(Comparable key, Object object) { 186: setObject(key, object); 187: } 188: 189: /** 190: * Replaces an existing object, or adds a new object to the collection. 191: * This is the same as the {@link #addObject(Comparable, Object)} 192: * method. 193: * 194: * @param key the key (<code>null</code> not permitted). 195: * @param object the object. 196: * 197: * @see #getObject(Comparable) 198: */ 199: public void setObject(Comparable key, Object object) { 200: int keyIndex = getIndex(key); 201: if (keyIndex >= 0) { 202: KeyedObject ko = (KeyedObject) this.data.get(keyIndex); 203: ko.setObject(object); 204: } 205: else { 206: KeyedObject ko = new KeyedObject(key, object); 207: this.data.add(ko); 208: } 209: } 210: 211: /** 212: * Inserts a new value at the specified position in the dataset or, if 213: * there is an existing item with the specified key, updates the value 214: * for that item and moves it to the specified position. 215: * 216: * @param position the position (in the range <code>0</code> to 217: * <code>getItemCount()</code>). 218: * @param key the key (<code>null</code> not permitted). 219: * @param value the value (<code>null</code> permitted). 220: * 221: * @since 1.0.7 222: */ 223: public void insertValue(int position, Comparable key, Object value) { 224: if (position < 0 || position > this.data.size()) { 225: throw new IllegalArgumentException("'position' out of bounds."); 226: } 227: if (key == null) { 228: throw new IllegalArgumentException("Null 'key' argument."); 229: } 230: int pos = getIndex(key); 231: if (pos >= 0) { 232: this.data.remove(pos); 233: } 234: KeyedObject item = new KeyedObject(key, value); 235: if (position <= this.data.size()) { 236: this.data.add(position, item); 237: } 238: else { 239: this.data.add(item); 240: } 241: } 242: 243: /** 244: * Removes a value from the collection. 245: * 246: * @param index the index of the item to remove. 247: * 248: * @see #removeValue(Comparable) 249: */ 250: public void removeValue(int index) { 251: this.data.remove(index); 252: } 253: 254: /** 255: * Removes a value from the collection. 256: * 257: * @param key the key (<code>null</code> not permitted). 258: * 259: * @see #removeValue(int) 260: * 261: * @throws UnknownKeyException if the key is not recognised. 262: */ 263: public void removeValue(Comparable key) { 264: // defer argument checking 265: int index = getIndex(key); 266: if (index < 0) { 267: throw new UnknownKeyException("The key (" + key.toString() 268: + ") is not recognised."); 269: } 270: removeValue(index); 271: } 272: 273: /** 274: * Clears all values from the collection. 275: * 276: * @since 1.0.7 277: */ 278: public void clear() { 279: this.data.clear(); 280: } 281: 282: /** 283: * Returns a clone of this object. Keys in the list should be immutable 284: * and are not cloned. Objects in the list are cloned only if they 285: * implement {@link PublicCloneable}. 286: * 287: * @return A clone. 288: * 289: * @throws CloneNotSupportedException if there is a problem cloning. 290: */ 291: public Object clone() throws CloneNotSupportedException { 292: KeyedObjects clone = (KeyedObjects) super.clone(); 293: clone.data = new java.util.ArrayList(); 294: Iterator iterator = this.data.iterator(); 295: while (iterator.hasNext()) { 296: KeyedObject ko = (KeyedObject) iterator.next(); 297: clone.data.add(ko.clone()); 298: } 299: return clone; 300: } 301: 302: /** 303: * Tests this object for equality with an arbitrary object. 304: * 305: * @param obj the object (<code>null</code> permitted). 306: * 307: * @return A boolean. 308: */ 309: public boolean equals(Object obj) { 310: 311: if (obj == this) { 312: return true; 313: } 314: if (!(obj instanceof KeyedObjects)) { 315: return false; 316: } 317: KeyedObjects that = (KeyedObjects) obj; 318: int count = getItemCount(); 319: if (count != that.getItemCount()) { 320: return false; 321: } 322: 323: for (int i = 0; i < count; i++) { 324: Comparable k1 = getKey(i); 325: Comparable k2 = that.getKey(i); 326: if (!k1.equals(k2)) { 327: return false; 328: } 329: Object o1 = getObject(i); 330: Object o2 = that.getObject(i); 331: if (o1 == null) { 332: if (o2 != null) { 333: return false; 334: } 335: } 336: else { 337: if (!o1.equals(o2)) { 338: return false; 339: } 340: } 341: } 342: return true; 343: 344: } 345: 346: /** 347: * Returns a hash code. 348: * 349: * @return A hash code. 350: */ 351: public int hashCode() { 352: return (this.data != null ? this.data.hashCode() : 0); 353: } 354: 355: }