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: * DefaultPieDataset.java 29: * ---------------------- 30: * (C) Copyright 2001-2007, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): Sam (oldman); 34: * 35: * Changes 36: * ------- 37: * 17-Nov-2001 : Version 1 (DG); 38: * 22-Jan-2002 : Removed legend methods from dataset implementations (DG); 39: * 07-Apr-2002 : Modified implementation to guarantee data sequence to remain 40: * in the order categories are added (oldman); 41: * 23-Oct-2002 : Added getCategory(int) method and getItemCount() method, in 42: * line with changes to the PieDataset interface (DG); 43: * 04-Feb-2003 : Changed underlying data storage to DefaultKeyedValues (DG); 44: * 04-Mar-2003 : Inserted DefaultKeyedValuesDataset class into hierarchy (DG); 45: * 24-Apr-2003 : Switched places with DefaultKeyedValuesDataset (DG); 46: * 18-Aug-2003 : Implemented Cloneable (DG); 47: * 03-Mar-2005 : Implemented PublicCloneable (DG); 48: * 29-Jun-2005 : Added remove() method (DG); 49: * ------------- JFREECHART 1.0.0 --------------------------------------------- 50: * 31-Jul-2006 : Added a clear() method to clear all values from the 51: * dataset (DG); 52: * 28-Sep-2006 : Added sortByKeys() and sortByValues() methods (DG); 53: * 30-Apr-2007 : Added new insertValues() methods (DG); 54: * 55: */ 56: 57: package org.jfree.data.general; 58: 59: import java.io.Serializable; 60: import java.util.Collections; 61: import java.util.List; 62: 63: import org.jfree.data.DefaultKeyedValues; 64: import org.jfree.data.KeyedValues; 65: import org.jfree.data.UnknownKeyException; 66: import org.jfree.util.PublicCloneable; 67: import org.jfree.util.SortOrder; 68: 69: /** 70: * A default implementation of the {@link PieDataset} interface. 71: */ 72: public class DefaultPieDataset extends AbstractDataset 73: implements PieDataset, 74: Cloneable, PublicCloneable, 75: Serializable { 76: 77: /** For serialization. */ 78: private static final long serialVersionUID = 2904745139106540618L; 79: 80: /** Storage for the data. */ 81: private DefaultKeyedValues data; 82: 83: /** 84: * Constructs a new dataset, initially empty. 85: */ 86: public DefaultPieDataset() { 87: this.data = new DefaultKeyedValues(); 88: } 89: 90: /** 91: * Creates a new dataset by copying data from a {@link KeyedValues} 92: * instance. 93: * 94: * @param data the data (<code>null</code> not permitted). 95: */ 96: public DefaultPieDataset(KeyedValues data) { 97: if (data == null) { 98: throw new IllegalArgumentException("Null 'data' argument."); 99: } 100: this.data = new DefaultKeyedValues(); 101: for (int i = 0; i < data.getItemCount(); i++) { 102: this.data.addValue(data.getKey(i), data.getValue(i)); 103: } 104: } 105: 106: /** 107: * Returns the number of items in the dataset. 108: * 109: * @return The item count. 110: */ 111: public int getItemCount() { 112: return this.data.getItemCount(); 113: } 114: 115: /** 116: * Returns the categories in the dataset. The returned list is 117: * unmodifiable. 118: * 119: * @return The categories in the dataset. 120: */ 121: public List getKeys() { 122: return Collections.unmodifiableList(this.data.getKeys()); 123: } 124: 125: /** 126: * Returns the key for the specified item, or <code>null</code>. 127: * 128: * @param item the item index (in the range <code>0</code> to 129: * <code>getItemCount() - 1</code>). 130: * 131: * @return The key, or <code>null</code>. 132: * 133: * @throws IndexOutOfBoundsException if <code>item</code> is not in the 134: * specified range. 135: */ 136: public Comparable getKey(int item) { 137: return this.data.getKey(item); 138: } 139: 140: /** 141: * Returns the index for a key, or -1 if the key is not recognised. 142: * 143: * @param key the key (<code>null</code> not permitted). 144: * 145: * @return The index, or <code>-1</code> if the key is unrecognised. 146: * 147: * @throws IllegalArgumentException if <code>key</code> is 148: * <code>null</code>. 149: */ 150: public int getIndex(Comparable key) { 151: return this.data.getIndex(key); 152: } 153: 154: /** 155: * Returns a value. 156: * 157: * @param item the value index. 158: * 159: * @return The value (possibly <code>null</code>). 160: */ 161: public Number getValue(int item) { 162: 163: Number result = null; 164: if (getItemCount() > item) { 165: result = this.data.getValue(item); 166: } 167: return result; 168: 169: } 170: 171: /** 172: * Returns the data value associated with a key. 173: * 174: * @param key the key (<code>null</code> not permitted). 175: * 176: * @return The value (possibly <code>null</code>). 177: * 178: * @throws UnknownKeyException if the key is not recognised. 179: */ 180: public Number getValue(Comparable key) { 181: if (key == null) { 182: throw new IllegalArgumentException("Null 'key' argument."); 183: } 184: return this.data.getValue(key); 185: } 186: 187: /** 188: * Sets the data value for a key and sends a {@link DatasetChangeEvent} to 189: * all registered listeners. 190: * 191: * @param key the key (<code>null</code> not permitted). 192: * @param value the value. 193: * 194: * @throws IllegalArgumentException if <code>key</code> is 195: * <code>null</code>. 196: */ 197: public void setValue(Comparable key, Number value) { 198: this.data.setValue(key, value); 199: fireDatasetChanged(); 200: } 201: 202: /** 203: * Sets the data value for a key and sends a {@link DatasetChangeEvent} to 204: * all registered listeners. 205: * 206: * @param key the key (<code>null</code> not permitted). 207: * @param value the value. 208: * 209: * @throws IllegalArgumentException if <code>key</code> is 210: * <code>null</code>. 211: */ 212: public void setValue(Comparable key, double value) { 213: setValue(key, new Double(value)); 214: } 215: 216: /** 217: * Inserts a new value at the specified position in the dataset or, if 218: * there is an existing item with the specified key, updates the value 219: * for that item and moves it to the specified position. After the change 220: * is made, this methods sends a {@link DatasetChangeEvent} to all 221: * registered listeners. 222: * 223: * @param position the position (in the range 0 to getItemCount()). 224: * @param key the key (<code>null</code> not permitted). 225: * @param value the value (<code>null</code> permitted). 226: * 227: * @since 1.0.6 228: */ 229: public void insertValue(int position, Comparable key, double value) { 230: insertValue(position, key, new Double(value)); 231: } 232: 233: /** 234: * Inserts a new value at the specified position in the dataset or, if 235: * there is an existing item with the specified key, updates the value 236: * for that item and moves it to the specified position. After the change 237: * is made, this methods sends a {@link DatasetChangeEvent} to all 238: * registered listeners. 239: * 240: * @param position the position (in the range 0 to getItemCount()). 241: * @param key the key (<code>null</code> not permitted). 242: * @param value the value (<code>null</code> permitted). 243: * 244: * @since 1.0.6 245: */ 246: public void insertValue(int position, Comparable key, Number value) { 247: this.data.insertValue(position, key, value); 248: fireDatasetChanged(); 249: } 250: 251: /** 252: * Removes an item from the dataset and sends a {@link DatasetChangeEvent} 253: * to all registered listeners. 254: * 255: * @param key the key (<code>null</code> not permitted). 256: * 257: * @throws IllegalArgumentException if <code>key</code> is 258: * <code>null</code>. 259: */ 260: public void remove(Comparable key) { 261: this.data.removeValue(key); 262: fireDatasetChanged(); 263: } 264: 265: /** 266: * Clears all data from this dataset and sends a {@link DatasetChangeEvent} 267: * to all registered listeners (unless the dataset was already empty). 268: * 269: * @since 1.0.2 270: */ 271: public void clear() { 272: if (getItemCount() > 0) { 273: this.data.clear(); 274: fireDatasetChanged(); 275: } 276: } 277: 278: /** 279: * Sorts the dataset's items by key and sends a {@link DatasetChangeEvent} 280: * to all registered listeners. 281: * 282: * @param order the sort order (<code>null</code> not permitted). 283: * 284: * @since 1.0.3 285: */ 286: public void sortByKeys(SortOrder order) { 287: this.data.sortByKeys(order); 288: fireDatasetChanged(); 289: } 290: 291: /** 292: * Sorts the dataset's items by value and sends a {@link DatasetChangeEvent} 293: * to all registered listeners. 294: * 295: * @param order the sort order (<code>null</code> not permitted). 296: * 297: * @since 1.0.3 298: */ 299: public void sortByValues(SortOrder order) { 300: this.data.sortByValues(order); 301: fireDatasetChanged(); 302: } 303: 304: /** 305: * Tests if this object is equal to another. 306: * 307: * @param obj the other object. 308: * 309: * @return A boolean. 310: */ 311: public boolean equals(Object obj) { 312: if (obj == this) { 313: return true; 314: } 315: 316: if (!(obj instanceof PieDataset)) { 317: return false; 318: } 319: PieDataset that = (PieDataset) obj; 320: int count = getItemCount(); 321: if (that.getItemCount() != count) { 322: return false; 323: } 324: 325: for (int i = 0; i < count; i++) { 326: Comparable k1 = getKey(i); 327: Comparable k2 = that.getKey(i); 328: if (!k1.equals(k2)) { 329: return false; 330: } 331: 332: Number v1 = getValue(i); 333: Number v2 = that.getValue(i); 334: if (v1 == null) { 335: if (v2 != null) { 336: return false; 337: } 338: } 339: else { 340: if (!v1.equals(v2)) { 341: return false; 342: } 343: } 344: } 345: return true; 346: 347: } 348: 349: /** 350: * Returns a hash code. 351: * 352: * @return A hash code. 353: */ 354: public int hashCode() { 355: return this.data.hashCode(); 356: } 357: 358: /** 359: * Returns a clone of the dataset. 360: * 361: * @return A clone. 362: * 363: * @throws CloneNotSupportedException This class will not throw this 364: * exception, but subclasses (if any) might. 365: */ 366: public Object clone() throws CloneNotSupportedException { 367: DefaultPieDataset clone = (DefaultPieDataset) super.clone(); 368: clone.data = (DefaultKeyedValues) this.data.clone(); 369: return clone; 370: } 371: 372: }