001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2020, 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-2016, 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.ObjectUtils;
051import org.jfree.chart.util.Args;
052import org.jfree.chart.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    @Override
099    public int getItemCount(int seriesIndex) {
100        return getSeries(seriesIndex).getItemCount();
101    }
102
103
104    /**
105     * Returns the series having the specified index.
106     *
107     * @param seriesIndex zero-based series index.
108     *
109     * @return The series.
110     */
111    public MatrixSeries getSeries(int seriesIndex) {
112        if ((seriesIndex < 0) || (seriesIndex > getSeriesCount())) {
113            throw new IllegalArgumentException("Index outside valid range.");
114        }
115        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
116        return series;
117    }
118
119
120    /**
121     * Returns the number of series in the collection.
122     *
123     * @return The number of series in the collection.
124     */
125    @Override
126    public int getSeriesCount() {
127        return this.seriesList.size();
128    }
129
130
131    /**
132     * Returns the key for a series.
133     *
134     * @param seriesIndex zero-based series index.
135     *
136     * @return The key for a series.
137     */
138    @Override
139    public Comparable getSeriesKey(int seriesIndex) {
140        return getSeries(seriesIndex).getKey();
141    }
142
143
144    /**
145     * Returns the j index value of the specified Mij matrix item in the
146     * specified matrix series.
147     *
148     * @param seriesIndex zero-based series index.
149     * @param itemIndex zero-based item index.
150     *
151     * @return The j index value for the specified matrix item.
152     *
153     * @see org.jfree.data.xy.XYDataset#getXValue(int, int)
154     */
155    @Override
156    public Number getX(int seriesIndex, int itemIndex) {
157        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
158        return series.getItemColumn(itemIndex);
159    }
160
161
162    /**
163     * Returns the i index value of the specified Mij matrix item in the
164     * specified matrix series.
165     *
166     * @param seriesIndex zero-based series index.
167     * @param itemIndex zero-based item index.
168     *
169     * @return The i index value for the specified matrix item.
170     *
171     * @see org.jfree.data.xy.XYDataset#getYValue(int, int)
172     */
173    @Override
174    public Number getY(int seriesIndex, int itemIndex) {
175        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
176        int y = series.getItemRow(itemIndex);
177
178        return y; // I know it's bad to create object. better idea?
179    }
180
181
182    /**
183     * Returns the Mij item value of the specified Mij matrix item in the
184     * specified matrix series.
185     *
186     * @param seriesIndex the series (zero-based index).
187     * @param itemIndex zero-based item index.
188     *
189     * @return The Mij item value for the specified matrix item.
190     *
191     * @see org.jfree.data.xy.XYZDataset#getZValue(int, int)
192     */
193    @Override
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 ({@code null} not permitted).
208     */
209    public void addSeries(MatrixSeries series) {
210        Args.nullNotPermitted(series, "series");
211        // FIXME: Check that there isn't already a series with the same key
212
213        // add the series...
214        this.seriesList.add(series);
215        series.addChangeListener(this);
216        fireDatasetChanged();
217    }
218
219
220    /**
221     * Tests this collection for equality with an arbitrary object.
222     *
223     * @param obj the object.
224     *
225     * @return A boolean.
226     */
227    @Override
228    public boolean equals(Object obj) {
229        if (obj == null) {
230            return false;
231        }
232
233        if (obj == this) {
234            return true;
235        }
236
237        if (obj instanceof MatrixSeriesCollection) {
238            MatrixSeriesCollection c = (MatrixSeriesCollection) obj;
239
240            return ObjectUtils.equal(this.seriesList, c.seriesList);
241        }
242
243        return false;
244    }
245
246    /**
247     * Returns a hash code.
248     *
249     * @return A hash code.
250     */
251    @Override
252    public int hashCode() {
253        return (this.seriesList != null ? this.seriesList.hashCode() : 0);
254    }
255
256    /**
257     * Returns a clone of this instance.
258     *
259     * @return A clone.
260     *
261     * @throws CloneNotSupportedException if there is a problem.
262     */
263    @Override
264    public Object clone() throws CloneNotSupportedException {
265        MatrixSeriesCollection clone = (MatrixSeriesCollection) super.clone();
266        clone.seriesList = (List) ObjectUtils.deepClone(this.seriesList);
267        return clone;
268    }
269
270    /**
271     * Removes all the series from the collection.
272     * <P>
273     * Notifies all registered listeners that the dataset has changed.
274     * </p>
275     */
276    public void removeAllSeries() {
277        // Unregister the collection as a change listener to each series in
278        // the collection.
279        for (int i = 0; i < this.seriesList.size(); i++) {
280            MatrixSeries series = (MatrixSeries) this.seriesList.get(i);
281            series.removeChangeListener(this);
282        }
283
284        // Remove all the series from the collection and notify listeners.
285        this.seriesList.clear();
286        fireDatasetChanged();
287    }
288
289
290    /**
291     * Removes a series from the collection.
292     * <P>
293     * Notifies all registered listeners that the dataset has changed.
294     * </p>
295     *
296     * @param series the series ({@code null}).
297     */
298    public void removeSeries(MatrixSeries series) {
299        Args.nullNotPermitted(series, "series");
300        if (this.seriesList.contains(series)) {
301            series.removeChangeListener(this);
302            this.seriesList.remove(series);
303            fireDatasetChanged();
304        }
305    }
306
307
308    /**
309     * Removes a series from the collection.
310     * <P>
311     * Notifies all registered listeners that the dataset has changed.
312     *
313     * @param seriesIndex the series (zero based index).
314     */
315    public void removeSeries(int seriesIndex) {
316        // check arguments...
317        if ((seriesIndex < 0) || (seriesIndex > getSeriesCount())) {
318            throw new IllegalArgumentException("Index outside valid range.");
319        }
320
321        // fetch the series, remove the change listener, then remove the series.
322        MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
323        series.removeChangeListener(this);
324        this.seriesList.remove(seriesIndex);
325        fireDatasetChanged();
326    }
327
328}