001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2005, 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 * DefaultWindDataset.java 029 * ----------------------- 030 * (C) Copyright 2001-2005, by Achilleus Mantzios and Contributors. 031 * 032 * Original Author: Achilleus Mantzios; 033 * Contributor(s): David Gilbert (for Object Refinery Limited); 034 * 035 * $Id: DefaultWindDataset.java,v 1.5.2.1 2005/10/25 21:36:51 mungady Exp $ 036 * 037 * Changes 038 * ------- 039 * 06-Feb-2002 : Version 1, based on code contributed by Achilleus 040 * Mantzios (DG); 041 * 05-May-2004 : Now extends AbstractXYDataset (DG); 042 * 15-Jul-2004 : Switched getX() with getXValue() and getY() with 043 * getYValue() (DG); 044 * 045 */ 046 047 package org.jfree.data.xy; 048 049 import java.util.Arrays; 050 import java.util.Collections; 051 import java.util.Date; 052 import java.util.List; 053 054 /** 055 * A default implementation of the {@link WindDataset} interface. 056 * 057 * @author Achilleus Mantzios 058 */ 059 public class DefaultWindDataset extends AbstractXYDataset 060 implements WindDataset { 061 062 /** The keys for the series. */ 063 private List seriesKeys; 064 065 /** Storage for the series data. */ 066 private List allSeriesData; 067 068 /** 069 * Constructs a new, empty, dataset. 070 */ 071 public DefaultWindDataset() { 072 this.seriesKeys = new java.util.ArrayList(); 073 this.allSeriesData = new java.util.ArrayList(); 074 } 075 076 /** 077 * Constructs a dataset based on the specified data array. 078 * 079 * @param data the data. 080 */ 081 public DefaultWindDataset(Object[][][] data) { 082 this(seriesNameListFromDataArray(data), data); 083 } 084 085 /** 086 * Constructs a dataset based on the specified data array. 087 * 088 * @param seriesNames the names of the series. 089 * @param data the wind data. 090 */ 091 public DefaultWindDataset(String[] seriesNames, Object[][][] data) { 092 this(Arrays.asList(seriesNames), data); 093 } 094 095 /** 096 * Constructs a dataset based on the specified data array. The array 097 * can contain multiple series, each series can contain multiple items, 098 * and each item is as follows: 099 * <ul> 100 * <li><code>data[series][item][0]</code> - the date (either a 101 * <code>Date</code> or a <code>Number</code> that is the milliseconds 102 * since 1-Jan-1970);</li> 103 * <li><code>data[series][item][1]</code> - the wind direction (1 - 12, 104 * like the numbers on a clock face);</li> 105 * <li><code>data[series][item][2]</code> - the wind force (1 - 12 on the 106 * Beaufort scale)</li> 107 * </ul> 108 * 109 * @param seriesKeys the names of the series. 110 * @param data the wind dataset. 111 */ 112 public DefaultWindDataset(List seriesKeys, Object[][][] data) { 113 114 this.seriesKeys = seriesKeys; 115 int seriesCount = data.length; 116 this.allSeriesData = new java.util.ArrayList(seriesCount); 117 118 for (int seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) { 119 List oneSeriesData = new java.util.ArrayList(); 120 int maxItemCount = data[seriesIndex].length; 121 for (int itemIndex = 0; itemIndex < maxItemCount; itemIndex++) { 122 Object xObject = data[seriesIndex][itemIndex][0]; 123 if (xObject != null) { 124 Number xNumber; 125 if (xObject instanceof Number) { 126 xNumber = (Number) xObject; 127 } 128 else { 129 if (xObject instanceof Date) { 130 Date xDate = (Date) xObject; 131 xNumber = new Long(xDate.getTime()); 132 } 133 else { 134 xNumber = new Integer(0); 135 } 136 } 137 Number windDir = (Number) data[seriesIndex][itemIndex][1]; 138 Number windForce = (Number) data[seriesIndex][itemIndex][2]; 139 oneSeriesData.add( 140 new WindDataItem(xNumber, windDir, windForce) 141 ); 142 } 143 } 144 Collections.sort(oneSeriesData); 145 this.allSeriesData.add(seriesIndex, oneSeriesData); 146 } 147 148 } 149 150 /** 151 * Returns the number of series in the dataset. 152 * 153 * @return The series count. 154 */ 155 public int getSeriesCount() { 156 return this.allSeriesData.size(); 157 } 158 159 /** 160 * Returns the number of items in a series. 161 * 162 * @param series the series (zero-based index). 163 * 164 * @return The item count. 165 */ 166 public int getItemCount(int series) { 167 List oneSeriesData = (List) this.allSeriesData.get(series); 168 return oneSeriesData.size(); 169 } 170 171 /** 172 * Returns the key for a series. 173 * 174 * @param series the series (zero-based index). 175 * 176 * @return The series key. 177 */ 178 public Comparable getSeriesKey(int series) { 179 return this.seriesKeys.get(series).toString(); 180 } 181 182 /** 183 * Returns the x-value for one item within a series. This should represent 184 * a point in time, encoded as milliseconds in the same way as 185 * java.util.Date. 186 * 187 * @param series the series (zero-based index). 188 * @param item the item (zero-based index). 189 * 190 * @return The x-value for the item within the series. 191 */ 192 public Number getX(int series, int item) { 193 List oneSeriesData = (List) this.allSeriesData.get(series); 194 WindDataItem windItem = (WindDataItem) oneSeriesData.get(item); 195 return windItem.getX(); 196 } 197 198 /** 199 * Returns the y-value for one item within a series. This maps to the 200 * {@link #getWindForce(int, int)} method and is implemented because 201 * <code>WindDataset</code> is an extension of {@link XYDataset}. 202 * 203 * @param series the series (zero-based index). 204 * @param item the item (zero-based index). 205 * 206 * @return The y-value for the item within the series. 207 */ 208 public Number getY(int series, int item) { 209 return getWindForce(series, item); 210 } 211 212 /** 213 * Returns the wind direction for one item within a series. This is a 214 * number between 0 and 12, like the numbers on a clock face. 215 * 216 * @param series the series (zero-based index). 217 * @param item the item (zero-based index). 218 * 219 * @return The wind direction for the item within the series. 220 */ 221 public Number getWindDirection(int series, int item) { 222 List oneSeriesData = (List) this.allSeriesData.get(series); 223 WindDataItem windItem = (WindDataItem) oneSeriesData.get(item); 224 return windItem.getWindDirection(); 225 } 226 227 /** 228 * Returns the wind force for one item within a series. This is a number 229 * between 0 and 12, as defined by the Beaufort scale. 230 * 231 * @param series the series (zero-based index). 232 * @param item the item (zero-based index). 233 * 234 * @return The wind force for the item within the series. 235 */ 236 public Number getWindForce(int series, int item) { 237 List oneSeriesData = (List) this.allSeriesData.get(series); 238 WindDataItem windItem = (WindDataItem) oneSeriesData.get(item); 239 return windItem.getWindForce(); 240 } 241 242 /** 243 * Utility method for automatically generating series names. 244 * @param data the wind dataset. 245 * 246 * @return An array of <i>Series N</i> with N = { 1 .. data.length }. 247 */ 248 public static List seriesNameListFromDataArray(Object[][] data) { 249 250 int seriesCount = data.length; 251 List seriesNameList = new java.util.ArrayList(seriesCount); 252 for (int i = 0; i < seriesCount; i++) { 253 seriesNameList.add("Series " + (i + 1)); 254 } 255 return seriesNameList; 256 257 } 258 259 } 260 261 /** 262 * A wind data item. 263 * 264 * @author Achilleus Mantzios 265 */ 266 class WindDataItem implements Comparable { 267 268 /** The x-value. */ 269 private Number x; 270 271 /** The wind direction. */ 272 private Number windDir; 273 274 /** The wind force. */ 275 private Number windForce; 276 277 /** 278 * Creates a new wind data item. 279 * 280 * @param x the x-value. 281 * @param windDir the direction. 282 * @param windForce the force. 283 */ 284 public WindDataItem(Number x, Number windDir, Number windForce) { 285 this.x = x; 286 this.windDir = windDir; 287 this.windForce = windForce; 288 } 289 290 /** 291 * Returns the x-value. 292 * 293 * @return The x-value. 294 */ 295 public Number getX() { 296 return this.x; 297 } 298 299 /** 300 * Returns the wind direction. 301 * 302 * @return The wind direction. 303 */ 304 public Number getWindDirection() { 305 return this.windDir; 306 } 307 308 /** 309 * Returns the wind force. 310 * 311 * @return The wind force. 312 */ 313 public Number getWindForce() { 314 return this.windForce; 315 } 316 317 /** 318 * Compares this item to another object. 319 * 320 * @param object the other object. 321 * 322 * @return An int that indicates the relative comparison. 323 */ 324 public int compareTo(Object object) { 325 if (object instanceof WindDataItem) { 326 WindDataItem item = (WindDataItem) object; 327 if (this.x.doubleValue() > item.x.doubleValue()) { 328 return 1; 329 } 330 else if (this.x.equals(item.x)) { 331 return 0; 332 } 333 else { 334 return -1; 335 } 336 } 337 else { 338 throw new ClassCastException("WindDataItem.compareTo(error)"); 339 } 340 } 341 342 }