KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > velocity > tools > generic > NumberTool


1 /*
2  * Copyright 2003-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.velocity.tools.generic;
18
19 import java.text.DecimalFormat JavaDoc;
20 import java.text.DecimalFormatSymbols JavaDoc;
21 import java.text.NumberFormat JavaDoc;
22 import java.util.Locale JavaDoc;
23
24 /**
25  * Tool for working with {@link Number} in Velocity templates.
26  * It is useful for accessing and
27  * formatting arbitrary {@link Number} objects. Also
28  * the tool can be used to retrieve {@link NumberFormat} instances
29  * or make conversions to and from various number types.
30  * <p><pre>
31  * Example uses:
32  * $myNumber -> 13.55
33  * $number.format('currency',$myNumber) -> $13.55
34  * $number.format('integer',$myNumber) -> 13
35  *
36  * Example toolbox.xml config (if you want to use this with VelocityView):
37  * &lt;tool&gt;
38  * &lt;key&gt;number&lt;/key&gt;
39  * &lt;scope&gt;application&lt;/scope&gt;
40  * &lt;class&gt;org.apache.velocity.tools.generic.NumberTool&lt;/class&gt;
41  * &lt;/tool&gt;
42  * </pre></p>
43  *
44  * <p>This tool is entirely threadsafe, and has no instance members.
45  * It may be used in any scope (request, session, or application).
46  * As such, the methods are highly interconnected, and overriding
47  * key methods provides an easy way to create subclasses that use
48  * a non-default format or locale.</p>
49  *
50  * @author <a HREF="mailto:nathan@esha.com">Nathan Bubna</a>
51  * @author <a HREF="mailto:mkienenb@alaska.net">Mike Kienenberger</a>
52  * @since VelocityTools 1.2
53  * @version $Id: NumberTool.java,v 1.3 2004/02/18 20:11:07 nbubna Exp $
54  */

