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 }