1 /* ===========================================================
2 * JFreeChart : a free chart library for the Java(tm) platform
3 * ===========================================================
4 *
5 * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
6 *
7 * Project Info: http://www.jfree.org/jfreechart/index.html
8 *
9 * This library is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 * License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 * USA.
23 *
24 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25 * in the United States and other countries.]
26 *
27 * ---------------------------
28 * DefaultCategoryDataset.java
29 * ---------------------------
30 * (C) Copyright 2002-2007, by Object Refinery Limited.
31 *
32 * Original Author: David Gilbert (for Object Refinery Limited);
33 * Contributor(s): -;
34 *
35 * Changes
36 * -------
37 * 21-Jan-2003 : Added standard header, and renamed DefaultCategoryDataset (DG);
38 * 13-Mar-2003 : Inserted DefaultKeyedValues2DDataset into class hierarchy (DG);
39 * 06-Oct-2003 : Added incrementValue() method (DG);
40 * 05-Apr-2004 : Added clear() method (DG);
41 * 18-Aug-2004 : Moved from org.jfree.data --> org.jfree.data.category (DG);
42 * ------------- JFREECHART 1.0.x ---------------------------------------------
43 * 26-Feb-2007 : Updated API docs (DG);
44 * 08-Mar-2007 : Implemented clone() (DG);
45 * 09-May-2008 : Implemented PublicCloneable (DG);
46 *
47 */
48
49 package org.jfree.data.category;
50
51 import java.io.Serializable;
52 import java.util.List;
53
54 import org.jfree.data.DefaultKeyedValues2D;
55 import org.jfree.data.UnknownKeyException;
56 import org.jfree.data.general.AbstractDataset;
57 import org.jfree.data.general.DatasetChangeEvent;
58 import org.jfree.util.PublicCloneable;
59
60 /**
61 * A default implementation of the {@link CategoryDataset} interface.
62 */
63 public class DefaultCategoryDataset extends AbstractDataset
64 implements CategoryDataset, PublicCloneable, Serializable {
65
66 /** For serialization. */
67 private static final long serialVersionUID = -8168173757291644622L;
68
69 /** A storage structure for the data. */
70 private DefaultKeyedValues2D data;
71
72 /**
73 * Creates a new (empty) dataset.
74 */
75 public DefaultCategoryDataset() {
76 this.data = new DefaultKeyedValues2D();
77 }
78
79 /**
80 * Returns the number of rows in the table.
81 *
82 * @return The row count.
83 *
84 * @see #getColumnCount()
85 */
86 public int getRowCount() {
87 return this.data.getRowCount();
88 }
89
90 /**
91 * Returns the number of columns in the table.
92 *
93 * @return The column count.
94 *
95 * @see #getRowCount()
96 */
97 public int getColumnCount() {
98 return this.data.getColumnCount();
99 }
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 }