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 * DefaultCategoryDataset.java 029 * --------------------------- 030 * (C) Copyright 2002-2008, by Object Refinery Limited. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 * Changes 036 * ------- 037 * 21-Jan-2003 : Added standard header, and renamed DefaultCategoryDataset (DG); 038 * 13-Mar-2003 : Inserted DefaultKeyedValues2DDataset into class hierarchy (DG); 039 * 06-Oct-2003 : Added incrementValue() method (DG); 040 * 05-Apr-2004 : Added clear() method (DG); 041 * 18-Aug-2004 : Moved from org.jfree.data --> org.jfree.data.category (DG); 042 * ------------- JFREECHART 1.0.x --------------------------------------------- 043 * 26-Feb-2007 : Updated API docs (DG); 044 * 08-Mar-2007 : Implemented clone() (DG); 045 * 09-May-2008 : Implemented PublicCloneable (DG); 046 * 047 */ 048 049 package org.jfree.data.category; 050 051 import java.io.Serializable; 052 import java.util.List; 053 054 import org.jfree.data.DefaultKeyedValues2D; 055 import org.jfree.data.UnknownKeyException; 056 import org.jfree.data.general.AbstractDataset; 057 import org.jfree.data.general.DatasetChangeEvent; 058 import org.jfree.util.PublicCloneable; 059 060 /** 061 * A default implementation of the {@link CategoryDataset} interface. 062 */ 063 public class DefaultCategoryDataset extends AbstractDataset 064 implements CategoryDataset, PublicCloneable, Serializable { 065 066 /** For serialization. */ 067 private static final long serialVersionUID = -8168173757291644622L; 068 069 /** A storage structure for the data. */ 070 private DefaultKeyedValues2D data; 071 072 /** 073 * Creates a new (empty) dataset. 074 */ 075 public DefaultCategoryDataset() { 076 this.data = new DefaultKeyedValues2D(); 077 } 078 079 /** 080 * Returns the number of rows in the table. 081 * 082 * @return The row count. 083 * 084 * @see #getColumnCount() 085 */ 086 public int getRowCount() { 087 return this.data.getRowCount(); 088 } 089 090 /** 091 * Returns the number of columns in the table. 092 * 093 * @return The column count. 094 * 095 * @see #getRowCount() 096 */ 097 public int getColumnCount() { 098 return this.data.getColumnCount(); 099 } 100 101 /** 102 * Returns a value from the table. 103 * 104 * @param row the row index (zero-based). 105 * @param column the column index (zero-based). 106 * 107 * @return The value (possibly <code>null</code>). 108 * 109 * @see #addValue(Number, Comparable, Comparable) 110 * @see #removeValue(Comparable, Comparable) 111 */ 112 public Number getValue(int row, int column) { 113 return this.data.getValue(row, column); 114 } 115 116 /** 117 * Returns the key for the specified row. 118 * 119 * @param row the row index (zero-based). 120 * 121 * @return The row key. 122 * 123 * @see #getRowIndex(Comparable) 124 * @see #getRowKeys() 125 * @see #getColumnKey(int) 126 */ 127 public Comparable getRowKey(int row) { 128 return this.data.getRowKey(row); 129 } 130 131 /** 132 * Returns the row index for a given key. 133 * 134 * @param key the row key (<code>null</code> not permitted). 135 * 136 * @return The row index. 137 * 138 * @see #getRowKey(int) 139 */ 140 public int getRowIndex(Comparable key) { 141 // defer null argument check 142 return this.data.getRowIndex(key); 143 } 144 145 /** 146 * Returns the row keys. 147 * 148 * @return The keys. 149 * 150 * @see #getRowKey(int) 151 */ 152 public List getRowKeys() { 153 return this.data.getRowKeys(); 154 } 155 156 /** 157 * Returns a column key. 158 * 159 * @param column the column index (zero-based). 160 * 161 * @return The column key. 162 * 163 * @see #getColumnIndex(Comparable) 164 */ 165 public Comparable getColumnKey(int column) { 166 return this.data.getColumnKey(column); 167 } 168 169 /** 170 * Returns the column index for a given key. 171 * 172 * @param key the column key (<code>null</code> not permitted). 173 * 174 * @return The column index. 175 * 176 * @see #getColumnKey(int) 177 */ 178 public int getColumnIndex(Comparable key) { 179 // defer null argument check 180 return this.data.getColumnIndex(key); 181 } 182 183 /** 184 * Returns the column keys. 185 * 186 * @return The keys. 187 * 188 * @see #getColumnKey(int) 189 */ 190 public List getColumnKeys() { 191 return this.data.getColumnKeys(); 192 } 193 194 /** 195 * Returns the value for a pair of keys. 196 * 197 * @param rowKey the row key (<code>null</code> not permitted). 198 * @param columnKey the column key (<code>null</code> not permitted). 199 * 200 * @return The value (possibly <code>null</code>). 201 * 202 * @throws UnknownKeyException if either key is not defined in the dataset. 203 * 204 * @see #addValue(Number, Comparable, Comparable) 205 */ 206 public Number getValue(Comparable rowKey, Comparable columnKey) { 207 return this.data.getValue(rowKey, columnKey); 208 } 209 210 /** 211 * Adds a value to the table. Performs the same function as setValue(). 212 * 213 * @param value the value. 214 * @param rowKey the row key. 215 * @param columnKey the column key. 216 * 217 * @see #getValue(Comparable, Comparable) 218 * @see #removeValue(Comparable, Comparable) 219 */ 220 public void addValue(Number value, Comparable rowKey, 221 Comparable columnKey) { 222 this.data.addValue(value, rowKey, columnKey); 223 fireDatasetChanged(); 224 } 225 226 /** 227 * Adds a value to the table. 228 * 229 * @param value the value. 230 * @param rowKey the row key. 231 * @param columnKey the column key. 232 * 233 * @see #getValue(Comparable, Comparable) 234 */ 235 public void addValue(double value, Comparable rowKey, 236 Comparable columnKey) { 237 addValue(new Double(value), rowKey, columnKey); 238 } 239 240 /** 241 * Adds or updates a value in the table and sends a 242 * {@link DatasetChangeEvent} to all registered listeners. 243 * 244 * @param value the value (<code>null</code> permitted). 245 * @param rowKey the row key (<code>null</code> not permitted). 246 * @param columnKey the column key (<code>null</code> not permitted). 247 * 248 * @see #getValue(Comparable, Comparable) 249 */ 250 public void setValue(Number value, Comparable rowKey, 251 Comparable columnKey) { 252 this.data.setValue(value, rowKey, columnKey); 253 fireDatasetChanged(); 254 } 255 256 /** 257 * Adds or updates a value in the table and sends a 258 * {@link DatasetChangeEvent} to all registered listeners. 259 * 260 * @param value the value. 261 * @param rowKey the row key (<code>null</code> not permitted). 262 * @param columnKey the column key (<code>null</code> not permitted). 263 * 264 * @see #getValue(Comparable, Comparable) 265 */ 266 public void setValue(double value, Comparable rowKey, 267 Comparable columnKey) { 268 setValue(new Double(value), rowKey, columnKey); 269 } 270 271 /** 272 * Adds the specified value to an existing value in the dataset (if the 273 * existing value is <code>null</code>, it is treated as if it were 0.0). 274 * 275 * @param value the value. 276 * @param rowKey the row key (<code>null</code> not permitted). 277 * @param columnKey the column key (<code>null</code> not permitted). 278 * 279 * @throws UnknownKeyException if either key is not defined in the dataset. 280 */ 281 public void incrementValue(double value, 282 Comparable rowKey, 283 Comparable columnKey) { 284 double existing = 0.0; 285 Number n = getValue(rowKey, columnKey); 286 if (n != null) { 287 existing = n.doubleValue(); 288 } 289 setValue(existing + value, rowKey, columnKey); 290 } 291 292 /** 293 * Removes a value from the dataset and sends a {@link DatasetChangeEvent} 294 * to all registered listeners. 295 * 296 * @param rowKey the row key. 297 * @param columnKey the column key. 298 * 299 * @see #addValue(Number, Comparable, Comparable) 300 */ 301 public void removeValue(Comparable rowKey, Comparable columnKey) { 302 this.data.removeValue(rowKey, columnKey); 303 fireDatasetChanged(); 304 } 305 306 /** 307 * Removes a row from the dataset and sends a {@link DatasetChangeEvent} 308 * to all registered listeners. 309 * 310 * @param rowIndex the row index. 311 * 312 * @see #removeColumn(int) 313 */ 314 public void removeRow(int rowIndex) { 315 this.data.removeRow(rowIndex); 316 fireDatasetChanged(); 317 } 318 319 /** 320 * Removes a row from the dataset and sends a {@link DatasetChangeEvent} 321 * to all registered listeners. 322 * 323 * @param rowKey the row key. 324 * 325 * @see #removeColumn(Comparable) 326 */ 327 public void removeRow(Comparable rowKey) { 328 this.data.removeRow(rowKey); 329 fireDatasetChanged(); 330 } 331 332 /** 333 * Removes a column from the dataset and sends a {@link DatasetChangeEvent} 334 * to all registered listeners. 335 * 336 * @param columnIndex the column index. 337 * 338 * @see #removeRow(int) 339 */ 340 public void removeColumn(int columnIndex) { 341 this.data.removeColumn(columnIndex); 342 fireDatasetChanged(); 343 } 344 345 /** 346 * Removes a column from the dataset and sends a {@link DatasetChangeEvent} 347 * to all registered listeners. 348 * 349 * @param columnKey the column key (<code>null</code> not permitted). 350 * 351 * @see #removeRow(Comparable) 352 * 353 * @throws UnknownKeyException if <code>columnKey</code> is not defined 354 * in the dataset. 355 */ 356 public void removeColumn(Comparable columnKey) { 357 this.data.removeColumn(columnKey); 358 fireDatasetChanged(); 359 } 360 361 /** 362 * Clears all data from the dataset and sends a {@link DatasetChangeEvent} 363 * to all registered listeners. 364 */ 365 public void clear() { 366 this.data.clear(); 367 fireDatasetChanged(); 368 } 369 370 /** 371 * Tests this dataset for equality with an arbitrary object. 372 * 373 * @param obj the object (<code>null</code> permitted). 374 * 375 * @return A boolean. 376 */ 377 public boolean equals(Object obj) { 378 if (obj == this) { 379 return true; 380 } 381 if (!(obj instanceof CategoryDataset)) { 382 return false; 383 } 384 CategoryDataset that = (CategoryDataset) obj; 385 if (!getRowKeys().equals(that.getRowKeys())) { 386 return false; 387 } 388 if (!getColumnKeys().equals(that.getColumnKeys())) { 389 return false; 390 } 391 int rowCount = getRowCount(); 392 int colCount = getColumnCount(); 393 for (int r = 0; r < rowCount; r++) { 394 for (int c = 0; c < colCount; c++) { 395 Number v1 = getValue(r, c); 396 Number v2 = that.getValue(r, c); 397 if (v1 == null) { 398 if (v2 != null) { 399 return false; 400 } 401 } 402 else if (!v1.equals(v2)) { 403 return false; 404 } 405 } 406 } 407 return true; 408 } 409 410 /** 411 * Returns a hash code for the dataset. 412 * 413 * @return A hash code. 414 */ 415 public int hashCode() { 416 return this.data.hashCode(); 417 } 418 419 /** 420 * Returns a clone of the dataset. 421 * 422 * @return A clone. 423 * 424 * @throws CloneNotSupportedException if there is a problem cloning the 425 * dataset. 426 */ 427 public Object clone() throws CloneNotSupportedException { 428 DefaultCategoryDataset clone = (DefaultCategoryDataset) super.clone(); 429 clone.data = (DefaultKeyedValues2D) this.data.clone(); 430 return clone; 431 } 432 433 }