001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2022, by David Gilbert 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * ------------------------------- 028 * XYIntervalSeriesCollection.java 029 * ------------------------------- 030 * (C) Copyright 2006-2022, by David Gilbert. 031 * 032 * Original Author: David Gilbert; 033 * Contributor(s): -; 034 * 035 */ 036 037package org.jfree.data.xy; 038 039import java.io.Serializable; 040import java.util.ArrayList; 041import java.util.List; 042import java.util.Objects; 043 044import org.jfree.chart.internal.Args; 045import org.jfree.chart.internal.CloneUtils; 046import org.jfree.chart.api.PublicCloneable; 047 048import org.jfree.data.general.DatasetChangeEvent; 049 050/** 051 * A collection of {@link XYIntervalSeries} objects. 052 * 053 * @param <S> The type for the series keys. 054 * 055 * @since 1.0.3 056 * 057 * @see XYIntervalSeries 058 */ 059public class XYIntervalSeriesCollection<S extends Comparable<S>> 060 extends AbstractIntervalXYDataset<S> 061 implements IntervalXYDataset<S>, PublicCloneable, Serializable { 062 063 /** Storage for the data series. */ 064 private List<XYIntervalSeries<S>> data; 065 066 /** 067 * Creates a new instance of {@code XIntervalSeriesCollection}. 068 */ 069 public XYIntervalSeriesCollection() { 070 this.data = new 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} not permitted). 078 */ 079 public void addSeries(XYIntervalSeries<S> series) { 080 Args.nullNotPermitted(series, "series"); 081 this.data.add(series); 082 series.addChangeListener(this); 083 fireDatasetChanged(); 084 } 085 086 /** 087 * Returns the number of series in the collection. 088 * 089 * @return The series count. 090 */ 091 @Override 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} is not in the 104 * range {@code 0} to {@code getSeriesCount() - 1}. 105 */ 106 public XYIntervalSeries<S> getSeries(int series) { 107 Args.requireInRange(series, "series", 0, this.data.size() - 1); 108 return this.data.get(series); 109 } 110 111 /** 112 * Returns the key for a series. 113 * 114 * @param series the series index (in the range {@code 0} to 115 * {@code getSeriesCount() - 1}). 116 * 117 * @return The key for a series. 118 * 119 * @throws IllegalArgumentException if {@code series} is not in the 120 * specified range. 121 */ 122 @Override 123 public S getSeriesKey(int series) { 124 // defer argument checking 125 return getSeries(series).getKey(); 126 } 127 128 /** 129 * Returns the number of items in the specified series. 130 * 131 * @param series the series (zero-based index). 132 * 133 * @return The item count. 134 * 135 * @throws IllegalArgumentException if {@code series} is not in the 136 * range {@code 0} to {@code getSeriesCount() - 1}. 137 */ 138 @Override 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 @Override 153 public Number getX(int series, int item) { 154 XYIntervalSeries<S> s = this.data.get(series); 155 return s.getX(item); 156 } 157 158 /** 159 * Returns the start x-value (as a double primitive) for an item within a 160 * series. 161 * 162 * @param series the series index (zero-based). 163 * @param item the item index (zero-based). 164 * 165 * @return The value. 166 */ 167 @Override 168 public double getStartXValue(int series, int item) { 169 XYIntervalSeries<S> s = 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 index (zero-based). 178 * @param item the item index (zero-based). 179 * 180 * @return The value. 181 */ 182 @Override 183 public double getEndXValue(int series, int item) { 184 XYIntervalSeries<S> s = 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 @Override 198 public double getYValue(int series, int item) { 199 XYIntervalSeries<S> s = this.data.get(series); 200 return s.getYValue(item); 201 } 202 203 /** 204 * Returns the start y-value (as a double primitive) for an item within a 205 * series. 206 * 207 * @param series the series index (zero-based). 208 * @param item the item index (zero-based). 209 * 210 * @return The value. 211 */ 212 @Override 213 public double getStartYValue(int series, int item) { 214 XYIntervalSeries<S> s = this.data.get(series); 215 return s.getYLowValue(item); 216 } 217 218 /** 219 * Returns the end y-value (as a double primitive) for an item within a 220 * series. 221 * 222 * @param series the series (zero-based index). 223 * @param item the item (zero-based index). 224 * 225 * @return The value. 226 */ 227 @Override 228 public double getEndYValue(int series, int item) { 229 XYIntervalSeries<S> s = this.data.get(series); 230 return s.getYHighValue(item); 231 } 232 233 /** 234 * Returns the y-value for an item within a series. 235 * 236 * @param series the series index. 237 * @param item the item index. 238 * 239 * @return The y-value. 240 */ 241 @Override 242 public Number getY(int series, int item) { 243 return getYValue(series, item); 244 } 245 246 /** 247 * Returns the start x-value for an item within a series. 248 * 249 * @param series the series index. 250 * @param item the item index. 251 * 252 * @return The x-value. 253 */ 254 @Override 255 public Number getStartX(int series, int item) { 256 return getStartXValue(series, item); 257 } 258 259 /** 260 * Returns the end x-value for an item within a series. 261 * 262 * @param series the series index. 263 * @param item the item index. 264 * 265 * @return The x-value. 266 */ 267 @Override 268 public Number getEndX(int series, int item) { 269 return getEndXValue(series, item); 270 } 271 272 /** 273 * Returns the start y-value for an item within a series. This method 274 * maps directly to {@link #getY(int, int)}. 275 * 276 * @param series the series index. 277 * @param item the item index. 278 * 279 * @return The start y-value. 280 */ 281 @Override 282 public Number getStartY(int series, int item) { 283 return getStartYValue(series, item); 284 } 285 286 /** 287 * Returns the end y-value for an item within a series. This method 288 * maps directly to {@link #getY(int, int)}. 289 * 290 * @param series the series index. 291 * @param item the item index. 292 * 293 * @return The end y-value. 294 */ 295 @Override 296 public Number getEndY(int series, int item) { 297 return getEndYValue(series, item); 298 } 299 300 /** 301 * Removes a series from the collection and sends a 302 * {@link DatasetChangeEvent} to all registered listeners. 303 * 304 * @param series the series index (zero-based). 305 * 306 * @since 1.0.10 307 */ 308 public void removeSeries(int series) { 309 if ((series < 0) || (series >= getSeriesCount())) { 310 throw new IllegalArgumentException("Series index out of bounds."); 311 } 312 XYIntervalSeries<S> ts = this.data.get(series); 313 ts.removeChangeListener(this); 314 this.data.remove(series); 315 fireDatasetChanged(); 316 } 317 318 /** 319 * Removes a series from the collection and sends a 320 * {@link DatasetChangeEvent} to all registered listeners. 321 * 322 * @param series the series ({@code null} not permitted). 323 * 324 * @since 1.0.10 325 */ 326 public void removeSeries(XYIntervalSeries<S> series) { 327 Args.nullNotPermitted(series, "series"); 328 if (this.data.contains(series)) { 329 series.removeChangeListener(this); 330 this.data.remove(series); 331 fireDatasetChanged(); 332 } 333 } 334 335 /** 336 * Removes all the series from the collection and sends a 337 * {@link DatasetChangeEvent} to all registered listeners. 338 * 339 * @since 1.0.10 340 */ 341 public void removeAllSeries() { 342 // Unregister the collection as a change listener to each series in 343 // the collection. 344 for (int i = 0; i < this.data.size(); i++) { 345 XYIntervalSeries<S> series = this.data.get(i); 346 series.removeChangeListener(this); 347 } 348 this.data.clear(); 349 fireDatasetChanged(); 350 } 351 352 /** 353 * Tests this instance for equality with an arbitrary object. 354 * 355 * @param obj the object ({@code null} permitted). 356 * 357 * @return A boolean. 358 */ 359 @Override 360 public boolean equals(Object obj) { 361 if (obj == this) { 362 return true; 363 } 364 if (!(obj instanceof XYIntervalSeriesCollection)) { 365 return false; 366 } 367 XYIntervalSeriesCollection<S> that = (XYIntervalSeriesCollection) obj; 368 return Objects.equals(this.data, that.data); 369 } 370 371 /** 372 * Returns a clone of this dataset. 373 * 374 * @return A clone of this dataset. 375 * 376 * @throws CloneNotSupportedException if there is a problem cloning. 377 */ 378 @Override 379 public Object clone() throws CloneNotSupportedException { 380 XYIntervalSeriesCollection clone 381 = (XYIntervalSeriesCollection) super.clone(); 382 clone.data = CloneUtils.cloneList(this.data); 383 return clone; 384 } 385 386}