001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2008, 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-2008, by Object Refinery Limited.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): -;
034 *
035 * Changes
036 * -------
037 * 27-Feb-2004 : Version 1 (DG);
038 * 12-May-2004 : Moved default tool tip format to
039 * StandardXYToolTipGenerator (DG);
040 * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
041 * getYValue() (DG);
042 * 08-Oct-2004 : Modified createItemArray() method to handle null values (DG);
043 * 10-Jan-2005 : Updated createItemArray() to use x, y primitives if
044 * possible (DG);
045 * ------------- JFREECHART 1.0.x --------------------------------------------
046 * 26-Jan-2006 : Minor API doc update (DG);
047 * 25-Jan-2007 : Added new constructor and fixed bug in clone() method (DG);
048 * 16-Oct-2007 : Removed redundant code (DG);
049 * 23-Nov-2007 : Implemented hashCode() (DG);
050 * 26-May-2008 : Added accessor methods for nullYString and updated equals()
051 * method (DG);
052 *
053 */
054
055 package org.jfree.chart.labels;
056
057 import java.io.Serializable;
058 import java.text.DateFormat;
059 import java.text.MessageFormat;
060 import java.text.NumberFormat;
061 import java.util.Date;
062
063 import org.jfree.chart.HashUtilities;
064 import org.jfree.data.xy.XYDataset;
065 import org.jfree.util.ObjectUtilities;
066
067 /**
068 * A base class for creating item label generators.
069 */
070 public class AbstractXYItemLabelGenerator implements Cloneable, Serializable {
071
072 /** For serialization. */
073 private static final long serialVersionUID = 5869744396278660636L;
074
075 /** The item label format string. */
076 private String formatString;
077
078 /** A number formatter for the x value. */
079 private NumberFormat xFormat;
080
081 /** A date formatter for the x value. */
082 private DateFormat xDateFormat;
083
084 /** A formatter for the y value. */
085 private NumberFormat yFormat;
086
087 /** A date formatter for the y value. */
088 private DateFormat yDateFormat;
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 * Returns the string representing a null value.
255 *
256 * @return The string representing a null value.
257 *
258 * @since 1.0.10
259 */
260 public String getNullYString() {
261 return this.nullYString;
262 }
263
264 /**
265 * Creates the array of items that can be passed to the
266 * {@link MessageFormat} class for creating labels.
267 *
268 * @param dataset the dataset (<code>null</code> not permitted).
269 * @param series the series (zero-based index).
270 * @param item the item (zero-based index).
271 *
272 * @return An array of three items from the dataset formatted as
273 * <code>String</code> objects (never <code>null</code>).
274 */
275 protected Object[] createItemArray(XYDataset dataset, int series,
276 int item) {
277 Object[] result = new Object[3];
278 result[0] = dataset.getSeriesKey(series).toString();
279
280 double x = dataset.getXValue(series, item);
281 if (this.xDateFormat != null) {
282 result[1] = this.xDateFormat.format(new Date((long) x));
283 }
284 else {
285 result[1] = this.xFormat.format(x);
286 }
287
288 double y = dataset.getYValue(series, item);
289 if (Double.isNaN(y) && dataset.getY(series, item) == null) {
290 result[2] = this.nullYString;
291 }
292 else {
293 if (this.yDateFormat != null) {
294 result[2] = this.yDateFormat.format(new Date((long) y));
295 }
296 else {
297 result[2] = this.yFormat.format(y);
298 }
299 }
300 return result;
301 }
302
303 /**
304 * Tests this object for equality with an arbitrary object.
305 *
306 * @param obj the other object (<code>null</code> permitted).
307 *
308 * @return A boolean.
309 */
310 public boolean equals(Object obj) {
311 if (obj == this) {
312 return true;
313 }
314 if (!(obj instanceof AbstractXYItemLabelGenerator)) {
315 return false;
316 }
317 AbstractXYItemLabelGenerator that = (AbstractXYItemLabelGenerator) obj;
318 if (!this.formatString.equals(that.formatString)) {
319 return false;
320 }
321 if (!ObjectUtilities.equal(this.xFormat, that.xFormat)) {
322 return false;
323 }
324 if (!ObjectUtilities.equal(this.xDateFormat, that.xDateFormat)) {
325 return false;
326 }
327 if (!ObjectUtilities.equal(this.yFormat, that.yFormat)) {
328 return false;
329 }
330 if (!ObjectUtilities.equal(this.yDateFormat, that.yDateFormat)) {
331 return false;
332 }
333 if (!this.nullYString.equals(that.nullYString)) {
334 return false;
335 }
336 return true;
337 }
338
339 /**
340 * Returns a hash code for this instance.
341 *
342 * @return A hash code.
343 */
344 public int hashCode() {
345 int result = 127;
346 result = HashUtilities.hashCode(result, this.formatString);
347 result = HashUtilities.hashCode(result, this.xFormat);
348 result = HashUtilities.hashCode(result, this.xDateFormat);
349 result = HashUtilities.hashCode(result, this.yFormat);
350 result = HashUtilities.hashCode(result, this.yDateFormat);
351 return result;
352 }
353
354 /**
355 * Returns an independent copy of the generator.
356 *
357 * @return A clone.
358 *
359 * @throws CloneNotSupportedException if cloning is not supported.
360 */
361 public Object clone() throws CloneNotSupportedException {
362 AbstractXYItemLabelGenerator clone
363 = (AbstractXYItemLabelGenerator) super.clone();
364 if (this.xFormat != null) {
365 clone.xFormat = (NumberFormat) this.xFormat.clone();
366 }
367 if (this.yFormat != null) {
368 clone.yFormat = (NumberFormat) this.yFormat.clone();
369 }
370 if (this.xDateFormat != null) {
371 clone.xDateFormat = (DateFormat) this.xDateFormat.clone();
372 }
373 if (this.yDateFormat != null) {
374 clone.yDateFormat = (DateFormat) this.yDateFormat.clone();
375 }
376 return clone;
377 }
378
379 }