package com.positive.charts.data.general;
import java.io.InvalidObjectException;
import java.io.ObjectInputValidation;
import org.eclipse.core.runtime.ListenerList;
import com.positive.charts.event.DatasetChangeEvent;
import com.positive.charts.event.DatasetChangeListener;
/**
* An abstract implementation of the {@link Dataset} interface, containing a
* mechanism for registering change listeners.
*/
public abstract class AbstractDataset implements Dataset, Cloneable,
ObjectInputValidation {
/** The group that the dataset belongs to. */
private DatasetGroup group;
/** Storage for registered change listeners. <DatasetChangeListener> */
private transient final ListenerList listenerList;
/**
* Constructs a dataset. By default, the dataset is assigned to its own
* group.
*/
protected AbstractDataset() {
this.group = new DatasetGroup();
this.listenerList = new ListenerList();
}
/**
* Registers an object to receive notification of changes to the dataset.
*
* @param listener
* the object to register.
*/
public void addChangeListener(final DatasetChangeListener listener) {
this.listenerList.add(listener);
}
/**
* Notifies all registered listeners that the dataset has changed.
*/
protected void fireDatasetChanged() {
this.notifyListeners(new DatasetChangeEvent(this, this));
}
/**
* Returns the dataset group for the dataset.
*
* @return The group.
*/
public DatasetGroup getGroup() {
return this.group;
}
/**
* Returns <code>true</code> if the specified object is registered with the
* dataset as a listener. Most applications won't need to call this method,
* it exists mainly for use by unit testing code.
*
* @param listener
* the listener.
*
* @return A boolean.
*/
public boolean hasListener(final DatasetChangeListener listener) {
// return listenerList.contains(listener);
// FIXME Implement some kind of ListenerList#contains()
return false;
}
/**
* Notifies all registered listeners that the dataset has changed.
*
* @param event
* contains information about the event that triggered the
* notification.
*/
protected void notifyListeners(final DatasetChangeEvent event) {
final Object[] listeners = this.listenerList.getListeners();
for (int i = 0; i < listeners.length; i++) {
final DatasetChangeListener listener = (DatasetChangeListener) listeners[i];
listener.datasetChanged(event);
}
}
/**
* Deregisters an object so that it no longer receives notification of
* changes to the dataset.
*
* @param listener
* the object to deregister.
*/
public void removeChangeListener(final DatasetChangeListener listener) {
this.listenerList.remove(listener);
}
/**
* Sets the dataset group for the dataset.
*
* @param group
* the group (<code>null</code> not permitted).
*/
public void setGroup(final DatasetGroup group) {
if (group == null) {
throw new IllegalArgumentException("Null 'group' argument.");
}
this.group = group;
}
/**
* Validates the object. We use this opportunity to call listeners who have
* registered during the deserialization process, as listeners are not
* serialized. This method is called by the serialization system after the
* entire graph is read.
*
* This object has registered itself to the system with a priority of 10.
* Other callbacks may register with a higher priority number to be called
* before this object, or with a lower priority number to be called after
* the listeners were notified.
*
* All listeners are supposed to have register by now, either in their
* readObject or validateObject methods. Notify them that this dataset has
* changed.
*
* @exception InvalidObjectException
* If the object cannot validate itself.
*/
public void validateObject() throws InvalidObjectException {
this.fireDatasetChanged();
}
}