Source for org.jfree.data.general.DefaultPieDataset

   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: }