001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2007, 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 * AbstractXYItemLabelGenerator.java
029 * ---------------------------------
030 * (C) Copyright 2004-2007, by Object Refinery Limited.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): -;
034 *
035 * $Id: AbstractXYItemLabelGenerator.java,v 1.9.2.4 2007/01/25 11:54:23 mungady Exp $
036 *
037 * Changes
038 * -------
039 * 27-Feb-2004 : Version 1 (DG);
040 * 12-May-2004 : Moved default tool tip format to
041 * StandardXYToolTipGenerator (DG);
042 * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
043 * getYValue() (DG);
044 * 08-Oct-2004 : Modified createItemArray() method to handle null values (DG);
045 * 10-Jan-2005 : Updated createItemArray() to use x, y primitives if
046 * possible (DG);
047 * ------------- JFREECHART 1.0.x --------------------------------------------
048 * 26-Jan-2006 : Minor API doc update (DG);
049 * 25-Jan-2007 : Added new constructor and fixed bug in clone() method (DG);
050 *
051 */
052
053 package org.jfree.chart.labels;
054
055 import java.io.Serializable;
056 import java.text.DateFormat;
057 import java.text.MessageFormat;
058 import java.text.NumberFormat;
059 import java.util.Date;
060
061 import org.jfree.data.xy.XYDataset;
062 import org.jfree.util.ObjectUtilities;
063
064 /**
065 * A base class for creating item label generators.
066 */
067 public class AbstractXYItemLabelGenerator implements Cloneable, Serializable {
068
069 /** For serialization. */
070 private static final long serialVersionUID = 5869744396278660636L;
071
072 /** The item label format string. */
073 private String formatString;
074
075 /** A number formatter for the x value. */
076 private NumberFormat xFormat;
077
078 /** A date formatter for the x value. */
079 private DateFormat xDateFormat;
080
081 /** A formatter for the y value. */
082 private NumberFormat yFormat;
083
084 /** A date formatter for the y value. */
085 private DateFormat yDateFormat;
086
087 /** The string used to represent 'null' for the x-value. */
088 private String nullXString = "null";
089
090 /** The string used to represent 'null' for the y-value. */
091 private String nullYString = "null";
092
093 /**
094 * Creates an item label generator using default number formatters.
095 */
096 protected AbstractXYItemLabelGenerator() {
097 this("{2}", NumberFormat.getNumberInstance(),
098 NumberFormat.getNumberInstance());
099 }
100
101 /**
102 * Creates an item label generator using the specified number formatters.
103 *
104 * @param formatString the item label format string (<code>null</code>
105 * not permitted).
106 * @param xFormat the format object for the x values (<code>null</code>
107 * not permitted).
108 * @param yFormat the format object for the y values (<code>null</code>
109 * not permitted).
110 */
111 protected AbstractXYItemLabelGenerator(String formatString,
112 NumberFormat xFormat,
113 NumberFormat yFormat) {
114
115 if (formatString == null) {
116 throw new IllegalArgumentException("Null 'formatString' argument.");
117 }
118 if (xFormat == null) {
119 throw new IllegalArgumentException("Null 'xFormat' argument.");
120 }
121 if (yFormat == null) {
122 throw new IllegalArgumentException("Null 'yFormat' argument.");
123 }
124 this.formatString = formatString;
125 this.xFormat = xFormat;
126 this.yFormat = yFormat;
127
128 }
129
130 /**
131 * Creates an item label generator using the specified number formatters.
132 *
133 * @param formatString the item label format string (<code>null</code>
134 * not permitted).
135 * @param xFormat the format object for the x values (<code>null</code>
136 * permitted).
137 * @param yFormat the format object for the y values (<code>null</code>
138 * not permitted).
139 */
140 protected AbstractXYItemLabelGenerator(String formatString,
141 DateFormat xFormat,
142 NumberFormat yFormat) {
143
144 this(formatString, NumberFormat.getInstance(), yFormat);
145 this.xDateFormat = xFormat;
146
147 }
148
149 /**
150 * Creates an item label generator using the specified formatters (a
151 * number formatter for the x-values and a date formatter for the
152 * y-values).
153 *
154 * @param formatString the item label format string (<code>null</code>
155 * not permitted).
156 * @param xFormat the format object for the x values (<code>null</code>
157 * permitted).
158 * @param yFormat the format object for the y values (<code>null</code>
159 * not permitted).
160 *
161 * @since 1.0.4
162 */
163 protected AbstractXYItemLabelGenerator(String formatString,
164 NumberFormat xFormat, DateFormat yFormat) {
165
166 this(formatString, xFormat, NumberFormat.getInstance());
167 this.yDateFormat = yFormat;
168 }
169
170 /**
171 * Creates an item label generator using the specified number formatters.
172 *
173 * @param formatString the item label format string (<code>null</code>
174 * not permitted).
175 * @param xFormat the format object for the x values (<code>null</code>
176 * permitted).
177 * @param yFormat the format object for the y values (<code>null</code>
178 * not permitted).
179 */
180 protected AbstractXYItemLabelGenerator(String formatString,
181 DateFormat xFormat,
182 DateFormat yFormat) {
183
184 this(formatString, NumberFormat.getInstance(),
185 NumberFormat.getInstance());
186 this.xDateFormat = xFormat;
187 this.yDateFormat = yFormat;
188
189 }
190
191 /**
192 * Returns the format string (this controls the overall structure of the
193 * label).
194 *
195 * @return The format string (never <code>null</code>).
196 */
197 public String getFormatString() {
198 return this.formatString;
199 }
200
201 /**
202 * Returns the number formatter for the x-values.
203 *
204 * @return The number formatter (possibly <code>null</code>).
205 */
206 public NumberFormat getXFormat() {
207 return this.xFormat;
208 }
209
210 /**
211 * Returns the date formatter for the x-values.
212 *
213 * @return The date formatter (possibly <code>null</code>).
214 */
215 public DateFormat getXDateFormat() {
216 return this.xDateFormat;
217 }
218
219 /**
220 * Returns the number formatter for the y-values.
221 *
222 * @return The number formatter (possibly <code>null</code>).
223 */
224 public NumberFormat getYFormat() {
225 return this.yFormat;
226 }
227
228 /**
229 * Returns the date formatter for the y-values.
230 *
231 * @return The date formatter (possibly <code>null</code>).
232 */
233 public DateFormat getYDateFormat() {
234 return this.yDateFormat;
235 }
236
237 /**
238 * Generates a label string for an item in the dataset.
239 *
240 * @param dataset the dataset (<code>null</code> not permitted).
241 * @param series the series (zero-based index).
242 * @param item the item (zero-based index).
243 *
244 * @return The label (possibly <code>null</code>).
245 */
246 public String generateLabelString(XYDataset dataset, int series, int item) {
247 String result = null;
248 Object[] items = createItemArray(dataset, series, item);
249 result = MessageFormat.format(this.formatString, items);
250 return result;
251 }
252
253 /**
254 * Creates the array of items that can be passed to the
255 * {@link MessageFormat} class for creating labels.
256 *
257 * @param dataset the dataset (<code>null</code> not permitted).
258 * @param series the series (zero-based index).
259 * @param item the item (zero-based index).
260 *
261 * @return An array of three items from the dataset formatted as
262 * <code>String</code> objects (never <code>null</code>).
263 */
264 protected Object[] createItemArray(XYDataset dataset, int series,
265 int item) {
266 Object[] result = new Object[3];
267 result[0] = dataset.getSeriesKey(series).toString();
268
269 double x = dataset.getXValue(series, item);
270 if (Double.isNaN(x) && dataset.getX(series, item) == null) {
271 result[1] = this.nullXString;
272 }
273 else {
274 if (this.xDateFormat != null) {
275 result[1] = this.xDateFormat.format(new Date((long) x));
276 }
277 else {
278 result[1] = this.xFormat.format(x);
279 }
280 }
281
282 double y = dataset.getYValue(series, item);
283 if (Double.isNaN(y) && dataset.getY(series, item) == null) {
284 result[2] = this.nullYString;
285 }
286 else {
287 if (this.yDateFormat != null) {
288 result[2] = this.yDateFormat.format(new Date((long) y));
289 }
290 else {
291 result[2] = this.yFormat.format(y);
292 }
293 }
294 return result;
295 }
296
297 /**
298 * Tests this object for equality with an arbitrary object.
299 *
300 * @param obj the other object (<code>null</code> permitted).
301 *
302 * @return A boolean.
303 */
304 public boolean equals(Object obj) {
305 if (obj == this) {
306 return true;
307 }
308 if (!(obj instanceof AbstractXYItemLabelGenerator)) {
309 return false;
310 }
311 AbstractXYItemLabelGenerator that = (AbstractXYItemLabelGenerator) obj;
312 if (!this.formatString.equals(that.formatString)) {
313 return false;
314 }
315 if (!ObjectUtilities.equal(this.xFormat, that.xFormat)) {
316 return false;
317 }
318 if (!ObjectUtilities.equal(this.xDateFormat, that.xDateFormat)) {
319 return false;
320 }
321 if (!ObjectUtilities.equal(this.yFormat, that.yFormat)) {
322 return false;
323 }
324 if (!ObjectUtilities.equal(this.yDateFormat, that.yDateFormat)) {
325 return false;
326 }
327 return true;
328 }
329
330 /**
331 * Returns an independent copy of the generator.
332 *
333 * @return A clone.
334 *
335 * @throws CloneNotSupportedException if cloning is not supported.
336 */
337 public Object clone() throws CloneNotSupportedException {
338 AbstractXYItemLabelGenerator clone
339 = (AbstractXYItemLabelGenerator) super.clone();
340 if (this.xFormat != null) {
341 clone.xFormat = (NumberFormat) this.xFormat.clone();
342 }
343 if (this.yFormat != null) {
344 clone.yFormat = (NumberFormat) this.yFormat.clone();
345 }
346 if (this.xDateFormat != null) {
347 clone.xDateFormat = (DateFormat) this.xDateFormat.clone();
348 }
349 if (this.yDateFormat != null) {
350 clone.yDateFormat = (DateFormat) this.yDateFormat.clone();
351 }
352 return clone;
353 }
354
355 }