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