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 * XYIntervalSeriesCollection.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 * 13-Feb-2007 : Provided a number of method overrides that enhance
039 * performance, and added a proper clone()
040 * implementation (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 XYIntervalSeries} objects.
057 *
058 * @since 1.0.3
059 *
060 * @see XYIntervalSeries
061 */
062 public class XYIntervalSeriesCollection 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>XIntervalSeriesCollection</code>.
070 */
071 public XYIntervalSeriesCollection() {
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(XYIntervalSeries 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 XYIntervalSeries getSeries(int series) {
110 if ((series < 0) || (series >= getSeriesCount())) {
111 throw new IllegalArgumentException("Series index out of bounds");
112 }
113 return (XYIntervalSeries) 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 XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
157 return s.getX(item);
158 }
159
160 /**
161 * Returns the start x-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 getStartXValue(int series, int item) {
170 XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
171 return s.getXLowValue(item);
172 }
173
174 /**
175 * Returns the end x-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 getEndXValue(int series, int item) {
184 XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
185 return s.getXHighValue(item);
186 }
187
188 /**
189 * Returns the y-value (as a double primitive) for an item within a
190 * series.
191 *
192 * @param series the series index (zero-based).
193 * @param item the item index (zero-based).
194 *
195 * @return The value.
196 */
197 public double getYValue(int series, int item) {
198 XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
199 return s.getYValue(item);
200 }
201
202 /**
203 * Returns the start y-value (as a double primitive) for an item within a
204 * series.
205 *
206 * @param series the series index (zero-based).
207 * @param item the item index (zero-based).
208 *
209 * @return The value.
210 */
211 public double getStartYValue(int series, int item) {
212 XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
213 return s.getYLowValue(item);
214 }
215
216 /**
217 * Returns the end y-value (as a double primitive) for an item within a
218 * series.
219 *
220 * @param series the series (zero-based index).
221 * @param item the item (zero-based index).
222 *
223 * @return The value.
224 */
225 public double getEndYValue(int series, int item) {
226 XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
227 return s.getYHighValue(item);
228 }
229
230 /**
231 * Returns the y-value for an item within a series.
232 *
233 * @param series the series index.
234 * @param item the item index.
235 *
236 * @return The y-value.
237 */
238 public Number getY(int series, int item) {
239 return new Double(getYValue(series, item));
240 }
241
242 /**
243 * Returns the start x-value for an item within a series.
244 *
245 * @param series the series index.
246 * @param item the item index.
247 *
248 * @return The x-value.
249 */
250 public Number getStartX(int series, int item) {
251 return new Double(getStartXValue(series, item));
252 }
253
254 /**
255 * Returns the end x-value for an item within a series.
256 *
257 * @param series the series index.
258 * @param item the item index.
259 *
260 * @return The x-value.
261 */
262 public Number getEndX(int series, int item) {
263 return new Double(getEndXValue(series, item));
264 }
265
266 /**
267 * Returns the start y-value for an item within a series. This method
268 * maps directly to {@link #getY(int, int)}.
269 *
270 * @param series the series index.
271 * @param item the item index.
272 *
273 * @return The start y-value.
274 */
275 public Number getStartY(int series, int item) {
276 return new Double(getStartYValue(series, item));
277 }
278
279 /**
280 * Returns the end y-value for an item within a series. This method
281 * maps directly to {@link #getY(int, int)}.
282 *
283 * @param series the series index.
284 * @param item the item index.
285 *
286 * @return The end y-value.
287 */
288 public Number getEndY(int series, int item) {
289 return new Double(getEndYValue(series, item));
290 }
291
292 /**
293 * Removes a series from the collection and sends a
294 * {@link DatasetChangeEvent} to all registered listeners.
295 *
296 * @param series the series index (zero-based).
297 *
298 * @since 1.0.10
299 */
300 public void removeSeries(int series) {
301 if ((series < 0) || (series >= getSeriesCount())) {
302 throw new IllegalArgumentException("Series index out of bounds.");
303 }
304 XYIntervalSeries ts = (XYIntervalSeries) this.data.get(series);
305 ts.removeChangeListener(this);
306 this.data.remove(series);
307 fireDatasetChanged();
308 }
309
310 /**
311 * Removes a series from the collection and sends a
312 * {@link DatasetChangeEvent} to all registered listeners.
313 *
314 * @param series the series (<code>null</code> not permitted).
315 *
316 * @since 1.0.10
317 */
318 public void removeSeries(XYIntervalSeries series) {
319 if (series == null) {
320 throw new IllegalArgumentException("Null 'series' argument.");
321 }
322 if (this.data.contains(series)) {
323 series.removeChangeListener(this);
324 this.data.remove(series);
325 fireDatasetChanged();
326 }
327 }
328
329 /**
330 * Removes all the series from the collection and sends a
331 * {@link DatasetChangeEvent} to all registered listeners.
332 *
333 * @since 1.0.10
334 */
335 public void removeAllSeries() {
336 // Unregister the collection as a change listener to each series in
337 // the collection.
338 for (int i = 0; i < this.data.size(); i++) {
339 XYIntervalSeries series = (XYIntervalSeries) this.data.get(i);
340 series.removeChangeListener(this);
341 }
342 this.data.clear();
343 fireDatasetChanged();
344 }
345
346 /**
347 * Tests this instance for equality with an arbitrary object.
348 *
349 * @param obj the object (<code>null</code> permitted).
350 *
351 * @return A boolean.
352 */
353 public boolean equals(Object obj) {
354 if (obj == this) {
355 return true;
356 }
357 if (!(obj instanceof XYIntervalSeriesCollection)) {
358 return false;
359 }
360 XYIntervalSeriesCollection that = (XYIntervalSeriesCollection) obj;
361 return ObjectUtilities.equal(this.data, that.data);
362 }
363
364 /**
365 * Returns a clone of this dataset.
366 *
367 * @return A clone of this dataset.
368 *
369 * @throws CloneNotSupportedException if there is a problem cloning.
370 */
371 public Object clone() throws CloneNotSupportedException {
372 XYIntervalSeriesCollection clone
373 = (XYIntervalSeriesCollection) super.clone();
374 int seriesCount = getSeriesCount();
375 clone.data = new java.util.ArrayList(seriesCount);
376 for (int i = 0; i < this.data.size(); i++) {
377 clone.data.set(i, getSeries(i).clone());
378 }
379 return clone;
380 }
381
382 }