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 * VectorSeriesCollection.java
029 * ---------------------------
030 * (C) Copyright 2007-2013, by Object Refinery Limited.
031 *
032 * Original Author:  David Gilbert (for Object Refinery Limited);
033 * Contributor(s):   -;
034 *
035 * Changes
036 * -------
037 * 30-Jan-2007 : Version 1 (DG);
038 * 24-May-2007 : Added indexOf(), removeSeries() and removeAllSeries()
039 *               methods (DG);
040 * 25-May-2007 : Moved from experimental to the main source tree (DG);
041 * 22-Apr-2008 : Implemented PublicCloneable (DG);
042 * 02-Jul-2013 : Use ParamChecks (DG);
043 *
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.data.general.DatasetChangeEvent;
053import org.jfree.util.ObjectUtilities;
054import org.jfree.util.PublicCloneable;
055
056/**
057 * A collection of {@link VectorSeries} objects.
058 *
059 * @since 1.0.6
060 */
061public class VectorSeriesCollection extends AbstractXYDataset
062        implements VectorXYDataset, PublicCloneable, Serializable {
063
064    /** Storage for the data series. */
065    private List data;
066
067    /**
068     * Creates a new instance of <code>VectorSeriesCollection</code>.
069     */
070    public VectorSeriesCollection() {
071        this.data = new java.util.ArrayList();
072    }
073
074    /**
075     * Adds a series to the collection and sends a {@link DatasetChangeEvent}
076     * to all registered listeners.
077     *
078     * @param series  the series (<code>null</code> not permitted).
079     */
080    public void addSeries(VectorSeries series) {
081        ParamChecks.nullNotPermitted(series, "series");
082        this.data.add(series);
083        series.addChangeListener(this);
084        fireDatasetChanged();
085    }
086
087    /**
088     * Removes the specified series from the collection and sends a
089     * {@link DatasetChangeEvent} to all registered listeners.
090     *
091     * @param series  the series (<code>null</code> not permitted).
092     *
093     * @return A boolean indicating whether the series has actually been
094     *         removed.
095     */
096    public boolean removeSeries(VectorSeries series) {
097        ParamChecks.nullNotPermitted(series, "series");
098        boolean removed = this.data.remove(series);
099        if (removed) {
100            series.removeChangeListener(this);
101            fireDatasetChanged();
102        }
103        return removed;
104    }
105
106    /**
107     * Removes all the series from the collection and sends a
108     * {@link DatasetChangeEvent} to all registered listeners.
109     */
110    public void removeAllSeries() {
111
112        // deregister the collection as a change listener to each series in the
113        // collection
114        for (int i = 0; i < this.data.size(); i++) {
115            VectorSeries series = (VectorSeries) this.data.get(i);
116            series.removeChangeListener(this);
117        }
118
119        // remove all the series from the collection and notify listeners.
120        this.data.clear();
121        fireDatasetChanged();
122
123    }
124
125    /**
126     * Returns the number of series in the collection.
127     *
128     * @return The series count.
129     */
130    @Override
131    public int getSeriesCount() {
132        return this.data.size();
133    }
134
135    /**
136     * Returns a series from the collection.
137     *
138     * @param series  the series index (zero-based).
139     *
140     * @return The series.
141     *
142     * @throws IllegalArgumentException if <code>series</code> is not in the
143     *     range <code>0</code> to <code>getSeriesCount() - 1</code>.
144     */
145    public VectorSeries getSeries(int series) {
146        if ((series < 0) || (series >= getSeriesCount())) {
147            throw new IllegalArgumentException("Series index out of bounds");
148        }
149        return (VectorSeries) this.data.get(series);
150    }
151
152    /**
153     * Returns the key for a series.
154     *
155     * @param series  the series index (in the range <code>0</code> to
156     *     <code>getSeriesCount() - 1</code>).
157     *
158     * @return The key for a series.
159     *
160     * @throws IllegalArgumentException if <code>series</code> is not in the
161     *     specified range.
162     */
163    @Override
164    public Comparable getSeriesKey(int series) {
165        // defer argument checking
166        return getSeries(series).getKey();
167    }
168
169    /**
170     * Returns the index of the specified series, or -1 if that series is not
171     * present in the dataset.
172     *
173     * @param series  the series (<code>null</code> not permitted).
174     *
175     * @return The series index.
176     */
177    public int indexOf(VectorSeries series) {
178        ParamChecks.nullNotPermitted(series, "series");
179        return this.data.indexOf(series);
180    }
181
182    /**
183     * Returns the number of items in the specified series.
184     *
185     * @param series  the series (zero-based index).
186     *
187     * @return The item count.
188     *
189     * @throws IllegalArgumentException if <code>series</code> is not in the
190     *     range <code>0</code> to <code>getSeriesCount() - 1</code>.
191     */
192    @Override
193    public int getItemCount(int series) {
194        // defer argument checking
195        return getSeries(series).getItemCount();
196    }
197
198    /**
199     * Returns the x-value for an item within a series.
200     *
201     * @param series  the series index.
202     * @param item  the item index.
203     *
204     * @return The x-value.
205     */
206    @Override
207    public double getXValue(int series, int item) {
208        VectorSeries s = (VectorSeries) this.data.get(series);
209        VectorDataItem di = (VectorDataItem) s.getDataItem(item);
210        return di.getXValue();
211    }
212
213    /**
214     * Returns the x-value for an item within a series.  Note that this method
215     * creates a new {@link Double} instance every time it is called---use
216     * {@link #getXValue(int, int)} instead, if possible.
217     *
218     * @param series  the series index.
219     * @param item  the item index.
220     *
221     * @return The x-value.
222     */
223    @Override
224    public Number getX(int series, int item) {
225        return new Double(getXValue(series, item));
226    }
227
228    /**
229     * Returns the y-value for an item within a series.
230     *
231     * @param series  the series index.
232     * @param item  the item index.
233     *
234     * @return The y-value.
235     */
236    @Override
237    public double getYValue(int series, int item) {
238        VectorSeries s = (VectorSeries) this.data.get(series);
239        VectorDataItem di = (VectorDataItem) s.getDataItem(item);
240        return di.getYValue();
241    }
242
243    /**
244     * Returns the y-value for an item within a series.  Note that this method
245     * creates a new {@link Double} instance every time it is called---use
246     * {@link #getYValue(int, int)} instead, if possible.
247     *
248     * @param series  the series index.
249     * @param item  the item index.
250     *
251     * @return The y-value.
252     */
253    @Override
254    public Number getY(int series, int item) {
255        return new Double(getYValue(series, item));
256    }
257
258    /**
259     * Returns the vector for an item in a series.
260     *
261     * @param series  the series index.
262     * @param item  the item index.
263     *
264     * @return The vector (possibly <code>null</code>).
265     */
266    @Override
267    public Vector getVector(int series, int item) {
268        VectorSeries s = (VectorSeries) this.data.get(series);
269        VectorDataItem di = (VectorDataItem) s.getDataItem(item);
270        return di.getVector();
271    }
272
273    /**
274     * Returns the x-component of the vector for an item in a series.
275     *
276     * @param series  the series index.
277     * @param item  the item index.
278     *
279     * @return The x-component of the vector.
280     */
281    @Override
282    public double getVectorXValue(int series, int item) {
283        VectorSeries s = (VectorSeries) this.data.get(series);
284        VectorDataItem di = (VectorDataItem) s.getDataItem(item);
285        return di.getVectorX();
286    }
287
288    /**
289     * Returns the y-component of the vector for an item in a series.
290     *
291     * @param series  the series index.
292     * @param item  the item index.
293     *
294     * @return The y-component of the vector.
295     */
296    @Override
297    public double getVectorYValue(int series, int item) {
298        VectorSeries s = (VectorSeries) this.data.get(series);
299        VectorDataItem di = (VectorDataItem) s.getDataItem(item);
300        return di.getVectorY();
301    }
302
303    /**
304     * Tests this instance for equality with an arbitrary object.
305     *
306     * @param obj  the object (<code>null</code> permitted).
307     *
308     * @return A boolean.
309     */
310    @Override
311    public boolean equals(Object obj) {
312        if (obj == this) {
313            return true;
314        }
315        if (!(obj instanceof VectorSeriesCollection)) {
316            return false;
317        }
318        VectorSeriesCollection that = (VectorSeriesCollection) obj;
319        return ObjectUtilities.equal(this.data, that.data);
320    }
321
322    /**
323     * Returns a clone of this instance.
324     *
325     * @return A clone.
326     *
327     * @throws CloneNotSupportedException if there is a problem.
328     */
329    @Override
330    public Object clone() throws CloneNotSupportedException {
331        VectorSeriesCollection clone
332                = (VectorSeriesCollection) super.clone();
333        clone.data = (List) ObjectUtilities.deepClone(this.data);
334        return clone;
335    }
336
337}