Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2006, 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: * Series.java 29: * ----------- 30: * (C) Copyright 2001-2006, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * $Id: Series.java,v 1.9.2.3 2006/07/25 15:55:48 mungady Exp $ 36: * 37: * Changes 38: * ------- 39: * 15-Nov-2001 : Version 1 (DG); 40: * 29-Nov-2001 : Added cloning and property change support (DG); 41: * 30-Jan-2002 : Added a description attribute and changed the constructors to 42: * protected (DG); 43: * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG); 44: * 13-Mar-2003 : Implemented Serializable (DG); 45: * 01-May-2003 : Added equals() method (DG); 46: * 26-Jun-2003 : Changed listener list to use EventListenerList - see bug 47: * 757027 (DG); 48: * 15-Oct-2003 : Added a flag to control whether or not change events are sent 49: * to registered listeners (DG); 50: * 19-May-2005 : Made abstract (DG); 51: * ------------- JFREECHART 1.0.0 --------------------------------------------- 52: * 04-May-2006 : Updated API docs (DG); 53: * 54: */ 55: 56: package org.jfree.data.general; 57: 58: import java.beans.PropertyChangeListener; 59: import java.beans.PropertyChangeSupport; 60: import java.io.Serializable; 61: 62: import javax.swing.event.EventListenerList; 63: 64: import org.jfree.util.ObjectUtilities; 65: 66: /** 67: * Base class representing a data series. Subclasses are left to implement the 68: * actual data structures. 69: * <P> 70: * The series has two properties ("Key" and "Description") for which you can 71: * register a <code>PropertyChangeListener</code>. 72: * <P> 73: * You can also register a {@link SeriesChangeListener} to receive notification 74: * of changes to the series data. 75: */ 76: public abstract class Series implements Cloneable, Serializable { 77: 78: /** For serialization. */ 79: private static final long serialVersionUID = -6906561437538683581L; 80: 81: /** The key for the series. */ 82: private Comparable key; 83: 84: /** A description of the series. */ 85: private String description; 86: 87: /** Storage for registered change listeners. */ 88: private EventListenerList listeners; 89: 90: /** Object to support property change notification. */ 91: private PropertyChangeSupport propertyChangeSupport; 92: 93: /** A flag that controls whether or not changes are notified. */ 94: private boolean notify; 95: 96: /** 97: * Creates a new series with the specified key. 98: * 99: * @param key the series key (<code>null</code> not permitted). 100: */ 101: protected Series(Comparable key) { 102: this(key, null); 103: } 104: 105: /** 106: * Creates a new series with the specified key and description. 107: * 108: * @param key the series key (<code>null</code> NOT permitted). 109: * @param description the series description (<code>null</code> permitted). 110: */ 111: protected Series(Comparable key, String description) { 112: if (key == null) { 113: throw new IllegalArgumentException("Null 'key' argument."); 114: } 115: this.key = key; 116: this.description = description; 117: this.listeners = new EventListenerList(); 118: this.propertyChangeSupport = new PropertyChangeSupport(this); 119: this.notify = true; 120: } 121: 122: /** 123: * Returns the key for the series. 124: * 125: * @return The series key (never <code>null</code>). 126: * 127: * @see #setKey(Comparable) 128: */ 129: public Comparable getKey() { 130: return this.key; 131: } 132: 133: /** 134: * Sets the key for the series and sends a <code>PropertyChangeEvent</code> 135: * (with the property name "Key") to all registered listeners. 136: * 137: * @param key the key (<code>null</code> not permitted). 138: * 139: * @see #getKey() 140: */ 141: public void setKey(Comparable key) { 142: if (key == null) { 143: throw new IllegalArgumentException("Null 'key' argument."); 144: } 145: Comparable old = this.key; 146: this.key = key; 147: this.propertyChangeSupport.firePropertyChange("Key", old, key); 148: } 149: 150: /** 151: * Returns a description of the series. 152: * 153: * @return The series description (possibly <code>null</code>). 154: * 155: * @see #setDescription(String) 156: */ 157: public String getDescription() { 158: return this.description; 159: } 160: 161: /** 162: * Sets the description of the series and sends a 163: * <code>PropertyChangeEvent</code> to all registered listeners. 164: * 165: * @param description the description (<code>null</code> permitted). 166: * 167: * @see #getDescription() 168: */ 169: public void setDescription(String description) { 170: String old = this.description; 171: this.description = description; 172: this.propertyChangeSupport.firePropertyChange("Description", old, 173: description); 174: } 175: 176: /** 177: * Returns the flag that controls whether or not change events are sent to 178: * registered listeners. 179: * 180: * @return A boolean. 181: * 182: * @see #setNotify(boolean) 183: */ 184: public boolean getNotify() { 185: return this.notify; 186: } 187: 188: /** 189: * Sets the flag that controls whether or not change events are sent to 190: * registered listeners. 191: * 192: * @param notify the new value of the flag. 193: * 194: * @see #getNotify() 195: */ 196: public void setNotify(boolean notify) { 197: if (this.notify != notify) { 198: this.notify = notify; 199: fireSeriesChanged(); 200: } 201: } 202: 203: /** 204: * Returns a clone of the series. 205: * <P> 206: * Notes: 207: * <ul> 208: * <li>No need to clone the name or description, since String object is 209: * immutable.</li> 210: * <li>We set the listener list to empty, since the listeners did not 211: * register with the clone.</li> 212: * <li>Same applies to the PropertyChangeSupport instance.</li> 213: * </ul> 214: * 215: * @return A clone of the series. 216: * 217: * @throws CloneNotSupportedException not thrown by this class, but 218: * subclasses may differ. 219: */ 220: public Object clone() throws CloneNotSupportedException { 221: 222: Series clone = (Series) super.clone(); 223: clone.listeners = new EventListenerList(); 224: clone.propertyChangeSupport = new PropertyChangeSupport(clone); 225: return clone; 226: 227: } 228: 229: /** 230: * Tests the series for equality with another object. 231: * 232: * @param obj the object (<code>null</code> permitted). 233: * 234: * @return <code>true</code> or <code>false</code>. 235: */ 236: public boolean equals(Object obj) { 237: if (obj == this) { 238: return true; 239: } 240: if (!(obj instanceof Series)) { 241: return false; 242: } 243: Series that = (Series) obj; 244: if (!getKey().equals(that.getKey())) { 245: return false; 246: } 247: if (!ObjectUtilities.equal(getDescription(), that.getDescription())) { 248: return false; 249: } 250: return true; 251: } 252: 253: /** 254: * Returns a hash code. 255: * 256: * @return A hash code. 257: */ 258: public int hashCode() { 259: int result; 260: result = this.key.hashCode(); 261: result = 29 * result + (this.description != null 262: ? this.description.hashCode() : 0); 263: return result; 264: } 265: 266: /** 267: * Registers an object with this series, to receive notification whenever 268: * the series changes. 269: * <P> 270: * Objects being registered must implement the {@link SeriesChangeListener} 271: * interface. 272: * 273: * @param listener the listener to register. 274: */ 275: public void addChangeListener(SeriesChangeListener listener) { 276: this.listeners.add(SeriesChangeListener.class, listener); 277: } 278: 279: /** 280: * Deregisters an object, so that it not longer receives notification 281: * whenever the series changes. 282: * 283: * @param listener the listener to deregister. 284: */ 285: public void removeChangeListener(SeriesChangeListener listener) { 286: this.listeners.remove(SeriesChangeListener.class, listener); 287: } 288: 289: /** 290: * General method for signalling to registered listeners that the series 291: * has been changed. 292: */ 293: public void fireSeriesChanged() { 294: if (this.notify) { 295: notifyListeners(new SeriesChangeEvent(this)); 296: } 297: } 298: 299: /** 300: * Sends a change event to all registered listeners. 301: * 302: * @param event contains information about the event that triggered the 303: * notification. 304: */ 305: protected void notifyListeners(SeriesChangeEvent event) { 306: 307: Object[] listenerList = this.listeners.getListenerList(); 308: for (int i = listenerList.length - 2; i >= 0; i -= 2) { 309: if (listenerList[i] == SeriesChangeListener.class) { 310: ((SeriesChangeListener) listenerList[i + 1]).seriesChanged( 311: event); 312: } 313: } 314: 315: } 316: 317: /** 318: * Adds a property change listener to the series. 319: * 320: * @param listener the listener. 321: */ 322: public void addPropertyChangeListener(PropertyChangeListener listener) { 323: this.propertyChangeSupport.addPropertyChangeListener(listener); 324: } 325: 326: /** 327: * Removes a property change listener from the series. 328: * 329: * @param listener The listener. 330: */ 331: public void removePropertyChangeListener(PropertyChangeListener listener) { 332: this.propertyChangeSupport.removePropertyChangeListener(listener); 333: } 334: 335: /** 336: * Fires a property change event. 337: * 338: * @param property the property key. 339: * @param oldValue the old value. 340: * @param newValue the new value. 341: */ 342: protected void firePropertyChange(String property, Object oldValue, 343: Object newValue) { 344: this.propertyChangeSupport.firePropertyChange(property, oldValue, 345: newValue); 346: } 347: 348: }