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