package com.positive.charts.data.general;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import org.eclipse.core.runtime.ListenerList;
import com.positive.charts.event.SeriesChangeEvent;
import com.positive.charts.event.SeriesChangeListener;
/**
* Base class representing a data series. Subclasses are left to implement the
* actual data structures.
* <P>
* The series has two properties ("Key" and "Description") for which you can
* register a <code>PropertyChangeListener</code>.
* <P>
* You can also register a {@link SeriesChangeListener} to receive notification
* of changes to the series data.
*/
public abstract class Series implements Cloneable, Serializable {
/** For serialization. */
private static final long serialVersionUID = -6906561437538683581L;
/** The key for the series. */
private Comparable key;
/** A description of the series. */
private String description;
/** Storage for registered change listeners. <SeriesChangeListener> */
private final ListenerList listeners;
/** Object to support property change notification. */
private final PropertyChangeSupport propertyChangeSupport;
/** A flag that controls whether or not changes are notified. */
private boolean notify = true;
/**
* Creates a new series with the specified key.
*
* @param key
* the series key (<code>null</code> not permitted).
*/
protected Series(final Comparable key) {
this(key, null);
}
/**
* Creates a new series with the specified key and description.
*
* @param key
* the series key (<code>null</code> NOT permitted).
* @param description
* the series description (<code>null</code> permitted).
*/
protected Series(final Comparable key, final String description) {
if (key == null) {
throw new IllegalArgumentException("Null 'key' argument.");
}
this.key = key;
this.description = description;
this.listeners = new ListenerList();
this.propertyChangeSupport = new PropertyChangeSupport(this);
}
/**
* Registers an object with this series, to receive notification whenever
* the series changes.
* <P>
* Objects being registered must implement the {@link SeriesChangeListener}
* interface.
*
* @param listener
* the listener to register.
*/
public void addChangeListener(final SeriesChangeListener listener) {
this.listeners.add(listener);
}
/**
* Adds a property change listener to the series.
*
* @param listener
* the listener.
*/
public void addPropertyChangeListener(final PropertyChangeListener listener) {
this.propertyChangeSupport.addPropertyChangeListener(listener);
}
/**
* Fires a property change event.
*
* @param property
* the property key.
* @param oldValue
* the old value.
* @param newValue
* the new value.
*/
protected void firePropertyChange(final String property,
final Object oldValue, final Object newValue) {
this.propertyChangeSupport.firePropertyChange(property, oldValue,
newValue);
}
/**
* General method for signalling to registered listeners that the series has
* been changed.
*/
public void fireSeriesChanged() {
if (this.notify) {
this.notifyListeners(new SeriesChangeEvent(this));
}
}
/**
* Returns a description of the series.
*
* @return The series description (possibly <code>null</code>).
*
* @see #setDescription(String)
*/
public String getDescription() {
return this.description;
}
/**
* Returns the key for the series.
*
* @return The series key (never <code>null</code>).
*
* @see #setKey(Comparable)
*/
public Comparable getKey() {
return this.key;
}
/**
* Returns the flag that controls whether or not change events are sent to
* registered listeners.
*
* @return A boolean.
*
* @see #setNotify(boolean)
*/
public boolean getNotify() {
return this.notify;
}
/**
* Sends a change event to all registered listeners.
*
* @param event
* contains information about the event that triggered the
* notification.
*/
protected void notifyListeners(final SeriesChangeEvent event) {
final Object[] listeners = this.listeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
final SeriesChangeListener listener = (SeriesChangeListener) listeners[i];
listener.seriesChanged(event);
}
}
/**
* Deregisters an object, so that it not longer receives notification
* whenever the series changes.
*
* @param listener
* the listener to deregister.
*/
public void removeChangeListener(final SeriesChangeListener listener) {
this.listeners.remove(listener);
}
/**
* Removes a property change listener from the series.
*
* @param listener
* The listener.
*/
public void removePropertyChangeListener(
final PropertyChangeListener listener) {
this.propertyChangeSupport.removePropertyChangeListener(listener);
}
/**
* Sets the description of the series and sends a
* <code>PropertyChangeEvent</code> to all registered listeners.
*
* @param description
* the description (<code>null</code> permitted).
*
* @see #getDescription()
*/
public void setDescription(final String description) {
final String old = this.description;
this.description = description;
this.propertyChangeSupport.firePropertyChange("Description", old,
description);
}
/**
* Sets the key for the series and sends a <code>PropertyChangeEvent</code>
* (with the property name "Key") to all registered listeners.
*
* @param key
* the key (<code>null</code> not permitted).
*
* @see #getKey()
*/
public void setKey(final Comparable key) {
if (key == null) {
throw new IllegalArgumentException("Null 'key' argument.");
}
final Comparable old = this.key;
this.key = key;
this.propertyChangeSupport.firePropertyChange("Key", old, key);
}
/**
* Sets the flag that controls whether or not change events are sent to
* registered listeners.
*
* @param notify
* the new value of the flag.
*
* @see #getNotify()
*/
public void setNotify(final boolean notify) {
if (this.notify != notify) {
this.notify = notify;
this.fireSeriesChanged();
}
}
}