001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2007, 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 * OHLCSeriesCollection.java 029 * ------------------------- 030 * (C) Copyright 2006, 2007, by Object Refinery Limited. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 * Changes 036 * ------- 037 * 04-Dec-2006 : Version 1 (DG); 038 * 039 */ 040 041 package org.jfree.data.time.ohlc; 042 043 import java.io.Serializable; 044 import java.util.List; 045 046 import org.jfree.data.general.DatasetChangeEvent; 047 import org.jfree.data.time.RegularTimePeriod; 048 import org.jfree.data.time.TimePeriodAnchor; 049 import org.jfree.data.xy.AbstractXYDataset; 050 import org.jfree.data.xy.OHLCDataset; 051 import org.jfree.util.ObjectUtilities; 052 053 /** 054 * A collection of {@link OHLCSeries} objects. 055 * 056 * @since 1.0.4 057 * 058 * @see OHLCSeries 059 */ 060 public class OHLCSeriesCollection extends AbstractXYDataset 061 implements OHLCDataset, Serializable { 062 063 /** Storage for the data series. */ 064 private List data; 065 066 private TimePeriodAnchor xPosition = TimePeriodAnchor.MIDDLE; 067 068 /** 069 * Creates a new instance of <code>OHLCSeriesCollection</code>. 070 */ 071 public OHLCSeriesCollection() { 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(OHLCSeries 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 OHLCSeries getSeries(int series) { 110 if ((series < 0) || (series >= getSeriesCount())) { 111 throw new IllegalArgumentException("Series index out of bounds"); 112 } 113 return (OHLCSeries) 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 a time period. 149 * 150 * @param period the time period (<code>null</code> not permitted). 151 * 152 * @return The x-value. 153 */ 154 protected synchronized long getX(RegularTimePeriod period) { 155 long result = 0L; 156 if (this.xPosition == TimePeriodAnchor.START) { 157 result = period.getFirstMillisecond(); 158 } 159 else if (this.xPosition == TimePeriodAnchor.MIDDLE) { 160 result = period.getMiddleMillisecond(); 161 } 162 else if (this.xPosition == TimePeriodAnchor.END) { 163 result = period.getLastMillisecond(); 164 } 165 return result; 166 } 167 168 /** 169 * Returns the x-value for an item within a series. 170 * 171 * @param series the series index. 172 * @param item the item index. 173 * 174 * @return The x-value. 175 */ 176 public double getXValue(int series, int item) { 177 OHLCSeries s = (OHLCSeries) this.data.get(series); 178 OHLCItem di = (OHLCItem) s.getDataItem(item); 179 RegularTimePeriod period = di.getPeriod(); 180 return getX(period); 181 } 182 183 /** 184 * Returns the x-value for an item within a series. 185 * 186 * @param series the series index. 187 * @param item the item index. 188 * 189 * @return The x-value. 190 */ 191 public Number getX(int series, int item) { 192 return new Double(getXValue(series, item)); 193 } 194 195 /** 196 * Returns the y-value for an item within a series. 197 * 198 * @param series the series index. 199 * @param item the item index. 200 * 201 * @return The y-value. 202 */ 203 public Number getY(int series, int item) { 204 OHLCSeries s = (OHLCSeries) this.data.get(series); 205 OHLCItem di = (OHLCItem) s.getDataItem(item); 206 return new Double(di.getYValue()); 207 } 208 209 /** 210 * Returns the open-value for an item within a series. 211 * 212 * @param series the series index. 213 * @param item the item index. 214 * 215 * @return The open-value. 216 */ 217 public double getOpenValue(int series, int item) { 218 OHLCSeries s = (OHLCSeries) this.data.get(series); 219 OHLCItem di = (OHLCItem) s.getDataItem(item); 220 return di.getOpenValue(); 221 } 222 223 /** 224 * Returns the open-value for an item within a series. 225 * 226 * @param series the series index. 227 * @param item the item index. 228 * 229 * @return The open-value. 230 */ 231 public Number getOpen(int series, int item) { 232 return new Double(getOpenValue(series, item)); 233 } 234 235 /** 236 * Returns the close-value for an item within a series. 237 * 238 * @param series the series index. 239 * @param item the item index. 240 * 241 * @return The close-value. 242 */ 243 public double getCloseValue(int series, int item) { 244 OHLCSeries s = (OHLCSeries) this.data.get(series); 245 OHLCItem di = (OHLCItem) s.getDataItem(item); 246 return di.getCloseValue(); 247 } 248 249 /** 250 * Returns the close-value for an item within a series. 251 * 252 * @param series the series index. 253 * @param item the item index. 254 * 255 * @return The close-value. 256 */ 257 public Number getClose(int series, int item) { 258 return new Double(getCloseValue(series, item)); 259 } 260 261 /** 262 * Returns the high-value for an item within a series. 263 * 264 * @param series the series index. 265 * @param item the item index. 266 * 267 * @return The high-value. 268 */ 269 public double getHighValue(int series, int item) { 270 OHLCSeries s = (OHLCSeries) this.data.get(series); 271 OHLCItem di = (OHLCItem) s.getDataItem(item); 272 return di.getHighValue(); 273 } 274 275 /** 276 * Returns the high-value for an item within a series. 277 * 278 * @param series the series index. 279 * @param item the item index. 280 * 281 * @return The high-value. 282 */ 283 public Number getHigh(int series, int item) { 284 return new Double(getHighValue(series, item)); 285 } 286 287 /** 288 * Returns the low-value for an item within a series. 289 * 290 * @param series the series index. 291 * @param item the item index. 292 * 293 * @return The low-value. 294 */ 295 public double getLowValue(int series, int item) { 296 OHLCSeries s = (OHLCSeries) this.data.get(series); 297 OHLCItem di = (OHLCItem) s.getDataItem(item); 298 return di.getLowValue(); 299 } 300 301 /** 302 * Returns the low-value for an item within a series. 303 * 304 * @param series the series index. 305 * @param item the item index. 306 * 307 * @return The low-value. 308 */ 309 public Number getLow(int series, int item) { 310 return new Double(getLowValue(series, item)); 311 } 312 313 public Number getVolume(int series, int item) { 314 return null; 315 } 316 317 public double getVolumeValue(int series, int item) { 318 return Double.NaN; 319 } 320 321 /** 322 * Tests this instance for equality with an arbitrary object. 323 * 324 * @param obj the object (<code>null</code> permitted). 325 * 326 * @return A boolean. 327 */ 328 public boolean equals(Object obj) { 329 if (obj == this) { 330 return true; 331 } 332 if (!(obj instanceof OHLCSeriesCollection)) { 333 return false; 334 } 335 OHLCSeriesCollection that = (OHLCSeriesCollection) obj; 336 return ObjectUtilities.equal(this.data, that.data); 337 } 338 339 /** 340 * Returns a clone of this instance. 341 * 342 * @return A clone. 343 * 344 * @throws CloneNotSupportedException if there is a problem. 345 */ 346 public Object clone() throws CloneNotSupportedException { 347 OHLCSeriesCollection clone 348 = (OHLCSeriesCollection) super.clone(); 349 clone.data = (List) ObjectUtilities.deepClone(this.data); 350 return clone; 351 } 352 353 }