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