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