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