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