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 }