KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > taglibs > standard > tag > common > fmt > FormatNumberSupport


1 /*
2  * Copyright 1999-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.taglibs.standard.tag.common.fmt;
18
19 import java.io.IOException JavaDoc;
20 import java.lang.reflect.Method JavaDoc;
21 import java.text.DecimalFormat JavaDoc;
22 import java.text.DecimalFormatSymbols JavaDoc;
23 import java.text.NumberFormat JavaDoc;
24 import java.util.Locale JavaDoc;
25
26 import javax.servlet.jsp.JspException JavaDoc;
27 import javax.servlet.jsp.JspTagException JavaDoc;
28 import javax.servlet.jsp.PageContext JavaDoc;
29 import javax.servlet.jsp.tagext.BodyTagSupport JavaDoc;
30
31 import org.apache.taglibs.standard.resources.Resources;
32 import org.apache.taglibs.standard.tag.common.core.Util;
33
34 /**
35  * Support for tag handlers for <formatNumber>, the number
36  * formatting tag in JSTL 1.0.
37  *
38  * @author Jan Luehe
39  */

40
41 public abstract class FormatNumberSupport extends BodyTagSupport JavaDoc {
42
43     //*********************************************************************
44
// Private constants
45

46     private static final Class JavaDoc[] GET_INSTANCE_PARAM_TYPES =
47     new Class JavaDoc[] { String JavaDoc.class };
48     private static final String JavaDoc NUMBER = "number";
49     private static final String JavaDoc CURRENCY = "currency";
50     private static final String JavaDoc PERCENT = "percent";
51
52
53     //*********************************************************************
54
// Protected state
55

56     protected Object JavaDoc value; // 'value' attribute
57
protected boolean valueSpecified; // status
58
protected String JavaDoc type; // 'type' attribute
59
protected String JavaDoc pattern; // 'pattern' attribute
60
protected String JavaDoc currencyCode; // 'currencyCode' attribute
61
protected String JavaDoc currencySymbol; // 'currencySymbol' attribute
62
protected boolean isGroupingUsed; // 'groupingUsed' attribute
63
protected boolean groupingUsedSpecified;
64     protected int maxIntegerDigits; // 'maxIntegerDigits' attribute
65
protected boolean maxIntegerDigitsSpecified;
66     protected int minIntegerDigits; // 'minIntegerDigits' attribute
67
protected boolean minIntegerDigitsSpecified;
68     protected int maxFractionDigits; // 'maxFractionDigits' attribute
69
protected boolean maxFractionDigitsSpecified;
70     protected int minFractionDigits; // 'minFractionDigits' attribute
71
protected boolean minFractionDigitsSpecified;
72
73
74     //*********************************************************************
75
// Private state
76

77     private String JavaDoc var; // 'var' attribute
78
private int scope; // 'scope' attribute
79
private static Class JavaDoc currencyClass;
80
81
82     //*********************************************************************
83
// Constructor and initialization
84

85     static {
86     try {
87         currencyClass = Class.forName("java.util.Currency");
88         // container's runtime is J2SE 1.4 or greater
89
} catch (Exception JavaDoc cnfe) {
90     }
91     }
92
93     public FormatNumberSupport() {
94     super();
95     init();
96     }
97
98     private void init() {
99     value = type = null;
100     valueSpecified = false;
101     pattern = var = currencyCode = currencySymbol = null;
102     groupingUsedSpecified = false;
103     maxIntegerDigitsSpecified = minIntegerDigitsSpecified = false;
104     maxFractionDigitsSpecified = minFractionDigitsSpecified = false;
105     scope = PageContext.PAGE_SCOPE;
106     }
107
108
109    //*********************************************************************
110
// Tag attributes known at translation time
111

112     public void setVar(String JavaDoc var) {
113         this.var = var;
114     }
115
116     public void setScope(String JavaDoc scope) {
117     this.scope = Util.getScope(scope);
118     }
119
120
121     //*********************************************************************
122
// Tag logic
123

124     public int doEndTag() throws JspException JavaDoc {
125     String JavaDoc formatted = null;
126         Object JavaDoc input = null;
127
128         // determine the input by...
129
if (valueSpecified) {
130         // ... reading 'value' attribute
131
input = value;
132     } else {
133         // ... retrieving and trimming our body
134
if (bodyContent != null && bodyContent.getString() != null)
135             input = bodyContent.getString().trim();
136     }
137
138     if ((input == null) || input.equals("")) {
139         // Spec says:
140
// If value is null or empty, remove the scoped variable
141
// if it is specified (see attributes var and scope).
142
if (var != null) {
143             pageContext.removeAttribute(var, scope);
144             }
145         return EVAL_PAGE;
146     }
147
148     /*
149      * If 'value' is a String, it is first parsed into an instance of
150      * java.lang.Number
151      */

152     if (input instanceof String JavaDoc) {
153         try {
154         if (((String JavaDoc) input).indexOf('.') != -1) {
155             input = Double.valueOf((String JavaDoc) input);
156         } else {
157             input = Long.valueOf((String JavaDoc) input);
158         }
159         } catch (NumberFormatException JavaDoc nfe) {
160         throw new JspException JavaDoc(
161                     Resources.getMessage("FORMAT_NUMBER_PARSE_ERROR", input),
162             nfe);
163         }
164     }
165
166     // Determine formatting locale
167
Locale JavaDoc loc = SetLocaleSupport.getFormattingLocale(
168             pageContext,
169         this,
170         true,
171         NumberFormat.getAvailableLocales());
172
173     if (loc != null) {
174         // Create formatter
175
NumberFormat JavaDoc formatter = null;
176         if ((pattern != null) && !pattern.equals("")) {
177         // if 'pattern' is specified, 'type' is ignored
178
DecimalFormatSymbols JavaDoc symbols = new DecimalFormatSymbols JavaDoc(loc);
179         formatter = new DecimalFormat JavaDoc(pattern, symbols);
180         } else {
181         formatter = createFormatter(loc);
182         }
183         if (((pattern != null) && !pattern.equals(""))
184             || CURRENCY.equalsIgnoreCase(type)) {
185         try {
186             setCurrency(formatter);
187         } catch (Exception JavaDoc e) {
188             throw new JspException JavaDoc(
189                         Resources.getMessage("FORMAT_NUMBER_CURRENCY_ERROR"),
190             e);
191         }
192         }
193         configureFormatter(formatter);
194         formatted = formatter.format(input);
195     } else {
196         // no formatting locale available, use toString()
197
formatted = input.toString();
198     }
199
200     if (var != null) {
201         pageContext.setAttribute(var, formatted, scope);
202     } else {
203         try {
204         pageContext.getOut().print(formatted);
205         } catch (IOException JavaDoc ioe) {
206         throw new JspTagException JavaDoc(ioe.toString(), ioe);
207         }
208     }
209
210     return EVAL_PAGE;
211     }
212
213     // Releases any resources we may have (or inherit)
214
public void release() {
215     init();
216     }
217
218
219     //*********************************************************************
220
// Private utility methods
221

222     private NumberFormat JavaDoc createFormatter(Locale JavaDoc loc) throws JspException JavaDoc {
223     NumberFormat JavaDoc formatter = null;
224     
225     if ((type == null) || NUMBER.equalsIgnoreCase(type)) {
226         formatter = NumberFormat.getNumberInstance(loc);
227     } else if (CURRENCY.equalsIgnoreCase(type)) {
228         formatter = NumberFormat.getCurrencyInstance(loc);
229     } else if (PERCENT.equalsIgnoreCase(type)) {
230         formatter = NumberFormat.getPercentInstance(loc);
231     } else {
232         throw new JspException JavaDoc(
233             Resources.getMessage("FORMAT_NUMBER_INVALID_TYPE", type));
234     }
235     
236     return formatter;
237     }
238
239     /*
240      * Applies the 'groupingUsed', 'maxIntegerDigits', 'minIntegerDigits',
241      * 'maxFractionDigits', and 'minFractionDigits' attributes to the given
242      * formatter.
243      */

244     private void configureFormatter(NumberFormat JavaDoc formatter) {
245     if (groupingUsedSpecified)
246         formatter.setGroupingUsed(isGroupingUsed);
247     if (maxIntegerDigitsSpecified)
248         formatter.setMaximumIntegerDigits(maxIntegerDigits);
249     if (minIntegerDigitsSpecified)
250         formatter.setMinimumIntegerDigits(minIntegerDigits);
251     if (maxFractionDigitsSpecified)
252         formatter.setMaximumFractionDigits(maxFractionDigits);
253     if (minFractionDigitsSpecified)
254         formatter.setMinimumFractionDigits(minFractionDigits);
255     }
256
257     /*
258      * Override the formatting locale's default currency symbol with the
259      * specified currency code (specified via the "currencyCode" attribute) or
260      * currency symbol (specified via the "currencySymbol" attribute).
261      *
262      * If both "currencyCode" and "currencySymbol" are present,
263      * "currencyCode" takes precedence over "currencySymbol" if the
264      * java.util.Currency class is defined in the container's runtime (that
265      * is, if the container's runtime is J2SE 1.4 or greater), and
266      * "currencySymbol" takes precendence over "currencyCode" otherwise.
267      *
268      * If only "currencyCode" is given, it is used as a currency symbol if
269      * java.util.Currency is not defined.
270      *
271      * Example:
272      *
273      * JDK "currencyCode" "currencySymbol" Currency symbol being displayed
274      * -----------------------------------------------------------------------
275      * all --- --- Locale's default currency symbol
276      *
277      * <1.4 EUR --- EUR
278      * >=1.4 EUR --- Locale's currency symbol for Euro
279      *
280      * all --- € €
281      *
282      * <1.4 EUR € €
283      * >=1.4 EUR € Locale's currency symbol for Euro
284      */

285     private void setCurrency(NumberFormat JavaDoc formatter) throws Exception JavaDoc {
286     String JavaDoc code = null;
287     String JavaDoc symbol = null;
288
289     if ((currencyCode == null) && (currencySymbol == null)) {
290         return;
291     }
292
293     if ((currencyCode != null) && (currencySymbol != null)) {
294         if (currencyClass != null)
295         code = currencyCode;
296         else
297         symbol = currencySymbol;
298     } else if (currencyCode == null) {
299         symbol = currencySymbol;
300     } else {
301         if (currencyClass != null)
302         code = currencyCode;
303         else
304         symbol = currencyCode;
305     }
306
307     if (code != null) {
308         Object JavaDoc[] methodArgs = new Object JavaDoc[1];
309
310         /*
311          * java.util.Currency.getInstance()
312          */

313         Method JavaDoc m = currencyClass.getMethod("getInstance",
314                            GET_INSTANCE_PARAM_TYPES);
315         methodArgs[0] = code;
316         Object JavaDoc currency = m.invoke(null, methodArgs);
317
318         /*
319          * java.text.NumberFormat.setCurrency()
320          */

321         Class JavaDoc[] paramTypes = new Class JavaDoc[1];
322         paramTypes[0] = currencyClass;
323         Class JavaDoc numberFormatClass = Class.forName("java.text.NumberFormat");
324         m = numberFormatClass.getMethod("setCurrency", paramTypes);
325         methodArgs[0] = currency;
326         m.invoke(formatter, methodArgs);
327     } else {
328         /*
329          * Let potential ClassCastException propagate up (will almost
330          * never happen)
331          */

332         DecimalFormat JavaDoc df = (DecimalFormat JavaDoc) formatter;
333         DecimalFormatSymbols JavaDoc dfs = df.getDecimalFormatSymbols();
334         dfs.setCurrencySymbol(symbol);
335         df.setDecimalFormatSymbols(dfs);
336     }
337     }
338 }
339
Popular Tags