    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     * AbstractPieItemLabelGenerator.java
    029     * ----------------------------------
    030     * (C) Copyright 2004-2006, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * $Id: AbstractPieItemLabelGenerator.java,v 1.5.2.2 2006/05/03 10:46:36 mungady Exp $
    036     *
    037     * Changes
    038     * -------
    039     * 09-Nov-2004 : Version 1, draws out code from StandardPieItemLabelGenerator
    040     *               and StandardPieToolTipGenerator (DG);
    041     * ------------- JFREECHART 1.0.0 ---------------------------------------------
    042     * 03-May-2006 : Fixed bug 1480978, a problem in the clone() method (DG);
    043     *
    044     */
    045
    046    package org.jfree.chart.labels;
    047
    048    import java.io.Serializable;
    049    import java.text.MessageFormat;
    050    import java.text.NumberFormat;
    051
    052    import org.jfree.data.general.DatasetUtilities;
    053    import org.jfree.data.general.PieDataset;
    054
    055    /**
    056     * A base class used for generating pie chart item labels.
    057     */
    058    public class AbstractPieItemLabelGenerator implements Serializable {
    059
    060        /** For serialization. */
    061        private static final long serialVersionUID = 7347703325267846275L;
    062
    063        /** The label format string. */
    064        private String labelFormat;
    065
    066        /** A number formatter for the value. */
    067        private NumberFormat numberFormat;
    068
    069        /** A number formatter for the percentage. */
    070        private NumberFormat percentFormat;
    071
    072        /**
    073         * Creates an item label generator using the specified number formatters.
    074         *
    075         * @param labelFormat  the label format string (<code>null</code> not
    076         *                     permitted).
    077         * @param numberFormat  the format object for the values (<code>null</code>
    078         *                      not permitted).
    079         * @param percentFormat  the format object for the percentages
    080         *                       (<code>null</code> not permitted).
    081         */
    082        protected AbstractPieItemLabelGenerator(String labelFormat,
    083                                                NumberFormat numberFormat,
    084                                                NumberFormat percentFormat) {
    085
    086            if (labelFormat == null) {
    087                throw new IllegalArgumentException("Null 'labelFormat' argument.");
    088            }
    089            if (numberFormat == null) {
    090                throw new IllegalArgumentException("Null 'numberFormat' argument.");
    091            }
    092            if (percentFormat == null) {
    093                throw new IllegalArgumentException(
    094                    "Null 'percentFormat' argument."
    095                );
    096            }
    097            this.labelFormat = labelFormat;
    098            this.numberFormat = numberFormat;
    099            this.percentFormat = percentFormat;
    100
    101        }
    102
    103        /**
    104         * Returns the label format string.
    105         *
    106         * @return The label format string (never <code>null</code>).
    107         */
    108        public String getLabelFormat() {
    109            return this.labelFormat;
    110        }
    111
    112        /**
    113         * Returns the number formatter.
    114         *
    115         * @return The formatter (never <code>null</code>).
    116         */
    117        public NumberFormat getNumberFormat() {
    118            return this.numberFormat;
    119        }
    120
    121        /**
    122         * Returns the percent formatter.
    123         *
    124         * @return The formatter (never <code>null</code>).
    125         */
    126        public NumberFormat getPercentFormat() {
    127            return this.percentFormat;
    128        }
    129
    130        /**
    131         * Creates the array of items that can be passed to the
    132         * {@link MessageFormat} class for creating labels.  The returned array
    133         * contains four values:
    134         * <ul>
    135         * <li>result[0] = the section key converted to a <code>String</code>;</li>
    136         * <li>result[1] = the formatted data value;</li>
    137         * <li>result[2] = the formatted percentage (of the total);</li>
    138         * <li>result[3] = the formatted total value.</li>
    139         * </ul>
    140         *
    141         * @param dataset  the dataset (<code>null</code> not permitted).
    142         * @param key  the key (<code>null</code> not permitted).
    143         *
    144         * @return The items (never <code>null</code>).
    145         */
    146        protected Object[] createItemArray(PieDataset dataset, Comparable key) {
    147            Object[] result = new Object[4];
    148            double total = DatasetUtilities.calculatePieDatasetTotal(dataset);
    149            result[0] = key.toString();
    150            Number value = dataset.getValue(key);
    151            if (value != null) {
    152                result[1] = this.numberFormat.format(value);
    153            }
    154            else {
    155                result[1] = "null";
    156            }
    157            double percent = 0.0;
    158            if (value != null) {
    159                double v = value.doubleValue();
    160                if (v > 0.0) {
    161                    percent = v / total;
    162                }
    163            }
    164            result[2] = this.percentFormat.format(percent);
    165            result[3] = this.numberFormat.format(total);
    166            return result;
    167        }
    168
    169        /**
    170         * Generates a label for a pie section.
    171         *
    172         * @param dataset  the dataset (<code>null</code> not permitted).
    173         * @param key  the section key (<code>null</code> not permitted).
    174         *
    175         * @return The label (possibly <code>null</code>).
    176         */
    177        protected String generateSectionLabel(PieDataset dataset, Comparable key) {
    178            String result = null;
    179            if (dataset != null) {
    180                Object[] items = createItemArray(dataset, key);
    181                result = MessageFormat.format(this.labelFormat, items);
    182            }
    183            return result;
    184        }
    185
    186        /**
    187         * Tests the generator for equality with an arbitrary object.
    188         *
    189         * @param obj  the object to test against (<code>null</code> permitted).
    190         *
    191         * @return A boolean.
    192         */
    193        public boolean equals(Object obj) {
    194            if (obj == this) {
    195                return true;
    196            }
    197            if (!(obj instanceof AbstractPieItemLabelGenerator)) {
    198                return false;
    199            }
    200
    201            AbstractPieItemLabelGenerator that
    202                = (AbstractPieItemLabelGenerator) obj;
    203            if (!this.labelFormat.equals(that.labelFormat)) {
    204                return false;
    205            }
    206            if (!this.numberFormat.equals(that.numberFormat)) {
    207                return false;
    208            }
    209            if (!this.percentFormat.equals(that.percentFormat)) {
    210                return false;
    211            }
    212            return true;
    213
    214        }
    215
    216        /**
    217         * Returns an independent copy of the generator.
    218         *
    219         * @return A clone.
    220         *
    221         * @throws CloneNotSupportedException  should not happen.
    222         */
    223        public Object clone() throws CloneNotSupportedException {
    224            AbstractPieItemLabelGenerator clone
    225                = (AbstractPieItemLabelGenerator) super.clone();
    226            if (this.numberFormat != null) {
    227                clone.numberFormat = (NumberFormat) this.numberFormat.clone();
    228            }
    229            if (this.percentFormat != null) {
    230                clone.percentFormat = (NumberFormat) this.percentFormat.clone();
    231            }
    232            return clone;
    233        }
    234
    235    }