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