001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2013, 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-2013, 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     * @throws IllegalArgumentException
113     */
114    public MatrixSeries getSeries(int seriesIndex) {
115        if ((seriesIndex < 0) || (seriesIndex > getSeriesCount())) {
116            throw new IllegalArgumentException("Index outside valid range.");
117        }
118        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
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    @Override
129    public int getSeriesCount() {
130        return this.seriesList.size();
131    }
132
133
134    /**
135     * Returns the key for a series.
136     *
137     * @param seriesIndex zero-based series index.
138     *
139     * @return The key for a series.
140     */
141    @Override
142    public Comparable getSeriesKey(int seriesIndex) {
143        return getSeries(seriesIndex).getKey();
144    }
145
146
147    /**
148     * Returns the j index value of the specified Mij matrix item in the
149     * specified matrix series.
150     *
151     * @param seriesIndex zero-based series index.
152     * @param itemIndex zero-based item index.
153     *
154     * @return The j index value for the specified matrix item.
155     *
156     * @see org.jfree.data.xy.XYDataset#getXValue(int, int)
157     */
158    @Override
159    public Number getX(int seriesIndex, int itemIndex) {
160        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
161        int x = series.getItemColumn(itemIndex);
162
163        return new Integer(x); // I know it's bad to create object. better idea?
164    }
165
166
167    /**
168     * Returns the i index value of the specified Mij matrix item in the
169     * specified matrix series.
170     *
171     * @param seriesIndex zero-based series index.
172     * @param itemIndex zero-based item index.
173     *
174     * @return The i index value for the specified matrix item.
175     *
176     * @see org.jfree.data.xy.XYDataset#getYValue(int, int)
177     */
178    @Override
179    public Number getY(int seriesIndex, int itemIndex) {
180        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
181        int y = series.getItemRow(itemIndex);
182
183        return new Integer(y); // I know it's bad to create object. better idea?
184    }
185
186
187    /**
188     * Returns the Mij item value of the specified Mij matrix item in the
189     * specified matrix series.
190     *
191     * @param seriesIndex the series (zero-based index).
192     * @param itemIndex zero-based item index.
193     *
194     * @return The Mij item value for the specified matrix item.
195     *
196     * @see org.jfree.data.xy.XYZDataset#getZValue(int, int)
197     */
198    @Override
199    public Number getZ(int seriesIndex, int itemIndex) {
200        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
201        Number z = series.getItem(itemIndex);
202        return z;
203    }
204
205
206    /**
207     * Adds a series to the collection.
208     * <P>
209     * Notifies all registered listeners that the dataset has changed.
210     * </p>
211     *
212     * @param series the series (<code>null</code> not permitted).
213     */
214    public void addSeries(MatrixSeries series) {
215        ParamChecks.nullNotPermitted(series, "series");
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    @Override
233    public boolean equals(Object obj) {
234        if (obj == null) {
235            return false;
236        }
237
238        if (obj == this) {
239            return true;
240        }
241
242        if (obj instanceof MatrixSeriesCollection) {
243            MatrixSeriesCollection c = (MatrixSeriesCollection) obj;
244
245            return ObjectUtilities.equal(this.seriesList, c.seriesList);
246        }
247
248        return false;
249    }
250
251    /**
252     * Returns a hash code.
253     *
254     * @return A hash code.
255     */
256    @Override
257    public int hashCode() {
258        return (this.seriesList != null ? this.seriesList.hashCode() : 0);
259    }
260
261    /**
262     * Returns a clone of this instance.
263     *
264     * @return A clone.
265     *
266     * @throws CloneNotSupportedException if there is a problem.
267     */
268    @Override
269    public Object clone() throws CloneNotSupportedException {
270        MatrixSeriesCollection clone = (MatrixSeriesCollection) super.clone();
271        clone.seriesList = (List) ObjectUtilities.deepClone(this.seriesList);
272        return clone;
273    }
274
275    /**
276     * Removes all the series from the collection.
277     * <P>
278     * Notifies all registered listeners that the dataset has changed.
279     * </p>
280     */
281    public void removeAllSeries() {
282        // Unregister the collection as a change listener to each series in
283        // the collection.
284        for (int i = 0; i < this.seriesList.size(); i++) {
285            MatrixSeries series = (MatrixSeries) this.seriesList.get(i);
286            series.removeChangeListener(this);
287        }
288
289        // Remove all the series from the collection and notify listeners.
290        this.seriesList.clear();
291        fireDatasetChanged();
292    }
293
294
295    /**
296     * Removes a series from the collection.
297     * <P>
298     * Notifies all registered listeners that the dataset has changed.
299     * </p>
300     *
301     * @param series the series (<code>null</code>).
302     */
303    public void removeSeries(MatrixSeries series) {
304        ParamChecks.nullNotPermitted(series, "series");
305        if (this.seriesList.contains(series)) {
306            series.removeChangeListener(this);
307            this.seriesList.remove(series);
308            fireDatasetChanged();
309        }
310    }
311
312
313    /**
314     * Removes a series from the collection.
315     * <P>
316     * Notifies all registered listeners that the dataset has changed.
317     *
318     * @param seriesIndex the series (zero based index).
319     *
320     * @throws IllegalArgumentException
321     */
322    public void removeSeries(int seriesIndex) {
323        // check arguments...
324        if ((seriesIndex < 0) || (seriesIndex > getSeriesCount())) {
325            throw new IllegalArgumentException("Index outside valid range.");
326        }
327
328        // fetch the series, remove the change listener, then remove the series.
329        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
330        series.removeChangeListener(this);
331        this.seriesList.remove(seriesIndex);
332        fireDatasetChanged();
333    }
334
335}