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: * AbstractDataset.java 29: * -------------------- 30: * (C)opyright 2000-2006, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): Nicolas Brodu (for Astrium and EADS Corporate Research 34: * Center); 35: * 36: * $Id: AbstractDataset.java,v 1.5.2.2 2006/07/26 12:14:20 mungady Exp $ 37: * 38: * Changes (from 21-Aug-2001) 39: * -------------------------- 40: * 21-Aug-2001 : Added standard header. Fixed DOS encoding problem (DG); 41: * 18-Sep-2001 : Updated e-mail address in header (DG); 42: * 15-Oct-2001 : Moved to new package (com.jrefinery.data.*) (DG); 43: * 22-Oct-2001 : Renamed DataSource.java --> Dataset.java etc. (DG); 44: * 17-Nov-2001 : Changed constructor from public to protected, created new 45: * AbstractSeriesDataset class and transferred series-related 46: * methods, updated Javadoc comments (DG); 47: * 04-Mar-2002 : Updated import statements (DG); 48: * 11-Jun-2002 : Updated for change in the event constructor (DG); 49: * 07-Aug-2002 : Changed listener list to use 50: * javax.swing.event.EventListenerList (DG); 51: * 04-Oct-2002 : Fixed errors reported by Checkstyle (DG); 52: * 27-Mar-2003 : Implemented Serializable (DG); 53: * 18-Aug-2003 : Implemented Cloneable (DG); 54: * 08-Sep-2003 : Serialization fixes (NB); 55: * 11-Sep-2003 : Cloning Fixes (NB); 56: * 01-Jun-2005 : Added hasListener() method for unit testing (DG); 57: * 58: */ 59: 60: package org.jfree.data.general; 61: 62: import java.io.IOException; 63: import java.io.InvalidObjectException; 64: import java.io.ObjectInputStream; 65: import java.io.ObjectInputValidation; 66: import java.io.ObjectOutputStream; 67: import java.io.Serializable; 68: import java.util.Arrays; 69: import java.util.EventListener; 70: import java.util.List; 71: 72: import javax.swing.event.EventListenerList; 73: 74: /** 75: * An abstract implementation of the {@link Dataset} interface, containing a 76: * mechanism for registering change listeners. 77: */ 78: public abstract class AbstractDataset implements Dataset, 79: Cloneable, 80: Serializable, 81: ObjectInputValidation { 82: 83: /** For serialization. */ 84: private static final long serialVersionUID = 1918768939869230744L; 85: 86: /** The group that the dataset belongs to. */ 87: private DatasetGroup group; 88: 89: /** Storage for registered change listeners. */ 90: private transient EventListenerList listenerList; 91: 92: /** 93: * Constructs a dataset. By default, the dataset is assigned to its own 94: * group. 95: */ 96: protected AbstractDataset() { 97: this.group = new DatasetGroup(); 98: this.listenerList = new EventListenerList(); 99: } 100: 101: /** 102: * Returns the dataset group for the dataset. 103: * 104: * @return The group. 105: */ 106: public DatasetGroup getGroup() { 107: return this.group; 108: } 109: 110: /** 111: * Sets the dataset group for the dataset. 112: * 113: * @param group the group (<code>null</code> not permitted). 114: */ 115: public void setGroup(DatasetGroup group) { 116: if (group == null) { 117: throw new IllegalArgumentException("Null 'group' argument."); 118: } 119: this.group = group; 120: } 121: 122: /** 123: * Registers an object to receive notification of changes to the dataset. 124: * 125: * @param listener the object to register. 126: */ 127: public void addChangeListener(DatasetChangeListener listener) { 128: this.listenerList.add(DatasetChangeListener.class, listener); 129: } 130: 131: /** 132: * Deregisters an object so that it no longer receives notification of 133: * changes to the dataset. 134: * 135: * @param listener the object to deregister. 136: */ 137: public void removeChangeListener(DatasetChangeListener listener) { 138: this.listenerList.remove(DatasetChangeListener.class, listener); 139: } 140: 141: /** 142: * Returns <code>true</code> if the specified object is registered with 143: * the dataset as a listener. Most applications won't need to call this 144: * method, it exists mainly for use by unit testing code. 145: * 146: * @param listener the listener. 147: * 148: * @return A boolean. 149: */ 150: public boolean hasListener(EventListener listener) { 151: List list = Arrays.asList(this.listenerList.getListenerList()); 152: return list.contains(listener); 153: } 154: 155: /** 156: * Notifies all registered listeners that the dataset has changed. 157: */ 158: protected void fireDatasetChanged() { 159: notifyListeners(new DatasetChangeEvent(this, this)); 160: } 161: 162: /** 163: * Notifies all registered listeners that the dataset has changed. 164: * 165: * @param event contains information about the event that triggered the 166: * notification. 167: */ 168: protected void notifyListeners(DatasetChangeEvent event) { 169: 170: Object[] listeners = this.listenerList.getListenerList(); 171: for (int i = listeners.length - 2; i >= 0; i -= 2) { 172: if (listeners[i] == DatasetChangeListener.class) { 173: ((DatasetChangeListener) listeners[i + 1]).datasetChanged( 174: event 175: ); 176: } 177: } 178: 179: } 180: 181: /** 182: * Returns a clone of the dataset. The cloned dataset will NOT include the 183: * {@link DatasetChangeListener} references that have been registered with 184: * this dataset. 185: * 186: * @return A clone. 187: * 188: * @throws CloneNotSupportedException if the dataset does not support 189: * cloning. 190: */ 191: public Object clone() throws CloneNotSupportedException { 192: AbstractDataset clone = (AbstractDataset) super.clone(); 193: clone.listenerList = new EventListenerList(); 194: return clone; 195: } 196: 197: /** 198: * Handles serialization. 199: * 200: * @param stream the output stream. 201: * 202: * @throws IOException if there is an I/O problem. 203: */ 204: private void writeObject(ObjectOutputStream stream) throws IOException { 205: stream.defaultWriteObject(); 206: } 207: 208: /** 209: * Restores a serialized object. 210: * 211: * @param stream the input stream. 212: * 213: * @throws IOException if there is an I/O problem. 214: * @throws ClassNotFoundException if there is a problem loading a class. 215: */ 216: private void readObject(ObjectInputStream stream) 217: throws IOException, ClassNotFoundException { 218: stream.defaultReadObject(); 219: this.listenerList = new EventListenerList(); 220: stream.registerValidation(this, 10); // see comments about priority of 221: // 10 in validateObject() 222: } 223: 224: /** 225: * Validates the object. We use this opportunity to call listeners who have 226: * registered during the deserialization process, as listeners are not 227: * serialized. This method is called by the serialization system after the 228: * entire graph is read. 229: * 230: * This object has registered itself to the system with a priority of 10. 231: * Other callbacks may register with a higher priority number to be called 232: * before this object, or with a lower priority number to be called after 233: * the listeners were notified. 234: * 235: * All listeners are supposed to have register by now, either in their 236: * readObject or validateObject methods. Notify them that this dataset has 237: * changed. 238: * 239: * @exception InvalidObjectException If the object cannot validate itself. 240: */ 241: public void validateObject() throws InvalidObjectException { 242: fireDatasetChanged(); 243: } 244: 245: }