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 * $Id: DefaultCategoryDataset.java,v 1.5.2.4 2007/03/08 11:12:08 mungady Exp $
036 *
037 * Changes
038 * -------
039 * 21-Jan-2003 : Added standard header, and renamed DefaultCategoryDataset (DG);
040 * 13-Mar-2003 : Inserted DefaultKeyedValues2DDataset into class hierarchy (DG);
041 * 06-Oct-2003 : Added incrementValue() method (DG);
042 * 05-Apr-2004 : Added clear() method (DG);
043 * 18-Aug-2004 : Moved from org.jfree.data --> org.jfree.data.category (DG);
044 * ------------- JFREECHART 1.0.x ---------------------------------------------
045 * 26-Feb-2007 : Updated API docs (DG);
046 * 08-Mar-2007 : Implemented clone() (DG);
047 *
048 */
049
050 package org.jfree.data.category;
051
052 import java.io.Serializable;
053 import java.util.List;
054
055 import org.jfree.data.DefaultKeyedValues2D;
056 import org.jfree.data.UnknownKeyException;
057 import org.jfree.data.general.AbstractDataset;
058 import org.jfree.data.general.DatasetChangeEvent;
059
060 /**
061 * A default implementation of the {@link CategoryDataset} interface.
062 */
063 public class DefaultCategoryDataset extends AbstractDataset
064 implements CategoryDataset, 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 */
111 public Number getValue(int row, int column) {
112 return this.data.getValue(row, column);
113 }
114
115 /**
116 * Returns a row key.
117 *
118 * @param row the row index (zero-based).
119 *
120 * @return The row key.
121 *
122 * @see #getRowIndex(Comparable)
123 * @see #getRowKeys()
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.
133 *
134 * @return The row index.
135 *
136 * @see #getRowKey(int)
137 */
138 public int getRowIndex(Comparable key) {
139 return this.data.getRowIndex(key);
140 }
141
142 /**
143 * Returns the row keys.
144 *
145 * @return The keys.
146 *
147 * @see #getRowKey(int)
148 */
149 public List getRowKeys() {
150 return this.data.getRowKeys();
151 }
152
153 /**
154 * Returns a column key.
155 *
156 * @param column the column index (zero-based).
157 *
158 * @return The column key.
159 *
160 * @see #getColumnIndex(Comparable)
161 */
162 public Comparable getColumnKey(int column) {
163 return this.data.getColumnKey(column);
164 }
165
166 /**
167 * Returns the column index for a given key.
168 *
169 * @param key the column key.
170 *
171 * @return The column index.
172 *
173 * @see #getColumnKey(int)
174 */
175 public int getColumnIndex(Comparable key) {
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 public List getColumnKeys() {
187 return this.data.getColumnKeys();
188 }
189
190 /**
191 * Returns the value for a pair of keys.
192 *
193 * @param rowKey the row key (<code>null</code> not permitted).
194 * @param columnKey the column key (<code>null</code> not permitted).
195 *
196 * @return The value (possibly <code>null</code>).
197 *
198 * @throws UnknownKeyException if either key is not defined in the dataset.
199 *
200 * @see #addValue(Number, Comparable, Comparable)
201 */
202 public Number getValue(Comparable rowKey, Comparable columnKey) {
203 return this.data.getValue(rowKey, columnKey);
204 }
205
206 /**
207 * Adds a value to the table. Performs the same function as setValue().
208 *
209 * @param value the value.
210 * @param rowKey the row key.
211 * @param columnKey the column key.
212 *
213 * @see #getValue(Comparable, Comparable)
214 * @see #removeValue(Comparable, Comparable)
215 */
216 public void addValue(Number value, Comparable rowKey,
217 Comparable columnKey) {
218 this.data.addValue(value, rowKey, columnKey);
219 fireDatasetChanged();
220 }
221
222 /**
223 * Adds a value to the table.
224 *
225 * @param value the value.
226 * @param rowKey the row key.
227 * @param columnKey the column key.
228 *
229 * @see #getValue(Comparable, Comparable)
230 */
231 public void addValue(double value, Comparable rowKey,
232 Comparable columnKey) {
233 addValue(new Double(value), rowKey, columnKey);
234 }
235
236 /**
237 * Adds or updates a value in the table and sends a
238 * {@link DatasetChangeEvent} to all registered listeners.
239 *
240 * @param value the value (<code>null</code> permitted).
241 * @param rowKey the row key (<code>null</code> not permitted).
242 * @param columnKey the column key (<code>null</code> not permitted).
243 *
244 * @see #getValue(Comparable, Comparable)
245 */
246 public void setValue(Number value, Comparable rowKey,
247 Comparable columnKey) {
248 this.data.setValue(value, rowKey, columnKey);
249 fireDatasetChanged();
250 }
251
252 /**
253 * Adds or updates a value in the table and sends a
254 * {@link DatasetChangeEvent} to all registered listeners.
255 *
256 * @param value the value.
257 * @param rowKey the row key (<code>null</code> not permitted).
258 * @param columnKey the column key (<code>null</code> not permitted).
259 *
260 * @see #getValue(Comparable, Comparable)
261 */
262 public void setValue(double value, Comparable rowKey,
263 Comparable columnKey) {
264 setValue(new Double(value), rowKey, columnKey);
265 }
266
267 /**
268 * Adds the specified value to an existing value in the dataset (if the
269 * existing value is <code>null</code>, it is treated as if it were 0.0).
270 *
271 * @param value the value.
272 * @param rowKey the row key (<code>null</code> not permitted).
273 * @param columnKey the column key (<code>null</code> not permitted).
274 *
275 * @throws UnknownKeyException if either key is not defined in the dataset.
276 */
277 public void incrementValue(double value,
278 Comparable rowKey,
279 Comparable columnKey) {
280 double existing = 0.0;
281 Number n = getValue(rowKey, columnKey);
282 if (n != null) {
283 existing = n.doubleValue();
284 }
285 setValue(existing + value, rowKey, columnKey);
286 }
287
288 /**
289 * Removes a value from the dataset and sends a {@link DatasetChangeEvent}
290 * to all registered listeners.
291 *
292 * @param rowKey the row key.
293 * @param columnKey the column key.
294 *
295 * @see #addValue(Number, Comparable, Comparable)
296 */
297 public void removeValue(Comparable rowKey, Comparable columnKey) {
298 this.data.removeValue(rowKey, columnKey);
299 fireDatasetChanged();
300 }
301
302 /**
303 * Removes a row from the dataset and sends a {@link DatasetChangeEvent}
304 * to all registered listeners.
305 *
306 * @param rowIndex the row index.
307 *
308 * @see #removeColumn(int)
309 */
310 public void removeRow(int rowIndex) {
311 this.data.removeRow(rowIndex);
312 fireDatasetChanged();
313 }
314
315 /**
316 * Removes a row from the dataset and sends a {@link DatasetChangeEvent}
317 * to all registered listeners.
318 *
319 * @param rowKey the row key.
320 *
321 * @see #removeColumn(Comparable)
322 */
323 public void removeRow(Comparable rowKey) {
324 this.data.removeRow(rowKey);
325 fireDatasetChanged();
326 }
327
328 /**
329 * Removes a column from the dataset and sends a {@link DatasetChangeEvent}
330 * to all registered listeners.
331 *
332 * @param columnIndex the column index.
333 *
334 * @see #removeRow(int)
335 */
336 public void removeColumn(int columnIndex) {
337 this.data.removeColumn(columnIndex);
338 fireDatasetChanged();
339 }
340
341 /**
342 * Removes a column from the dataset and sends a {@link DatasetChangeEvent}
343 * to all registered listeners.
344 *
345 * @param columnKey the column key.
346 *
347 * @see #removeRow(Comparable)
348 */
349 public void removeColumn(Comparable columnKey) {
350 this.data.removeColumn(columnKey);
351 fireDatasetChanged();
352 }
353
354 /**
355 * Clears all data from the dataset and sends a {@link DatasetChangeEvent}
356 * to all registered listeners.
357 */
358 public void clear() {
359 this.data.clear();
360 fireDatasetChanged();
361 }
362
363 /**
364 * Tests this dataset for equality with an arbitrary object.
365 *
366 * @param obj the object (<code>null</code> permitted).
367 *
368 * @return A boolean.
369 */
370 public boolean equals(Object obj) {
371
372 if (obj == this) {
373 return true;
374 }
375
376 if (!(obj instanceof CategoryDataset)) {
377 return false;
378 }
379
380 CategoryDataset that = (CategoryDataset) obj;
381 if (!getRowKeys().equals(that.getRowKeys())) {
382 return false;
383 }
384
385 if (!getColumnKeys().equals(that.getColumnKeys())) {
386 return false;
387 }
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 }