001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-present, by David Gilbert 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * --------------------------- 028 * DefaultCategoryDataset.java 029 * --------------------------- 030 * (C) Copyright 2002-present, by David Gilbert. 031 * 032 * Original Author: David Gilbert; 033 * Contributor(s): -; 034 * 035 */ 036 037package org.jfree.data.category; 038 039import java.io.Serializable; 040import java.util.List; 041import org.jfree.chart.util.PublicCloneable; 042 043import org.jfree.data.DefaultKeyedValues2D; 044import org.jfree.data.UnknownKeyException; 045import org.jfree.data.general.AbstractDataset; 046import org.jfree.data.general.DatasetChangeEvent; 047 048/** 049 * A default implementation of the {@link CategoryDataset} interface. 050 */ 051public class DefaultCategoryDataset extends AbstractDataset 052 implements CategoryDataset, PublicCloneable, Serializable { 053 054 /** For serialization. */ 055 private static final long serialVersionUID = -8168173757291644622L; 056 057 /** A storage structure for the data. */ 058 private DefaultKeyedValues2D data; 059 060 /** 061 * Creates a new (empty) dataset. 062 */ 063 public DefaultCategoryDataset() { 064 this.data = new DefaultKeyedValues2D(); 065 } 066 067 /** 068 * Returns the number of rows in the table. 069 * 070 * @return The row count. 071 * 072 * @see #getColumnCount() 073 */ 074 @Override 075 public int getRowCount() { 076 return this.data.getRowCount(); 077 } 078 079 /** 080 * Returns the number of columns in the table. 081 * 082 * @return The column count. 083 * 084 * @see #getRowCount() 085 */ 086 @Override 087 public int getColumnCount() { 088 return this.data.getColumnCount(); 089 } 090 091 /** 092 * Returns a value from the table. 093 * 094 * @param row the row index (zero-based). 095 * @param column the column index (zero-based). 096 * 097 * @return The value (possibly {@code null}). 098 * 099 * @see #addValue(Number, Comparable, Comparable) 100 * @see #removeValue(Comparable, Comparable) 101 */ 102 @Override 103 public Number getValue(int row, int column) { 104 return this.data.getValue(row, column); 105 } 106 107 /** 108 * Returns the key for the specified row. 109 * 110 * @param row the row index (zero-based). 111 * 112 * @return The row key. 113 * 114 * @see #getRowIndex(Comparable) 115 * @see #getRowKeys() 116 * @see #getColumnKey(int) 117 */ 118 @Override 119 public Comparable getRowKey(int row) { 120 return this.data.getRowKey(row); 121 } 122 123 /** 124 * Returns the row index for a given key. 125 * 126 * @param key the row key ({@code null} not permitted). 127 * 128 * @return The row index. 129 * 130 * @see #getRowKey(int) 131 */ 132 @Override 133 public int getRowIndex(Comparable key) { 134 // defer null argument check 135 return this.data.getRowIndex(key); 136 } 137 138 /** 139 * Returns the row keys. 140 * 141 * @return The keys. 142 * 143 * @see #getRowKey(int) 144 */ 145 @Override 146 public List getRowKeys() { 147 return this.data.getRowKeys(); 148 } 149 150 /** 151 * Returns a column key. 152 * 153 * @param column the column index (zero-based). 154 * 155 * @return The column key. 156 * 157 * @see #getColumnIndex(Comparable) 158 */ 159 @Override 160 public Comparable getColumnKey(int column) { 161 return this.data.getColumnKey(column); 162 } 163 164 /** 165 * Returns the column index for a given key. 166 * 167 * @param key the column key ({@code null} not permitted). 168 * 169 * @return The column index. 170 * 171 * @see #getColumnKey(int) 172 */ 173 @Override 174 public int getColumnIndex(Comparable key) { 175 // defer null argument check 176 return this.data.getColumnIndex(key); 177 } 178 179 /** 180 * Returns the column keys. 181 * 182 * @return The keys. 183 * 184 * @see #getColumnKey(int) 185 */ 186 @Override 187 public List getColumnKeys() { 188 return this.data.getColumnKeys(); 189 } 190 191 /** 192 * Returns the value for a pair of keys. 193 * 194 * @param rowKey the row key ({@code null} not permitted). 195 * @param columnKey the column key ({@code null} not permitted). 196 * 197 * @return The value (possibly {@code null}). 198 * 199 * @throws UnknownKeyException if either key is not defined in the dataset. 200 * 201 * @see #addValue(Number, Comparable, Comparable) 202 */ 203 @Override 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(Double.valueOf(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} permitted). 243 * @param rowKey the row key ({@code null} not permitted). 244 * @param columnKey the column key ({@code null} 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} not permitted). 260 * @param columnKey the column key ({@code null} not permitted). 261 * 262 * @see #getValue(Comparable, Comparable) 263 */ 264 public void setValue(double value, Comparable rowKey, 265 Comparable columnKey) { 266 setValue(Double.valueOf(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}, it is treated as if it were 0.0). 272 * 273 * @param value the value. 274 * @param rowKey the row key ({@code null} not permitted). 275 * @param columnKey the column key ({@code null} 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} not permitted). 348 * 349 * @see #removeRow(Comparable) 350 * 351 * @throws UnknownKeyException if {@code columnKey} 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} permitted). 372 * 373 * @return A boolean. 374 */ 375 @Override 376 public boolean equals(Object obj) { 377 if (obj == this) { 378 return true; 379 } 380 if (!(obj instanceof CategoryDataset)) { 381 return false; 382 } 383 CategoryDataset that = (CategoryDataset) obj; 384 if (!getRowKeys().equals(that.getRowKeys())) { 385 return false; 386 } 387 if (!getColumnKeys().equals(that.getColumnKeys())) { 388 return false; 389 } 390 int rowCount = getRowCount(); 391 int colCount = getColumnCount(); 392 for (int r = 0; r < rowCount; r++) { 393 for (int c = 0; c < colCount; c++) { 394 Number v1 = getValue(r, c); 395 Number v2 = that.getValue(r, c); 396 if (v1 == null) { 397 if (v2 != null) { 398 return false; 399 } 400 } 401 else if (!v1.equals(v2)) { 402 return false; 403 } 404 } 405 } 406 return true; 407 } 408 409 /** 410 * Returns a hash code for the dataset. 411 * 412 * @return A hash code. 413 */ 414 @Override 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 @Override 428 public Object clone() throws CloneNotSupportedException { 429 DefaultCategoryDataset clone = (DefaultCategoryDataset) super.clone(); 430 clone.data = (DefaultKeyedValues2D) this.data.clone(); 431 return clone; 432 } 433 434}