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