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 * VectorSeriesCollection.java 029 * --------------------------- 030 * (C) Copyright 2007, 2008, by Object Refinery Limited. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 * Changes 036 * ------- 037 * 30-Jan-2007 : Version 1 (DG); 038 * 24-May-2007 : Added indexOf(), removeSeries() and removeAllSeries() 039 * methods (DG); 040 * 25-May-2007 : Moved from experimental to the main source tree (DG); 041 * 22-Apr-2008 : Implemented PublicCloneable (DG); 042 * 043 */ 044 045 package org.jfree.data.xy; 046 047 import java.io.Serializable; 048 import java.util.List; 049 050 import org.jfree.data.general.DatasetChangeEvent; 051 import org.jfree.util.ObjectUtilities; 052 import org.jfree.util.PublicCloneable; 053 054 /** 055 * A collection of {@link VectorSeries} objects. 056 * 057 * @since 1.0.6 058 */ 059 public class VectorSeriesCollection extends AbstractXYDataset 060 implements VectorXYDataset, PublicCloneable, Serializable { 061 062 /** Storage for the data series. */ 063 private List data; 064 065 /** 066 * Creates a new instance of <code>VectorSeriesCollection</code>. 067 */ 068 public VectorSeriesCollection() { 069 this.data = new java.util.ArrayList(); 070 } 071 072 /** 073 * Adds a series to the collection and sends a {@link DatasetChangeEvent} 074 * to all registered listeners. 075 * 076 * @param series the series (<code>null</code> not permitted). 077 */ 078 public void addSeries(VectorSeries series) { 079 if (series == null) { 080 throw new IllegalArgumentException("Null 'series' argument."); 081 } 082 this.data.add(series); 083 series.addChangeListener(this); 084 fireDatasetChanged(); 085 } 086 087 /** 088 * Removes the specified series from the collection and sends a 089 * {@link DatasetChangeEvent} to all registered listeners. 090 * 091 * @param series the series (<code>null</code> not permitted). 092 * 093 * @return A boolean indicating whether the series has actually been 094 * removed. 095 */ 096 public boolean removeSeries(VectorSeries series) { 097 if (series == null) { 098 throw new IllegalArgumentException("Null 'series' argument."); 099 } 100 boolean removed = this.data.remove(series); 101 if (removed) { 102 series.removeChangeListener(this); 103 fireDatasetChanged(); 104 } 105 return removed; 106 } 107 108 /** 109 * Removes all the series from the collection and sends a 110 * {@link DatasetChangeEvent} to all registered listeners. 111 */ 112 public void removeAllSeries() { 113 114 // deregister the collection as a change listener to each series in the 115 // collection 116 for (int i = 0; i < this.data.size(); i++) { 117 VectorSeries series = (VectorSeries) this.data.get(i); 118 series.removeChangeListener(this); 119 } 120 121 // remove all the series from the collection and notify listeners. 122 this.data.clear(); 123 fireDatasetChanged(); 124 125 } 126 127 /** 128 * Returns the number of series in the collection. 129 * 130 * @return The series count. 131 */ 132 public int getSeriesCount() { 133 return this.data.size(); 134 } 135 136 /** 137 * Returns a series from the collection. 138 * 139 * @param series the series index (zero-based). 140 * 141 * @return The series. 142 * 143 * @throws IllegalArgumentException if <code>series</code> is not in the 144 * range <code>0</code> to <code>getSeriesCount() - 1</code>. 145 */ 146 public VectorSeries getSeries(int series) { 147 if ((series < 0) || (series >= getSeriesCount())) { 148 throw new IllegalArgumentException("Series index out of bounds"); 149 } 150 return (VectorSeries) this.data.get(series); 151 } 152 153 /** 154 * Returns the key for a series. 155 * 156 * @param series the series index (in the range <code>0</code> to 157 * <code>getSeriesCount() - 1</code>). 158 * 159 * @return The key for a series. 160 * 161 * @throws IllegalArgumentException if <code>series</code> is not in the 162 * specified range. 163 */ 164 public Comparable getSeriesKey(int series) { 165 // defer argument checking 166 return getSeries(series).getKey(); 167 } 168 169 /** 170 * Returns the index of the specified series, or -1 if that series is not 171 * present in the dataset. 172 * 173 * @param series the series (<code>null</code> not permitted). 174 * 175 * @return The series index. 176 */ 177 public int indexOf(VectorSeries series) { 178 if (series == null) { 179 throw new IllegalArgumentException("Null 'series' argument."); 180 } 181 return this.data.indexOf(series); 182 } 183 184 /** 185 * Returns the number of items in the specified series. 186 * 187 * @param series the series (zero-based index). 188 * 189 * @return The item count. 190 * 191 * @throws IllegalArgumentException if <code>series</code> is not in the 192 * range <code>0</code> to <code>getSeriesCount() - 1</code>. 193 */ 194 public int getItemCount(int series) { 195 // defer argument checking 196 return getSeries(series).getItemCount(); 197 } 198 199 /** 200 * Returns the x-value for an item within a series. 201 * 202 * @param series the series index. 203 * @param item the item index. 204 * 205 * @return The x-value. 206 */ 207 public double getXValue(int series, int item) { 208 VectorSeries s = (VectorSeries) this.data.get(series); 209 VectorDataItem di = (VectorDataItem) s.getDataItem(item); 210 return di.getXValue(); 211 } 212 213 /** 214 * Returns the x-value for an item within a series. Note that this method 215 * creates a new {@link Double} instance every time it is called---use 216 * {@link #getXValue(int, int)} instead, if possible. 217 * 218 * @param series the series index. 219 * @param item the item index. 220 * 221 * @return The x-value. 222 */ 223 public Number getX(int series, int item) { 224 return new Double(getXValue(series, item)); 225 } 226 227 /** 228 * Returns the y-value for an item within a series. 229 * 230 * @param series the series index. 231 * @param item the item index. 232 * 233 * @return The y-value. 234 */ 235 public double getYValue(int series, int item) { 236 VectorSeries s = (VectorSeries) this.data.get(series); 237 VectorDataItem di = (VectorDataItem) s.getDataItem(item); 238 return di.getYValue(); 239 } 240 241 /** 242 * Returns the y-value for an item within a series. Note that this method 243 * creates a new {@link Double} instance every time it is called---use 244 * {@link #getYValue(int, int)} instead, if possible. 245 * 246 * @param series the series index. 247 * @param item the item index. 248 * 249 * @return The y-value. 250 */ 251 public Number getY(int series, int item) { 252 return new Double(getYValue(series, item)); 253 } 254 255 /** 256 * Returns the vector for an item in a series. 257 * 258 * @param series the series index. 259 * @param item the item index. 260 * 261 * @return The vector (possibly <code>null</code>). 262 */ 263 public Vector getVector(int series, int item) { 264 VectorSeries s = (VectorSeries) this.data.get(series); 265 VectorDataItem di = (VectorDataItem) s.getDataItem(item); 266 return di.getVector(); 267 } 268 269 /** 270 * Returns the x-component of the vector for an item in a series. 271 * 272 * @param series the series index. 273 * @param item the item index. 274 * 275 * @return The x-component of the vector. 276 */ 277 public double getVectorXValue(int series, int item) { 278 VectorSeries s = (VectorSeries) this.data.get(series); 279 VectorDataItem di = (VectorDataItem) s.getDataItem(item); 280 return di.getVectorX(); 281 } 282 283 /** 284 * Returns the y-component of the vector for an item in a series. 285 * 286 * @param series the series index. 287 * @param item the item index. 288 * 289 * @return The y-component of the vector. 290 */ 291 public double getVectorYValue(int series, int item) { 292 VectorSeries s = (VectorSeries) this.data.get(series); 293 VectorDataItem di = (VectorDataItem) s.getDataItem(item); 294 return di.getVectorY(); 295 } 296 297 /** 298 * Tests this instance for equality with an arbitrary object. 299 * 300 * @param obj the object (<code>null</code> permitted). 301 * 302 * @return A boolean. 303 */ 304 public boolean equals(Object obj) { 305 if (obj == this) { 306 return true; 307 } 308 if (!(obj instanceof VectorSeriesCollection)) { 309 return false; 310 } 311 VectorSeriesCollection that = (VectorSeriesCollection) obj; 312 return ObjectUtilities.equal(this.data, that.data); 313 } 314 315 /** 316 * Returns a clone of this instance. 317 * 318 * @return A clone. 319 * 320 * @throws CloneNotSupportedException if there is a problem. 321 */ 322 public Object clone() throws CloneNotSupportedException { 323 VectorSeriesCollection clone 324 = (VectorSeriesCollection) super.clone(); 325 clone.data = (List) ObjectUtilities.deepClone(this.data); 326 return clone; 327 } 328 329 }