001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2014, 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
025 * Other names may be trademarks of their respective owners.]
026 *
027 * ---------------------------
028 * MatrixSeriesCollection.java
029 * ---------------------------
030 * (C) Copyright 2003-2014, 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;
050import org.jfree.chart.util.ParamChecks;
051
052import org.jfree.util.ObjectUtilities;
053import org.jfree.util.PublicCloneable;
054
055/**
056 * Represents a collection of {@link MatrixSeries} that can be used as a
057 * dataset.
058 *
059 * @see org.jfree.data.xy.MatrixSeries
060 */
061public class MatrixSeriesCollection extends AbstractXYZDataset
062        implements XYZDataset, PublicCloneable, Serializable {
063
064    /** For serialization. */
065    private static final long serialVersionUID = -3197705779242543945L;
066
067    /** The series that are included in the collection. */
068    private List seriesList;
069
070    /**
071     * Constructs an empty dataset.
072     */
073    public MatrixSeriesCollection() {
074        this(null);
075    }
076
077
078    /**
079     * Constructs a dataset and populates it with a single matrix series.
080     *
081     * @param series the time series.
082     */
083    public MatrixSeriesCollection(MatrixSeries series) {
084        this.seriesList = new java.util.ArrayList();
085
086        if (series != null) {
087            this.seriesList.add(series);
088            series.addChangeListener(this);
089        }
090    }
091
092    /**
093     * Returns the number of items in the specified series.
094     *
095     * @param seriesIndex zero-based series index.
096     *
097     * @return The number of items in the specified series.
098     */
099    @Override
100    public int getItemCount(int seriesIndex) {
101        return getSeries(seriesIndex).getItemCount();
102    }
103
104
105    /**
106     * Returns the series having the specified index.
107     *
108     * @param seriesIndex zero-based series index.
109     *
110     * @return The series.
111     */
112    public MatrixSeries getSeries(int seriesIndex) {
113        if ((seriesIndex < 0) || (seriesIndex > getSeriesCount())) {
114            throw new IllegalArgumentException("Index outside valid range.");
115        }
116        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
117        return series;
118    }
119
120
121    /**
122     * Returns the number of series in the collection.
123     *
124     * @return The number of series in the collection.
125     */
126    @Override
127    public int getSeriesCount() {
128        return this.seriesList.size();
129    }
130
131
132    /**
133     * Returns the key for a series.
134     *
135     * @param seriesIndex zero-based series index.
136     *
137     * @return The key for a series.
138     */
139    @Override
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    @Override
157    public Number getX(int seriesIndex, int itemIndex) {
158        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
159        int x = series.getItemColumn(itemIndex);
160
161        return new Integer(x); // I know it's bad to create object. better idea?
162    }
163
164
165    /**
166     * Returns the i index value of the specified Mij matrix item in the
167     * specified matrix series.
168     *
169     * @param seriesIndex zero-based series index.
170     * @param itemIndex zero-based item index.
171     *
172     * @return The i index value for the specified matrix item.
173     *
174     * @see org.jfree.data.xy.XYDataset#getYValue(int, int)
175     */
176    @Override
177    public Number getY(int seriesIndex, int itemIndex) {
178        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
179        int y = series.getItemRow(itemIndex);
180
181        return new Integer(y); // I know it's bad to create object. better idea?
182    }
183
184
185    /**
186     * Returns the Mij item value of the specified Mij matrix item in the
187     * specified matrix series.
188     *
189     * @param seriesIndex the series (zero-based index).
190     * @param itemIndex zero-based item index.
191     *
192     * @return The Mij item value for the specified matrix item.
193     *
194     * @see org.jfree.data.xy.XYZDataset#getZValue(int, int)
195     */
196    @Override
197    public Number getZ(int seriesIndex, int itemIndex) {
198        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
199        Number z = series.getItem(itemIndex);
200        return z;
201    }
202
203
204    /**
205     * Adds a series to the collection.
206     * <P>
207     * Notifies all registered listeners that the dataset has changed.
208     * </p>
209     *
210     * @param series the series (<code>null</code> not permitted).
211     */
212    public void addSeries(MatrixSeries series) {
213        ParamChecks.nullNotPermitted(series, "series");
214        // FIXME: Check that there isn't already a series with the same key
215
216        // add the series...
217        this.seriesList.add(series);
218        series.addChangeListener(this);
219        fireDatasetChanged();
220    }
221
222
223    /**
224     * Tests this collection for equality with an arbitrary object.
225     *
226     * @param obj the object.
227     *
228     * @return A boolean.
229     */
230    @Override
231    public boolean equals(Object obj) {
232        if (obj == null) {
233            return false;
234        }
235
236        if (obj == this) {
237            return true;
238        }
239
240        if (obj instanceof MatrixSeriesCollection) {
241            MatrixSeriesCollection c = (MatrixSeriesCollection) obj;
242
243            return ObjectUtilities.equal(this.seriesList, c.seriesList);
244        }
245
246        return false;
247    }
248
249    /**
250     * Returns a hash code.
251     *
252     * @return A hash code.
253     */
254    @Override
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    @Override
267    public Object clone() throws CloneNotSupportedException {
268        MatrixSeriesCollection clone = (MatrixSeriesCollection) super.clone();
269        clone.seriesList = (List) ObjectUtilities.deepClone(this.seriesList);
270        return clone;
271    }
272
273    /**
274     * Removes all the series from the collection.
275     * <P>
276     * Notifies all registered listeners that the dataset has changed.
277     * </p>
278     */
279    public void removeAllSeries() {
280        // Unregister the collection as a change listener to each series in
281        // the collection.
282        for (int i = 0; i < this.seriesList.size(); i++) {
283            MatrixSeries series = (MatrixSeries) this.seriesList.get(i);
284            series.removeChangeListener(this);
285        }
286
287        // Remove all the series from the collection and notify listeners.
288        this.seriesList.clear();
289        fireDatasetChanged();
290    }
291
292
293    /**
294     * Removes a series from the collection.
295     * <P>
296     * Notifies all registered listeners that the dataset has changed.
297     * </p>
298     *
299     * @param series the series (<code>null</code>).
300     */
301    public void removeSeries(MatrixSeries series) {
302        ParamChecks.nullNotPermitted(series, "series");
303        if (this.seriesList.contains(series)) {
304            series.removeChangeListener(this);
305            this.seriesList.remove(series);
306            fireDatasetChanged();
307        }
308    }
309
310
311    /**
312     * Removes a series from the collection.
313     * <P>
314     * Notifies all registered listeners that the dataset has changed.
315     *
316     * @param seriesIndex the series (zero based index).
317     */
318    public void removeSeries(int seriesIndex) {
319        // check arguments...
320        if ((seriesIndex < 0) || (seriesIndex > getSeriesCount())) {
321            throw new IllegalArgumentException("Index outside valid range.");
322        }
323
324        // fetch the series, remove the change listener, then remove the series.
325        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
326        series.removeChangeListener(this);
327        this.seriesList.remove(seriesIndex);
328        fireDatasetChanged();
329    }
330
331}