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 }