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