001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2013, 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 * [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 * DefaultIntervalCategoryDataset.java 029 * ----------------------------------- 030 * (C) Copyright 2002-2013, by Jeremy Bowman and Contributors. 031 * 032 * Original Author: Jeremy Bowman; 033 * Contributor(s): David Gilbert (for Object Refinery Limited); 034 * 035 * Changes 036 * ------- 037 * 29-Apr-2002 : Version 1, contributed by Jeremy Bowman (DG); 038 * 24-Oct-2002 : Amendments for changes made to the dataset interface (DG); 039 * ------------- JFREECHART 1.0.x --------------------------------------------- 040 * 08-Mar-2007 : Added equals() and clone() overrides (DG); 041 * 25-Feb-2008 : Fix for the special case where the dataset is empty, see bug 042 * 1897580 (DG) 043 * 18-Dec-2008 : Use ResourceBundleWrapper - see patch 1607918 by 044 * Jess Thrysoee (DG); 045 * 03-Jul-2013 : Use ParamChecks (DG); 046 * 047 */ 048 049package org.jfree.data.category; 050 051import java.util.ArrayList; 052import java.util.Arrays; 053import java.util.Collections; 054import java.util.List; 055import java.util.ResourceBundle; 056import org.jfree.chart.util.ParamChecks; 057 058import org.jfree.chart.util.ResourceBundleWrapper; 059import org.jfree.data.DataUtilities; 060import org.jfree.data.UnknownKeyException; 061import org.jfree.data.general.AbstractSeriesDataset; 062 063/** 064 * A convenience class that provides a default implementation of the 065 * {@link IntervalCategoryDataset} interface. 066 * <p> 067 * The standard constructor accepts data in a two dimensional array where the 068 * first dimension is the series, and the second dimension is the category. 069 */ 070public class DefaultIntervalCategoryDataset extends AbstractSeriesDataset 071 implements IntervalCategoryDataset { 072 073 /** The series keys. */ 074 private Comparable[] seriesKeys; 075 076 /** The category keys. */ 077 private Comparable[] categoryKeys; 078 079 /** Storage for the start value data. */ 080 private Number[][] startData; 081 082 /** Storage for the end value data. */ 083 private Number[][] endData; 084 085 /** 086 * Creates a new dataset using the specified data values and automatically 087 * generated series and category keys. 088 * 089 * @param starts the starting values for the intervals (<code>null</code> 090 * not permitted). 091 * @param ends the ending values for the intervals (<code>null</code> not 092 * permitted). 093 */ 094 public DefaultIntervalCategoryDataset(double[][] starts, double[][] ends) { 095 this(DataUtilities.createNumberArray2D(starts), 096 DataUtilities.createNumberArray2D(ends)); 097 } 098 099 /** 100 * Constructs a dataset and populates it with data from the array. 101 * <p> 102 * The arrays are indexed as data[series][category]. Series and category 103 * names are automatically generated - you can change them using the 104 * {@link #setSeriesKeys(Comparable[])} and 105 * {@link #setCategoryKeys(Comparable[])} methods. 106 * 107 * @param starts the start values data. 108 * @param ends the end values data. 109 */ 110 public DefaultIntervalCategoryDataset(Number[][] starts, Number[][] ends) { 111 this(null, null, starts, ends); 112 } 113 114 /** 115 * Constructs a DefaultIntervalCategoryDataset, populates it with data 116 * from the arrays, and uses the supplied names for the series. 117 * <p> 118 * Category names are generated automatically ("Category 1", "Category 2", 119 * etc). 120 * 121 * @param seriesNames the series names (if <code>null</code>, series names 122 * will be generated automatically). 123 * @param starts the start values data, indexed as data[series][category]. 124 * @param ends the end values data, indexed as data[series][category]. 125 */ 126 public DefaultIntervalCategoryDataset(String[] seriesNames, 127 Number[][] starts, 128 Number[][] ends) { 129 130 this(seriesNames, null, starts, ends); 131 132 } 133 134 /** 135 * Constructs a DefaultIntervalCategoryDataset, populates it with data 136 * from the arrays, and uses the supplied names for the series and the 137 * supplied objects for the categories. 138 * 139 * @param seriesKeys the series keys (if <code>null</code>, series keys 140 * will be generated automatically). 141 * @param categoryKeys the category keys (if <code>null</code>, category 142 * keys will be generated automatically). 143 * @param starts the start values data, indexed as data[series][category]. 144 * @param ends the end values data, indexed as data[series][category]. 145 */ 146 public DefaultIntervalCategoryDataset(Comparable[] seriesKeys, 147 Comparable[] categoryKeys, 148 Number[][] starts, 149 Number[][] ends) { 150 151 this.startData = starts; 152 this.endData = ends; 153 154 if (starts != null && ends != null) { 155 156 String baseName = "org.jfree.data.resources.DataPackageResources"; 157 ResourceBundle resources = ResourceBundleWrapper.getBundle( 158 baseName); 159 160 int seriesCount = starts.length; 161 if (seriesCount != ends.length) { 162 String errMsg = "DefaultIntervalCategoryDataset: the number " 163 + "of series in the start value dataset does " 164 + "not match the number of series in the end " 165 + "value dataset."; 166 throw new IllegalArgumentException(errMsg); 167 } 168 if (seriesCount > 0) { 169 170 // set up the series names... 171 if (seriesKeys != null) { 172 173 if (seriesKeys.length != seriesCount) { 174 throw new IllegalArgumentException( 175 "The number of series keys does not " 176 + "match the number of series in the data."); 177 } 178 179 this.seriesKeys = seriesKeys; 180 } 181 else { 182 String prefix = resources.getString( 183 "series.default-prefix") + " "; 184 this.seriesKeys = generateKeys(seriesCount, prefix); 185 } 186 187 // set up the category names... 188 int categoryCount = starts[0].length; 189 if (categoryCount != ends[0].length) { 190 String errMsg = "DefaultIntervalCategoryDataset: the " 191 + "number of categories in the start value " 192 + "dataset does not match the number of " 193 + "categories in the end value dataset."; 194 throw new IllegalArgumentException(errMsg); 195 } 196 if (categoryKeys != null) { 197 if (categoryKeys.length != categoryCount) { 198 throw new IllegalArgumentException( 199 "The number of category keys does not match " 200 + "the number of categories in the data."); 201 } 202 this.categoryKeys = categoryKeys; 203 } 204 else { 205 String prefix = resources.getString( 206 "categories.default-prefix") + " "; 207 this.categoryKeys = generateKeys(categoryCount, prefix); 208 } 209 210 } 211 else { 212 this.seriesKeys = new Comparable[0]; 213 this.categoryKeys = new Comparable[0]; 214 } 215 } 216 217 } 218 219 /** 220 * Returns the number of series in the dataset (possibly zero). 221 * 222 * @return The number of series in the dataset. 223 * 224 * @see #getRowCount() 225 * @see #getCategoryCount() 226 */ 227 @Override 228 public int getSeriesCount() { 229 int result = 0; 230 if (this.startData != null) { 231 result = this.startData.length; 232 } 233 return result; 234 } 235 236 /** 237 * Returns a series index. 238 * 239 * @param seriesKey the series key. 240 * 241 * @return The series index. 242 * 243 * @see #getRowIndex(Comparable) 244 * @see #getSeriesKey(int) 245 */ 246 public int getSeriesIndex(Comparable seriesKey) { 247 int result = -1; 248 for (int i = 0; i < this.seriesKeys.length; i++) { 249 if (seriesKey.equals(this.seriesKeys[i])) { 250 result = i; 251 break; 252 } 253 } 254 return result; 255 } 256 257 /** 258 * Returns the name of the specified series. 259 * 260 * @param series the index of the required series (zero-based). 261 * 262 * @return The name of the specified series. 263 * 264 * @see #getSeriesIndex(Comparable) 265 */ 266 @Override 267 public Comparable getSeriesKey(int series) { 268 if ((series >= getSeriesCount()) || (series < 0)) { 269 throw new IllegalArgumentException("No such series : " + series); 270 } 271 return this.seriesKeys[series]; 272 } 273 274 /** 275 * Sets the names of the series in the dataset. 276 * 277 * @param seriesKeys the new keys (<code>null</code> not permitted, the 278 * length of the array must match the number of series in the 279 * dataset). 280 * 281 * @see #setCategoryKeys(Comparable[]) 282 */ 283 public void setSeriesKeys(Comparable[] seriesKeys) { 284 ParamChecks.nullNotPermitted(seriesKeys, "seriesKeys"); 285 if (seriesKeys.length != getSeriesCount()) { 286 throw new IllegalArgumentException( 287 "The number of series keys does not match the data."); 288 } 289 this.seriesKeys = seriesKeys; 290 fireDatasetChanged(); 291 } 292 293 /** 294 * Returns the number of categories in the dataset. 295 * 296 * @return The number of categories in the dataset. 297 * 298 * @see #getColumnCount() 299 */ 300 public int getCategoryCount() { 301 int result = 0; 302 if (this.startData != null) { 303 if (getSeriesCount() > 0) { 304 result = this.startData[0].length; 305 } 306 } 307 return result; 308 } 309 310 /** 311 * Returns a list of the categories in the dataset. This method supports 312 * the {@link CategoryDataset} interface. 313 * 314 * @return A list of the categories in the dataset. 315 * 316 * @see #getRowKeys() 317 */ 318 @Override 319 public List getColumnKeys() { 320 // the CategoryDataset interface expects a list of categories, but 321 // we've stored them in an array... 322 if (this.categoryKeys == null) { 323 return new ArrayList(); 324 } 325 else { 326 return Collections.unmodifiableList(Arrays.asList( 327 this.categoryKeys)); 328 } 329 } 330 331 /** 332 * Sets the categories for the dataset. 333 * 334 * @param categoryKeys an array of objects representing the categories in 335 * the dataset. 336 * 337 * @see #getRowKeys() 338 * @see #setSeriesKeys(Comparable[]) 339 */ 340 public void setCategoryKeys(Comparable[] categoryKeys) { 341 ParamChecks.nullNotPermitted(categoryKeys, "categoryKeys"); 342 if (categoryKeys.length != getCategoryCount()) { 343 throw new IllegalArgumentException( 344 "The number of categories does not match the data."); 345 } 346 for (int i = 0; i < categoryKeys.length; i++) { 347 if (categoryKeys[i] == null) { 348 throw new IllegalArgumentException( 349 "DefaultIntervalCategoryDataset.setCategoryKeys(): " 350 + "null category not permitted."); 351 } 352 } 353 this.categoryKeys = categoryKeys; 354 fireDatasetChanged(); 355 } 356 357 /** 358 * Returns the data value for one category in a series. 359 * <P> 360 * This method is part of the CategoryDataset interface. Not particularly 361 * meaningful for this class...returns the end value. 362 * 363 * @param series The required series (zero based index). 364 * @param category The required category. 365 * 366 * @return The data value for one category in a series (null possible). 367 * 368 * @see #getEndValue(Comparable, Comparable) 369 */ 370 @Override 371 public Number getValue(Comparable series, Comparable category) { 372 int seriesIndex = getSeriesIndex(series); 373 if (seriesIndex < 0) { 374 throw new UnknownKeyException("Unknown 'series' key."); 375 } 376 int itemIndex = getColumnIndex(category); 377 if (itemIndex < 0) { 378 throw new UnknownKeyException("Unknown 'category' key."); 379 } 380 return getValue(seriesIndex, itemIndex); 381 } 382 383 /** 384 * Returns the data value for one category in a series. 385 * <P> 386 * This method is part of the CategoryDataset interface. Not particularly 387 * meaningful for this class...returns the end value. 388 * 389 * @param series the required series (zero based index). 390 * @param category the required category. 391 * 392 * @return The data value for one category in a series (null possible). 393 * 394 * @see #getEndValue(int, int) 395 */ 396 @Override 397 public Number getValue(int series, int category) { 398 return getEndValue(series, category); 399 } 400 401 /** 402 * Returns the start data value for one category in a series. 403 * 404 * @param series the required series. 405 * @param category the required category. 406 * 407 * @return The start data value for one category in a series 408 * (possibly <code>null</code>). 409 * 410 * @see #getStartValue(int, int) 411 */ 412 @Override 413 public Number getStartValue(Comparable series, Comparable category) { 414 int seriesIndex = getSeriesIndex(series); 415 if (seriesIndex < 0) { 416 throw new UnknownKeyException("Unknown 'series' key."); 417 } 418 int itemIndex = getColumnIndex(category); 419 if (itemIndex < 0) { 420 throw new UnknownKeyException("Unknown 'category' key."); 421 } 422 return getStartValue(seriesIndex, itemIndex); 423 } 424 425 /** 426 * Returns the start data value for one category in a series. 427 * 428 * @param series the required series (zero based index). 429 * @param category the required category. 430 * 431 * @return The start data value for one category in a series 432 * (possibly <code>null</code>). 433 * 434 * @see #getStartValue(Comparable, Comparable) 435 */ 436 @Override 437 public Number getStartValue(int series, int category) { 438 439 // check arguments... 440 if ((series < 0) || (series >= getSeriesCount())) { 441 throw new IllegalArgumentException( 442 "DefaultIntervalCategoryDataset.getValue(): " 443 + "series index out of range."); 444 } 445 446 if ((category < 0) || (category >= getCategoryCount())) { 447 throw new IllegalArgumentException( 448 "DefaultIntervalCategoryDataset.getValue(): " 449 + "category index out of range."); 450 } 451 452 // fetch the value... 453 return this.startData[series][category]; 454 455 } 456 457 /** 458 * Returns the end data value for one category in a series. 459 * 460 * @param series the required series. 461 * @param category the required category. 462 * 463 * @return The end data value for one category in a series (null possible). 464 * 465 * @see #getEndValue(int, int) 466 */ 467 @Override 468 public Number getEndValue(Comparable series, Comparable category) { 469 int seriesIndex = getSeriesIndex(series); 470 if (seriesIndex < 0) { 471 throw new UnknownKeyException("Unknown 'series' key."); 472 } 473 int itemIndex = getColumnIndex(category); 474 if (itemIndex < 0) { 475 throw new UnknownKeyException("Unknown 'category' key."); 476 } 477 return getEndValue(seriesIndex, itemIndex); 478 } 479 480 /** 481 * Returns the end data value for one category in a series. 482 * 483 * @param series the required series (zero based index). 484 * @param category the required category. 485 * 486 * @return The end data value for one category in a series (null possible). 487 * 488 * @see #getEndValue(Comparable, Comparable) 489 */ 490 @Override 491 public Number getEndValue(int series, int category) { 492 if ((series < 0) || (series >= getSeriesCount())) { 493 throw new IllegalArgumentException( 494 "DefaultIntervalCategoryDataset.getValue(): " 495 + "series index out of range."); 496 } 497 498 if ((category < 0) || (category >= getCategoryCount())) { 499 throw new IllegalArgumentException( 500 "DefaultIntervalCategoryDataset.getValue(): " 501 + "category index out of range."); 502 } 503 504 return this.endData[series][category]; 505 } 506 507 /** 508 * Sets the start data value for one category in a series. 509 * 510 * @param series the series (zero-based index). 511 * @param category the category. 512 * 513 * @param value The value. 514 * 515 * @see #setEndValue(int, Comparable, Number) 516 */ 517 public void setStartValue(int series, Comparable category, Number value) { 518 519 // does the series exist? 520 if ((series < 0) || (series > getSeriesCount() - 1)) { 521 throw new IllegalArgumentException( 522 "DefaultIntervalCategoryDataset.setValue: " 523 + "series outside valid range."); 524 } 525 526 // is the category valid? 527 int categoryIndex = getCategoryIndex(category); 528 if (categoryIndex < 0) { 529 throw new IllegalArgumentException( 530 "DefaultIntervalCategoryDataset.setValue: " 531 + "unrecognised category."); 532 } 533 534 // update the data... 535 this.startData[series][categoryIndex] = value; 536 fireDatasetChanged(); 537 538 } 539 540 /** 541 * Sets the end data value for one category in a series. 542 * 543 * @param series the series (zero-based index). 544 * @param category the category. 545 * 546 * @param value the value. 547 * 548 * @see #setStartValue(int, Comparable, Number) 549 */ 550 public void setEndValue(int series, Comparable category, Number value) { 551 552 // does the series exist? 553 if ((series < 0) || (series > getSeriesCount() - 1)) { 554 throw new IllegalArgumentException( 555 "DefaultIntervalCategoryDataset.setValue: " 556 + "series outside valid range."); 557 } 558 559 // is the category valid? 560 int categoryIndex = getCategoryIndex(category); 561 if (categoryIndex < 0) { 562 throw new IllegalArgumentException( 563 "DefaultIntervalCategoryDataset.setValue: " 564 + "unrecognised category."); 565 } 566 567 // update the data... 568 this.endData[series][categoryIndex] = value; 569 fireDatasetChanged(); 570 571 } 572 573 /** 574 * Returns the index for the given category. 575 * 576 * @param category the category (<code>null</code> not permitted). 577 * 578 * @return The index. 579 * 580 * @see #getColumnIndex(Comparable) 581 */ 582 public int getCategoryIndex(Comparable category) { 583 int result = -1; 584 for (int i = 0; i < this.categoryKeys.length; i++) { 585 if (category.equals(this.categoryKeys[i])) { 586 result = i; 587 break; 588 } 589 } 590 return result; 591 } 592 593 /** 594 * Generates an array of keys, by appending a space plus an integer 595 * (starting with 1) to the supplied prefix string. 596 * 597 * @param count the number of keys required. 598 * @param prefix the name prefix. 599 * 600 * @return An array of <i>prefixN</i> with N = { 1 .. count}. 601 */ 602 private Comparable[] generateKeys(int count, String prefix) { 603 Comparable[] result = new Comparable[count]; 604 String name; 605 for (int i = 0; i < count; i++) { 606 name = prefix + (i + 1); 607 result[i] = name; 608 } 609 return result; 610 } 611 612 /** 613 * Returns a column key. 614 * 615 * @param column the column index. 616 * 617 * @return The column key. 618 * 619 * @see #getRowKey(int) 620 */ 621 @Override 622 public Comparable getColumnKey(int column) { 623 return this.categoryKeys[column]; 624 } 625 626 /** 627 * Returns a column index. 628 * 629 * @param columnKey the column key (<code>null</code> not permitted). 630 * 631 * @return The column index. 632 * 633 * @see #getCategoryIndex(Comparable) 634 */ 635 @Override 636 public int getColumnIndex(Comparable columnKey) { 637 ParamChecks.nullNotPermitted(columnKey, "columnKey"); 638 return getCategoryIndex(columnKey); 639 } 640 641 /** 642 * Returns a row index. 643 * 644 * @param rowKey the row key. 645 * 646 * @return The row index. 647 * 648 * @see #getSeriesIndex(Comparable) 649 */ 650 @Override 651 public int getRowIndex(Comparable rowKey) { 652 return getSeriesIndex(rowKey); 653 } 654 655 /** 656 * Returns a list of the series in the dataset. This method supports the 657 * {@link CategoryDataset} interface. 658 * 659 * @return A list of the series in the dataset. 660 * 661 * @see #getColumnKeys() 662 */ 663 @Override 664 public List getRowKeys() { 665 // the CategoryDataset interface expects a list of series, but 666 // we've stored them in an array... 667 if (this.seriesKeys == null) { 668 return new java.util.ArrayList(); 669 } 670 else { 671 return Collections.unmodifiableList(Arrays.asList(this.seriesKeys)); 672 } 673 } 674 675 /** 676 * Returns the name of the specified series. 677 * 678 * @param row the index of the required row/series (zero-based). 679 * 680 * @return The name of the specified series. 681 * 682 * @see #getColumnKey(int) 683 */ 684 @Override 685 public Comparable getRowKey(int row) { 686 if ((row >= getRowCount()) || (row < 0)) { 687 throw new IllegalArgumentException( 688 "The 'row' argument is out of bounds."); 689 } 690 return this.seriesKeys[row]; 691 } 692 693 /** 694 * Returns the number of categories in the dataset. This method is part of 695 * the {@link CategoryDataset} interface. 696 * 697 * @return The number of categories in the dataset. 698 * 699 * @see #getCategoryCount() 700 * @see #getRowCount() 701 */ 702 @Override 703 public int getColumnCount() { 704 return this.categoryKeys.length; 705 } 706 707 /** 708 * Returns the number of series in the dataset (possibly zero). 709 * 710 * @return The number of series in the dataset. 711 * 712 * @see #getSeriesCount() 713 * @see #getColumnCount() 714 */ 715 @Override 716 public int getRowCount() { 717 return this.seriesKeys.length; 718 } 719 720 /** 721 * Tests this dataset for equality with an arbitrary object. 722 * 723 * @param obj the object (<code>null</code> permitted). 724 * 725 * @return A boolean. 726 */ 727 @Override 728 public boolean equals(Object obj) { 729 if (obj == this) { 730 return true; 731 } 732 if (!(obj instanceof DefaultIntervalCategoryDataset)) { 733 return false; 734 } 735 DefaultIntervalCategoryDataset that 736 = (DefaultIntervalCategoryDataset) obj; 737 if (!Arrays.equals(this.seriesKeys, that.seriesKeys)) { 738 return false; 739 } 740 if (!Arrays.equals(this.categoryKeys, that.categoryKeys)) { 741 return false; 742 } 743 if (!equal(this.startData, that.startData)) { 744 return false; 745 } 746 if (!equal(this.endData, that.endData)) { 747 return false; 748 } 749 // seem to be the same... 750 return true; 751 } 752 753 /** 754 * Returns a clone of this dataset. 755 * 756 * @return A clone. 757 * 758 * @throws CloneNotSupportedException if there is a problem cloning the 759 * dataset. 760 */ 761 @Override 762 public Object clone() throws CloneNotSupportedException { 763 DefaultIntervalCategoryDataset clone 764 = (DefaultIntervalCategoryDataset) super.clone(); 765 clone.categoryKeys = (Comparable[]) this.categoryKeys.clone(); 766 clone.seriesKeys = (Comparable[]) this.seriesKeys.clone(); 767 clone.startData = clone(this.startData); 768 clone.endData = clone(this.endData); 769 return clone; 770 } 771 772 /** 773 * Tests two double[][] arrays for equality. 774 * 775 * @param array1 the first array (<code>null</code> permitted). 776 * @param array2 the second arrray (<code>null</code> permitted). 777 * 778 * @return A boolean. 779 */ 780 private static boolean equal(Number[][] array1, Number[][] array2) { 781 if (array1 == null) { 782 return (array2 == null); 783 } 784 if (array2 == null) { 785 return false; 786 } 787 if (array1.length != array2.length) { 788 return false; 789 } 790 for (int i = 0; i < array1.length; i++) { 791 if (!Arrays.equals(array1[i], array2[i])) { 792 return false; 793 } 794 } 795 return true; 796 } 797 798 /** 799 * Clones a two dimensional array of <code>Number</code> objects. 800 * 801 * @param array the array (<code>null</code> not permitted). 802 * 803 * @return A clone of the array. 804 */ 805 private static Number[][] clone(Number[][] array) { 806 ParamChecks.nullNotPermitted(array, "array"); 807 Number[][] result = new Number[array.length][]; 808 for (int i = 0; i < array.length; i++) { 809 Number[] child = array[i]; 810 Number[] copychild = new Number[child.length]; 811 System.arraycopy(child, 0, copychild, 0, child.length); 812 result[i] = copychild; 813 } 814 return result; 815 } 816 817 /** 818 * Returns a list of the series in the dataset. 819 * 820 * @return A list of the series in the dataset. 821 * 822 * @deprecated Use {@link #getRowKeys()} instead. 823 */ 824 public List getSeries() { 825 if (this.seriesKeys == null) { 826 return new java.util.ArrayList(); 827 } 828 else { 829 return Collections.unmodifiableList(Arrays.asList(this.seriesKeys)); 830 } 831 } 832 833 /** 834 * Returns a list of the categories in the dataset. 835 * 836 * @return A list of the categories in the dataset. 837 * 838 * @deprecated Use {@link #getColumnKeys()} instead. 839 */ 840 public List getCategories() { 841 return getColumnKeys(); 842 } 843 844 /** 845 * Returns the item count. 846 * 847 * @return The item count. 848 * 849 * @deprecated Use {@link #getCategoryCount()} instead. 850 */ 851 public int getItemCount() { 852 return this.categoryKeys.length; 853 } 854 855}