001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2007, 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 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
025 * in the United States and other countries.]
026 *
027 * -------------------------------
028 * XYIntervalSeriesCollection.java
029 * -------------------------------
030 * (C) Copyright 2006, 2007, by Object Refinery Limited.
031 *
032 * Original Author:  David Gilbert (for Object Refinery Limited);
033 * Contributor(s):   -;
034 *
035 * Changes
036 * -------
037 * 20-Oct-2006 : Version 1 (DG);
038 * 13-Feb-2007 : Provided a number of method overrides that enhance 
039 *               performance, and added a proper clone() 
040 *               implementation (DG);
041 *
042 */
043
044package org.jfree.data.xy;
045
046import java.io.Serializable;
047import java.util.List;
048
049import org.jfree.data.general.DatasetChangeEvent;
050import org.jfree.util.ObjectUtilities;
051
052/**
053 * A collection of {@link XYIntervalSeries} objects.
054 *
055 * @since 1.0.3
056 *
057 * @see XYIntervalSeries
058 */
059public class XYIntervalSeriesCollection extends AbstractIntervalXYDataset
060                                implements IntervalXYDataset, Serializable {
061
062    /** Storage for the data series. */
063    private List data;
064    
065    /** 
066     * Creates a new instance of <code>XIntervalSeriesCollection</code>. 
067     */
068    public XYIntervalSeriesCollection() {
069        this.data = new java.util.ArrayList();
070    }
071
072    /**
073     * Adds a series to the collection and sends a {@link DatasetChangeEvent} 
074     * to all registered listeners.
075     *
076     * @param series  the series (<code>null</code> not permitted).
077     */
078    public void addSeries(XYIntervalSeries series) {
079        if (series == null) {
080            throw new IllegalArgumentException("Null 'series' argument.");
081        }
082        this.data.add(series);
083        series.addChangeListener(this);
084        fireDatasetChanged();
085    }
086
087    /**
088     * Returns the number of series in the collection.
089     *
090     * @return The series count.
091     */
092    public int getSeriesCount() {
093        return this.data.size();
094    }
095
096    /**
097     * Returns a series from the collection.
098     *
099     * @param series  the series index (zero-based).
100     *
101     * @return The series.
102     * 
103     * @throws IllegalArgumentException if <code>series</code> is not in the
104     *     range <code>0</code> to <code>getSeriesCount() - 1</code>.
105     */
106    public XYIntervalSeries getSeries(int series) {
107        if ((series < 0) || (series >= getSeriesCount())) {
108            throw new IllegalArgumentException("Series index out of bounds");
109        }
110        return (XYIntervalSeries) this.data.get(series);
111    }
112
113    /**
114     * Returns the key for a series.
115     *
116     * @param series  the series index (in the range <code>0</code> to 
117     *     <code>getSeriesCount() - 1</code>).
118     *
119     * @return The key for a series.
120     * 
121     * @throws IllegalArgumentException if <code>series</code> is not in the
122     *     specified range.
123     */
124    public Comparable getSeriesKey(int series) {
125        // defer argument checking
126        return getSeries(series).getKey();
127    }
128
129    /**
130     * Returns the number of items in the specified series.
131     *
132     * @param series  the series (zero-based index).
133     *
134     * @return The item count.
135     * 
136     * @throws IllegalArgumentException if <code>series</code> is not in the
137     *     range <code>0</code> to <code>getSeriesCount() - 1</code>.
138     */
139    public int getItemCount(int series) {
140        // defer argument checking
141        return getSeries(series).getItemCount();
142    }
143
144    /**
145     * Returns the x-value for an item within a series.
146     *
147     * @param series  the series index.
148     * @param item  the item index.
149     *
150     * @return The x-value.
151     */
152    public Number getX(int series, int item) {
153        XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
154        return s.getX(item);
155    }
156
157    /**
158     * Returns the start x-value (as a double primitive) for an item within a 
159     * series.
160     * 
161     * @param series  the series index (zero-based).
162     * @param item  the item index (zero-based).
163     * 
164     * @return The value.
165     */
166    public double getStartXValue(int series, int item) {
167        XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
168        return s.getXLowValue(item);
169    }
170
171    /**
172     * Returns the end x-value (as a double primitive) for an item within a 
173     * series.
174     * 
175     * @param series  the series index (zero-based).
176     * @param item  the item index (zero-based).
177     * 
178     * @return The value.
179     */
180    public double getEndXValue(int series, int item) {
181        XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
182        return s.getXHighValue(item);
183    }
184
185    /**
186     * Returns the y-value (as a double primitive) for an item within a 
187     * series.
188     * 
189     * @param series  the series index (zero-based).
190     * @param item  the item index (zero-based).
191     * 
192     * @return The value.
193     */
194    public double getYValue(int series, int item) {
195        XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
196        return s.getYValue(item);
197    }
198
199    /**
200     * Returns the start y-value (as a double primitive) for an item within a 
201     * series.
202     * 
203     * @param series  the series index (zero-based).
204     * @param item  the item index (zero-based).
205     * 
206     * @return The value.
207     */
208    public double getStartYValue(int series, int item) {
209        XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
210        return s.getYLowValue(item);
211    }
212
213    /**
214     * Returns the end y-value (as a double primitive) for an item within a 
215     * series.
216     * 
217     * @param series  the series (zero-based index).
218     * @param item  the item (zero-based index).
219     * 
220     * @return The value.
221     */
222    public double getEndYValue(int series, int item) {
223        XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
224        return s.getYHighValue(item);
225    }
226
227    /**
228     * Returns the y-value for an item within a series.
229     *
230     * @param series  the series index.
231     * @param item  the item index.
232     *
233     * @return The y-value.
234     */
235    public Number getY(int series, int item) {
236        return new Double(getYValue(series, item));
237    }
238
239    /**
240     * Returns the start x-value for an item within a series.  
241     *
242     * @param series  the series index.
243     * @param item  the item index.
244     *
245     * @return The x-value.
246     */
247    public Number getStartX(int series, int item) {
248        return new Double(getStartXValue(series, item));
249    }
250
251    /**
252     * Returns the end x-value for an item within a series.  
253     *
254     * @param series  the series index.
255     * @param item  the item index.
256     *
257     * @return The x-value.
258     */
259    public Number getEndX(int series, int item) {
260        return new Double(getEndXValue(series, item));
261    }
262
263    /**
264     * Returns the start y-value for an item within a series.  This method
265     * maps directly to {@link #getY(int, int)}.
266     *
267     * @param series  the series index.
268     * @param item  the item index.
269     *
270     * @return The start y-value.
271     */
272    public Number getStartY(int series, int item) {
273        return new Double(getStartYValue(series, item));
274    }
275
276    /**
277     * Returns the end y-value for an item within a series.  This method
278     * maps directly to {@link #getY(int, int)}.
279     *
280     * @param series  the series index.
281     * @param item  the item index.
282     *
283     * @return The end y-value.
284     */
285    public Number getEndY(int series, int item) {
286        return new Double(getEndYValue(series, item));
287    }
288    
289    /**
290     * Tests this instance for equality with an arbitrary object.
291     *
292     * @param obj  the object (<code>null</code> permitted).
293     *
294     * @return A boolean. 
295     */
296    public boolean equals(Object obj) {
297        if (obj == this) {
298            return true;
299        }
300        if (!(obj instanceof XYIntervalSeriesCollection)) {
301            return false;
302        }
303        XYIntervalSeriesCollection that = (XYIntervalSeriesCollection) obj;
304        return ObjectUtilities.equal(this.data, that.data);
305    }
306    
307    /**
308     * Returns a clone of this dataset.
309     * 
310     * @return A clone of this dataset.
311     * 
312     * @throws CloneNotSupportedException if there is a problem cloning.
313     */
314    public Object clone() throws CloneNotSupportedException {
315        XYIntervalSeriesCollection clone 
316                = (XYIntervalSeriesCollection) super.clone();
317        int seriesCount = getSeriesCount();
318        clone.data = new java.util.ArrayList(seriesCount);
319        for (int i = 0; i < this.data.size(); i++) {
320            clone.data.set(i, getSeries(i).clone());
321        }
322        return clone;
323    }
324    
325}