55 public class NumberTool
56 {
57
58     /**
59      * The default format to be used when none is specified.
60      */

61     public static final String JavaDoc DEFAULT_FORMAT = "default";
62
63     private static final int STYLE_NUMBER = 0;
64     private static final int STYLE_CURRENCY = 1;
65     private static final int STYLE_PERCENT = 2;
66     //NOTE: '3' belongs to a non-public "scientific" style
67
private static final int STYLE_INTEGER = 4;
68
69     /**
70      * Default constructor.
71      */

72     public NumberTool()
73     {
74         // do nothing
75
}
76
77
78     // ------------------------- default parameter access ----------------
79

80     /**
81      * This implementation returns the default locale. Subclasses
82      * may override this to return alternate locales. Please note that
83      * doing so will affect all formatting methods where no locale is
84      * specified in the parameters.
85      *
86      * @return the default {@link Locale}
87      */

88     public Locale JavaDoc getLocale()
89     {
90         return Locale.getDefault();
91     }
92
93     /**
94      * Return the pattern or style to be used for formatting numbers when none
95      * is specified. This implementation gives a 'default' number format.
96      * Subclasses may override this to provide a different default format.
97      *
98      * <p>NOTE: At some point in the future it may be feasible to configure
99      * this value via the toolbox definition, but at present, it is not possible
100      * to specify custom tool configurations there. For now you should just
101      * override this in a subclass to have a different default.</p>
102      */

103     public String JavaDoc getFormat()
104     {
105         return DEFAULT_FORMAT;
106     }
107
108
109     // ------------------------- formatting methods ---------------------------
110

111     /**
112      * Converts the specified object to a number and formats it according to
113      * the pattern or style returned by {@link #getFormat()}.
114      *
115      * @param obj the number object to be formatted
116      * @return the specified number formatted as a string
117      * @see #format(String format, Object obj, Locale locale)
118      */

119     public String JavaDoc format(Object JavaDoc obj)
120     {
121         return format(getFormat(), obj);
122     }
123
124     /**
125      * Converts the specified object to a number and returns
126      * a formatted string representing that number in the locale
127      * returned by {@link #getLocale()}.
128      *
129      * @param format the formatting instructions
130      * @param obj the number object to be formatted
131      * @return a formatted string for this locale representing the specified
132      * number or <code>null</code> if the parameters are invalid
133      * @see #format(String format, Object obj, Locale locale)
134      */

135     public String JavaDoc format(String JavaDoc format, Object JavaDoc obj)
136     {
137         return format(format, obj, getLocale());
138     }
139
140     /**
141      * Converts the specified object to a number and returns
142      * a formatted string representing that number in the specified
143      * {@link Locale}.
144      *
145      * @param format the custom or standard pattern to be used
146      * @param obj the number object to be formatted
147      * @param locale the {@link Locale} to be used when formatting
148      * @return a formatted string representing the specified number or
149      * <code>null</code> if the parameters are invalid
150      */

151     public String JavaDoc format(String JavaDoc format, Object JavaDoc obj, Locale JavaDoc locale)
152     {
153         Number JavaDoc number = toNumber(obj);
154         NumberFormat JavaDoc nf = getNumberFormat(format, locale);
155         if (number == null || nf == null)
156         {
157             return null;
158         }
159         return nf.format(number);
160     }
161
162     // -------------------------- NumberFormat creation methods --------------
163

164     /**
165      * Returns a {@link NumberFormat} instance for the specified
166      * format and {@link Locale}. If the format specified is a standard
167      * style pattern, then a number instance
168      * will be returned with the number style set to the
169      * specified style. If it is a custom format, then a customized
170      * {@link NumberFormat} will be returned.
171      *
172      * @param format the custom or standard formatting pattern to be used
173      * @param locale the {@link Locale} to be used
174      * @return an instance of {@link NumberFormat}
175      * @see NumberFormat
176      */

177     public NumberFormat JavaDoc getNumberFormat(String JavaDoc format, Locale JavaDoc locale)
178     {
179         if (format == null)
180         {
181             return null;
182         }
183
184         NumberFormat JavaDoc nf = null;
185         int style = getStyleAsInt(format);
186         if (style < 0)
187         {
188             // we have a custom format
189
nf = new DecimalFormat JavaDoc(format, new DecimalFormatSymbols JavaDoc(locale));
190         }
191         else
192         {
193             // we have a standard format
194
nf = getNumberFormat(style, locale);
195         }
196         return nf;
197     }
198
199     /**
200      * Returns a {@link NumberFormat} instance for the specified
201      * number style and {@link Locale}.
202      *
203      * @param numberStyle the number style (number will be ignored if this is
204      * less than zero or the number style is not recognized)
205      * @param locale the {@link Locale} to be used
206      * @return an instance of {@link NumberFormat} or <code>null</code>
207      * if an instance cannot be constructed with the given
208      * parameters
209      */

210     protected NumberFormat JavaDoc getNumberFormat(int numberStyle, Locale JavaDoc locale)
211     {
212         try
213         {
214             NumberFormat JavaDoc nf;
215             switch (numberStyle)
216             {
217                 case STYLE_NUMBER:
218                     nf = NumberFormat.getNumberInstance(locale);
219                     break;
220                 case STYLE_CURRENCY:
221                     nf = NumberFormat.getCurrencyInstance(locale);
222                     break;
223                 case STYLE_PERCENT:
224                     nf = NumberFormat.getPercentInstance(locale);
225                     break;
226                 case STYLE_INTEGER:
227                     nf = getIntegerInstance(locale);
228                     break;
229                 default:
230                     // invalid style was specified, return null
231
nf = null;
232             }
233             return nf;
234         }
235         catch (Exception JavaDoc suppressed)
236         {
237             // let it go...
238
return null;
239         }
240     }
241
242     /**
243      * Since we wish to continue supporting Java 1.3,
244      * for the present we cannot use Java 1.4's
245      * NumberFormat.getIntegerInstance(Locale) method.
246      * This method mimics that method (at least as of JDK1.4.2_01).
247      * It is private so that it can be removed later
248      * without a deprecation period.
249      */

250     private NumberFormat JavaDoc getIntegerInstance(Locale JavaDoc locale)
251     {
252         DecimalFormat JavaDoc format =
253             (DecimalFormat JavaDoc)NumberFormat.getNumberInstance(locale);
254         format.setMaximumFractionDigits(0);
255         format.setDecimalSeparatorAlwaysShown(false);
256         format.setParseIntegerOnly(true);
257         return format;
258     }
259
260     /**
261      * Checks a string to see if it matches one of the standard
262      * NumberFormat style patterns:
263      * NUMBER, CURRENCY, PERCENT, INTEGER, or DEFAULT.
264      * if it does it will return the integer constant for that pattern.
265      * if not, it will return -1.
266      *
267      * @see NumberFormat
268      * @param style the string to be checked
269      * @return the int identifying the style pattern
270      */

271     protected int getStyleAsInt(String JavaDoc style)
272     {
273         // avoid needlessly running through all the string comparisons
274
if (style == null || style.length() < 6 || style.length() > 8) {
275             return -1;
276         }
277         if (style.equalsIgnoreCase("default"))
278         {
279             //NOTE: java.text.NumberFormat returns "number" instances
280
// as the default (at least in Java 1.3 and 1.4).
281
return STYLE_NUMBER;
282         }
283         if (style.equalsIgnoreCase("number"))
284         {
285             return STYLE_NUMBER;
286         }
287         if (style.equalsIgnoreCase("currency"))
288         {
289             return STYLE_CURRENCY;
290         }
291         if (style.equalsIgnoreCase("percent"))
292         {
293             return STYLE_PERCENT;
294         }
295         if (style.equalsIgnoreCase("integer"))
296         {
297             return STYLE_INTEGER;
298         }
299         // ok, it's not any of the standard patterns
300
return -1;
301     }
302
303
304     // ------------------------- number conversion methods ---------------
305

306     /**
307      * Converts an object to an instance of {@link Number} using the
308      * format returned by {@link #getFormat()} and the {@link Locale}
309      * returned by {@link #getLocale()} if the object is not already
310      * an instance of Number.
311      *
312      * @param obj the number to convert
313      * @return the object as a {@link Number} or <code>null</code> if no
314      * conversion is possible
315      */

316     public Number JavaDoc toNumber(Object JavaDoc obj)
317     {
318         return toNumber(getFormat(), obj, getLocale());
319     }
320
321     /**
322      * Converts an object to an instance of {@link Number} using the
323      * specified format and the {@link Locale} returned by
324      * {@link #getLocale()} if the object is not already an instance
325      * of Number.
326      *
327      * @param format - the format the number is in
328      * @param obj - the number to convert
329      * @return the object as a {@link Number} or <code>null</code> if no
330      * conversion is possible
331      * @see #toNumber(String format, Object obj, Locale locale)
332      */

333     public Number JavaDoc toNumber(String JavaDoc format, Object JavaDoc obj)
334     {
335         return toNumber(format, obj, getLocale());
336     }
337
338     /**
339      * Converts an object to an instance of {@link Number} using the
340      * specified format and {@link Locale}if the object is not already
341      * an instance of Number.
342      *
343      * @param format - the format the number is in
344      * @param obj - the number to convert
345      * @param locale - the {@link Locale}
346      * @return the object as a {@link Number} or <code>null</code> if no
347      * conversion is possible
348      * @see NumberFormat#parse
349      */

350     public Number JavaDoc toNumber(String JavaDoc format, Object JavaDoc obj, Locale JavaDoc locale)
351     {
352         if (obj == null)
353         {
354             return null;
355         }
356         if (obj instanceof Number JavaDoc)
357         {
358             return (Number JavaDoc)obj;
359         }
360         try
361         {
362             NumberFormat JavaDoc parser = getNumberFormat(format, locale);
363             return parser.parse(String.valueOf(obj));
364         }
365         catch (Exception JavaDoc e)
366         {
367             return null;
368         }
369     }
370
371 }
372
Popular Tags