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