001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
006 *
007 * Project Info:  http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022 * USA.
023 *
024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025 * in the United States and other countries.]
026 *
027 * ---------------------------
028 * MatrixSeriesCollection.java
029 * ---------------------------
030 * (C) Copyright 2003-2008, by Barak Naveh and Contributors.
031 *
032 * Original Author:  Barak Naveh;
033 * Contributor(s):   David Gilbert (for Object Refinery Limited);
034 *
035 * Changes
036 * -------
037 * 10-Jul-2003 : Version 1 contributed by Barak Naveh (DG);
038 * 05-May-2004 : Now extends AbstractXYZDataset (DG);
039 * 15-Jul-2004 : Switched getZ() and getZValue() methods (DG);
040 * ------------- JFREECHART 1.0.x ---------------------------------------------
041 * 27-Nov-2006 : Added clone() override (DG);
042 * 02-Feb-2007 : Removed author tags all over JFreeChart sources (DG);
043 * 22-Apr-2008 : Implemented PublicCloneable (DG);
044 */
045
046package org.jfree.data.xy;
047
048import java.io.Serializable;
049import java.util.List;
050
051import org.jfree.util.ObjectUtilities;
052import org.jfree.util.PublicCloneable;
053
054/**
055 * Represents a collection of {@link MatrixSeries} that can be used as a
056 * dataset.
057 *
058 * @see org.jfree.data.xy.MatrixSeries
059 */
060public class MatrixSeriesCollection extends AbstractXYZDataset
061        implements XYZDataset, PublicCloneable, Serializable {
062
063    /** For serialization. */
064    private static final long serialVersionUID = -3197705779242543945L;
065
066    /** The series that are included in the collection. */
067    private List seriesList;
068
069    /**
070     * Constructs an empty dataset.
071     */
072    public MatrixSeriesCollection() {
073        this(null);
074    }
075
076
077    /**
078     * Constructs a dataset and populates it with a single matrix series.
079     *
080     * @param series the time series.
081     */
082    public MatrixSeriesCollection(MatrixSeries series) {
083        this.seriesList = new java.util.ArrayList();
084
085        if (series != null) {
086            this.seriesList.add(series);
087            series.addChangeListener(this);
088        }
089    }
090
091    /**
092     * Returns the number of items in the specified series.
093     *
094     * @param seriesIndex zero-based series index.
095     *
096     * @return The number of items in the specified series.
097     */
098    public int getItemCount(int seriesIndex) {
099        return getSeries(seriesIndex).getItemCount();
100    }
101
102
103    /**
104     * Returns the series having the specified index.
105     *
106     * @param seriesIndex zero-based series index.
107     *
108     * @return The series.
109     *
110     * @throws IllegalArgumentException
111     */
112    public MatrixSeries getSeries(int seriesIndex) {
113        if ((seriesIndex < 0) || (seriesIndex > getSeriesCount())) {
114            throw new IllegalArgumentException("Index outside valid range.");
115        }
116
117        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
118
119        return series;
120    }
121
122
123    /**
124     * Returns the number of series in the collection.
125     *
126     * @return The number of series in the collection.
127     */
128    public int getSeriesCount() {
129        return this.seriesList.size();
130    }
131
132
133    /**
134     * Returns the key for a series.
135     *
136     * @param seriesIndex zero-based series index.
137     *
138     * @return The key for a series.
139     */
140    public Comparable getSeriesKey(int seriesIndex) {
141        return getSeries(seriesIndex).getKey();
142    }
143
144
145    /**
146     * Returns the j index value of the specified Mij matrix item in the
147     * specified matrix series.
148     *
149     * @param seriesIndex zero-based series index.
150     * @param itemIndex zero-based item index.
151     *
152     * @return The j index value for the specified matrix item.
153     *
154     * @see org.jfree.data.xy.XYDataset#getXValue(int, int)
155     */
156    public Number getX(int seriesIndex, int itemIndex) {
157        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
158        int x = series.getItemColumn(itemIndex);
159
160        return new Integer(x); // I know it's bad to create object. better idea?
161    }
162
163
164    /**
165     * Returns the i index value of the specified Mij matrix item in the
166     * specified matrix series.
167     *
168     * @param seriesIndex zero-based series index.
169     * @param itemIndex zero-based item index.
170     *
171     * @return The i index value for the specified matrix item.
172     *
173     * @see org.jfree.data.xy.XYDataset#getYValue(int, int)
174     */
175    public Number getY(int seriesIndex, int itemIndex) {
176        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
177        int y = series.getItemRow(itemIndex);
178
179        return new Integer(y); // I know it's bad to create object. better idea?
180    }
181
182
183    /**
184     * Returns the Mij item value of the specified Mij matrix item in the
185     * specified matrix series.
186     *
187     * @param seriesIndex the series (zero-based index).
188     * @param itemIndex zero-based item index.
189     *
190     * @return The Mij item value for the specified matrix item.
191     *
192     * @see org.jfree.data.xy.XYZDataset#getZValue(int, int)
193     */
194    public Number getZ(int seriesIndex, int itemIndex) {
195        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
196        Number z = series.getItem(itemIndex);
197        return z;
198    }
199
200
201    /**
202     * Adds a series to the collection.
203     * <P>
204     * Notifies all registered listeners that the dataset has changed.
205     * </p>
206     *
207     * @param series the series.
208     *
209     * @throws IllegalArgumentException
210     */
211    public void addSeries(MatrixSeries series) {
212        // check arguments...
213        if (series == null) {
214            throw new IllegalArgumentException("Cannot add null series.");
215        }
216        // FIXME: Check that there isn't already a series with the same key
217
218        // add the series...
219        this.seriesList.add(series);
220        series.addChangeListener(this);
221        fireDatasetChanged();
222    }
223
224
225    /**
226     * Tests this collection for equality with an arbitrary object.
227     *
228     * @param obj the object.
229     *
230     * @return A boolean.
231     */
232    public boolean equals(Object obj) {
233        if (obj == null) {
234            return false;
235        }
236
237        if (obj == this) {
238            return true;
239        }
240
241        if (obj instanceof MatrixSeriesCollection) {
242            MatrixSeriesCollection c = (MatrixSeriesCollection) obj;
243
244            return ObjectUtilities.equal(this.seriesList, c.seriesList);
245        }
246
247        return false;
248    }
249
250    /**
251     * Returns a hash code.
252     *
253     * @return A hash code.
254     */
255    public int hashCode() {
256        return (this.seriesList != null ? this.seriesList.hashCode() : 0);
257    }
258
259    /**
260     * Returns a clone of this instance.
261     *
262     * @return A clone.
263     *
264     * @throws CloneNotSupportedException if there is a problem.
265     */
266    public Object clone() throws CloneNotSupportedException {
267        MatrixSeriesCollection clone = (MatrixSeriesCollection) super.clone();
268        clone.seriesList = (List) ObjectUtilities.deepClone(this.seriesList);
269        return clone;
270    }
271
272    /**
273     * Removes all the series from the collection.
274     * <P>
275     * Notifies all registered listeners that the dataset has changed.
276     * </p>
277     */
278    public void removeAllSeries() {
279        // Unregister the collection as a change listener to each series in
280        // the collection.
281        for (int i = 0; i < this.seriesList.size(); i++) {
282            MatrixSeries series = (MatrixSeries) this.seriesList.get(i);
283            series.removeChangeListener(this);
284        }
285
286        // Remove all the series from the collection and notify listeners.
287        this.seriesList.clear();
288        fireDatasetChanged();
289    }
290
291
292    /**
293     * Removes a series from the collection.
294     * <P>
295     * Notifies all registered listeners that the dataset has changed.
296     * </p>
297     *
298     * @param series the series.
299     *
300     * @throws IllegalArgumentException
301     */
302    public void removeSeries(MatrixSeries series) {
303        // check arguments...
304        if (series == null) {
305            throw new IllegalArgumentException("Cannot remove null series.");
306        }
307
308        // remove the series...
309        if (this.seriesList.contains(series)) {
310            series.removeChangeListener(this);
311            this.seriesList.remove(series);
312            fireDatasetChanged();
313        }
314    }
315
316
317    /**
318     * Removes a series from the collection.
319     * <P>
320     * Notifies all registered listeners that the dataset has changed.
321     *
322     * @param seriesIndex the series (zero based index).
323     *
324     * @throws IllegalArgumentException
325     */
326    public void removeSeries(int seriesIndex) {
327        // check arguments...
328        if ((seriesIndex < 0) || (seriesIndex > getSeriesCount())) {
329            throw new IllegalArgumentException("Index outside valid range.");
330        }
331
332        // fetch the series, remove the change listener, then remove the series.
333        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
334        series.removeChangeListener(this);
335        this.seriesList.remove(seriesIndex);
336        fireDatasetChanged();
337    }
338
339}