    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2006, 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     * AbstractCategoryItemLabelGenerator.java
    029     * ---------------------------------------
    030     * (C) Copyright 2005, 2006, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * $Id: AbstractCategoryItemLabelGenerator.java,v 1.6.2.2 2006/05/03 15:44:02 mungady Exp $
    036     *
    037     * Changes
    038     * -------
    039     * 11-May-2004 : Version 1, distilled from StandardCategoryLabelGenerator (DG);
    040     * 31-Jan-2005 : Added methods to return row and column labels (DG);
    041     * 17-May-2005 : Added percentage to item array (DG);
    042     * ------------- JFREECHART 1.0.0 ---------------------------------------------
    043     * 03-May-2006 : Added new constructor (DG);
    044     */
    045
    046    package org.jfree.chart.labels;
    047
    048    import java.io.Serializable;
    049    import java.text.DateFormat;
    050    import java.text.MessageFormat;
    051    import java.text.NumberFormat;
    052
    053    import org.jfree.data.DataUtilities;
    054    import org.jfree.data.category.CategoryDataset;
    055    import org.jfree.util.ObjectUtilities;
    056    import org.jfree.util.PublicCloneable;
    057
    058    /**
    059     * A base class that can be used to create a label or tooltip generator that
    060     * can be assigned to a
    061     * {@link org.jfree.chart.renderer.category.CategoryItemRenderer}.
    062     */
    063    public abstract class AbstractCategoryItemLabelGenerator
    064                    implements PublicCloneable, Cloneable, Serializable {
    065
    066        /** For serialization. */
    067        private static final long serialVersionUID = -7108591260223293197L;
    068
    069        /**
    070         * The label format string used by a <code>MessageFormat</code> object to
    071         * combine the standard items:  {0} = series name, {1} = category,
    072         * {2} = value, {3} = value as a percentage of the column total.
    073         */
    074        private String labelFormat;
    075
    076        /** The string used to represent a null value. */
    077        private String nullValueString;
    078
    079        /**
    080         * A number formatter used to preformat the value before it is passed to
    081         * the MessageFormat object.
    082         */
    083        private NumberFormat numberFormat;
    084
    085        /**
    086         * A date formatter used to preformat the value before it is passed to the
    087         * MessageFormat object.
    088         */
    089        private DateFormat dateFormat;
    090
    091        /**
    092         * A number formatter used to preformat the percentage value before it is
    093         * passed to the MessageFormat object.
    094         */
    095        private NumberFormat percentFormat;
    096
    097        /**
    098         * Creates a label generator with the specified number formatter.
    099         *
    100         * @param labelFormat  the label format string (<code>null</code> not
    101         *                     permitted).
    102         * @param formatter  the number formatter (<code>null</code> not permitted).
    103         */
    104        protected AbstractCategoryItemLabelGenerator(String labelFormat,
    105                                                     NumberFormat formatter) {
    106            this(labelFormat, formatter, NumberFormat.getPercentInstance());
    107        }
    108
    109        /**
    110         * Creates a label generator with the specified number formatter.
    111         *
    112         * @param labelFormat  the label format string (<code>null</code> not
    113         *                     permitted).
    114         * @param formatter  the number formatter (<code>null</code> not permitted).
    115         * @param percentFormatter  the percent formatter (<code>null</code> not
    116         *     permitted).
    117         *
    118         * @since 1.0.2
    119         */
    120        protected AbstractCategoryItemLabelGenerator(String labelFormat,
    121                NumberFormat formatter, NumberFormat percentFormatter) {
    122            if (labelFormat == null) {
    123                throw new IllegalArgumentException("Null 'labelFormat' argument.");
    124            }
    125            if (formatter == null) {
    126                throw new IllegalArgumentException("Null 'formatter' argument.");
    127            }
    128            if (percentFormatter == null) {
    129                throw new IllegalArgumentException(
    130                        "Null 'percentFormatter' argument.");
    131            }
    132            this.labelFormat = labelFormat;
    133            this.numberFormat = formatter;
    134            this.percentFormat = percentFormatter;
    135            this.dateFormat = null;
    136            this.nullValueString = "-";
    137        }
    138
    139        /**
    140         * Creates a label generator with the specified date formatter.
    141         *
    142         * @param labelFormat  the label format string (<code>null</code> not
    143         *                     permitted).
    144         * @param formatter  the date formatter (<code>null</code> not permitted).
    145         */
    146        protected AbstractCategoryItemLabelGenerator(String labelFormat,
    147                                                     DateFormat formatter) {
    148            if (labelFormat == null) {
    149                throw new IllegalArgumentException("Null 'labelFormat' argument.");
    150            }
    151            if (formatter == null) {
    152                throw new IllegalArgumentException("Null 'formatter' argument.");
    153            }
    154            this.labelFormat = labelFormat;
    155            this.numberFormat = null;
    156            this.percentFormat = NumberFormat.getPercentInstance();
    157            this.dateFormat = formatter;
    158            this.nullValueString = "-";
    159        }
    160
    161        /**
    162         * Generates a label for the specified row.
    163         *
    164         * @param dataset  the dataset (<code>null</code> not permitted).
    165         * @param row  the row index (zero-based).
    166         *
    167         * @return The label.
    168         */
    169        public String generateRowLabel(CategoryDataset dataset, int row) {
    170            return dataset.getRowKey(row).toString();
    171        }
    172
    173        /**
    174         * Generates a label for the specified row.
    175         *
    176         * @param dataset  the dataset (<code>null</code> not permitted).
    177         * @param column  the column index (zero-based).
    178         *
    179         * @return The label.
    180         */
    181        public String generateColumnLabel(CategoryDataset dataset, int column) {
    182            return dataset.getColumnKey(column).toString();
    183        }
    184
    185        /**
    186         * Returns the label format string.
    187         *
    188         * @return The label format string (never <code>null</code>).
    189         */
    190        public String getLabelFormat() {
    191            return this.labelFormat;
    192        }
    193
    194        /**
    195         * Returns the number formatter.
    196         *
    197         * @return The number formatter (possibly <code>null</code>).
    198         */
    199        public NumberFormat getNumberFormat() {
    200            return this.numberFormat;
    201        }
    202
    203        /**
    204         * Returns the date formatter.
    205         *
    206         * @return The date formatter (possibly <code>null</code>).
    207         */
    208        public DateFormat getDateFormat() {
    209            return this.dateFormat;
    210        }
    211
    212        /**
    213         * Generates a for the specified item.
    214         *
    215         * @param dataset  the dataset (<code>null</code> not permitted).
    216         * @param row  the row index (zero-based).
    217         * @param column  the column index (zero-based).
    218         *
    219         * @return The label (possibly <code>null</code>).
    220         */
    221        protected String generateLabelString(CategoryDataset dataset,
    222                                             int row, int column) {
    223            if (dataset == null) {
    224                throw new IllegalArgumentException("Null 'dataset' argument.");
    225            }
    226            String result = null;
    227            Object[] items = createItemArray(dataset, row, column);
    228            result = MessageFormat.format(this.labelFormat, items);
    229            return result;
    230
    231        }
    232
    233        /**
    234         * Creates the array of items that can be passed to the
    235         * {@link MessageFormat} class for creating labels.
    236         *
    237         * @param dataset  the dataset (<code>null</code> not permitted).
    238         * @param row  the row index (zero-based).
    239         * @param column  the column index (zero-based).
    240         *
    241         * @return The items (never <code>null</code>).
    242         */
    243        protected Object[] createItemArray(CategoryDataset dataset,
    244                                           int row, int column) {
    245            Object[] result = new Object[4];
    246            result[0] = dataset.getRowKey(row).toString();
    247            result[1] = dataset.getColumnKey(column).toString();
    248            Number value = dataset.getValue(row, column);
    249            if (value != null) {
    250                if (this.numberFormat != null) {
    251                    result[2] = this.numberFormat.format(value);
    252                }
    253                else if (this.dateFormat != null) {
    254                    result[2] = this.dateFormat.format(value);
    255                }
    256            }
    257            else {
    258                result[2] = this.nullValueString;
    259            }
    260            if (value != null) {
    261                double total = DataUtilities.calculateColumnTotal(dataset, column);
    262                double percent = value.doubleValue() / total;
    263                result[3] = this.percentFormat.format(percent);
    264            }
    265
    266            return result;
    267        }
    268
    269        /**
    270         * Tests this object for equality with an arbitrary object.
    271         *
    272         * @param obj  the other object (<code>null</code> permitted).
    273         *
    274         * @return A boolean.
    275         */
    276        public boolean equals(Object obj) {
    277            if (obj == this) {
    278                return true;
    279            }
    280            if (!(obj instanceof AbstractCategoryItemLabelGenerator)) {
    281                return false;
    282            }
    283
    284            AbstractCategoryItemLabelGenerator that
    285                = (AbstractCategoryItemLabelGenerator) obj;
    286            if (!this.labelFormat.equals(that.labelFormat)) {
    287                return false;
    288            }
    289            if (!ObjectUtilities.equal(this.dateFormat, that.dateFormat)) {
    290                return false;
    291            }
    292            if (!ObjectUtilities.equal(this.numberFormat, that.numberFormat)) {
    293                return false;
    294            }
    295            return true;
    296        }
    297
    298        /**
    299         * Returns an independent copy of the generator.
    300         *
    301         * @return A clone.
    302         *
    303         * @throws CloneNotSupportedException  should not happen.
    304         */
    305        public Object clone() throws CloneNotSupportedException {
    306            AbstractCategoryItemLabelGenerator clone
    307                = (AbstractCategoryItemLabelGenerator) super.clone();
    308            if (this.numberFormat != null) {
    309                clone.numberFormat = (NumberFormat) this.numberFormat.clone();
    310            }
    311            if (this.dateFormat != null) {
    312                clone.dateFormat = (DateFormat) this.dateFormat.clone();
    313            }
    314            return clone;
    315        }
    316
    317    }