KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freemarker > core > NumericalOutput


1 /*
2  * Copyright (c) 2003 The Visigoth Software Society. All rights
3  * reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. The end-user documentation included with the redistribution, if
18  * any, must include the following acknowledgement:
19  * "This product includes software developed by the
20  * Visigoth Software Society (http://www.visigoths.org/)."
21  * Alternately, this acknowledgement may appear in the software itself,
22  * if and wherever such third-party acknowledgements normally appear.
23  *
24  * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
25  * project contributors may be used to endorse or promote products derived
26  * from this software without prior written permission. For written
27  * permission, please contact visigoths@visigoths.org.
28  *
29  * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
30  * nor may "FreeMarker" or "Visigoth" appear in their names
31  * without prior written permission of the Visigoth Software Society.
32  *
33  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
34  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36  * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
37  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  * ====================================================================
46  *
47  * This software consists of voluntary contributions made by many
48  * individuals on behalf of the Visigoth Software Society. For more
49  * information on the Visigoth Software Society, please see
50  * http://www.visigoths.org/
51  */

52
53 package freemarker.core;
54
55 import java.io.IOException JavaDoc;
56 import java.text.NumberFormat JavaDoc;
57 import java.util.Locale JavaDoc;
58 import freemarker.template.*;
59
60 /**
61  * An instruction that outputs the value of a numerical expression.
62  * @author <a HREF="mailto:jon@revusky.com">Jonathan Revusky</a>
63  */

64 final class NumericalOutput extends TemplateElement {
65
66     private final Expression expression;
67     private final boolean hasFormat;
68     private final int minFracDigits;
69     private final int maxFracDigits;
70     private volatile FormatHolder formatCache; // creating new NumberFormat is slow operation
71

72     NumericalOutput(Expression expression) {
73         this.expression = expression;
74         hasFormat = false;
75         this.minFracDigits = 0;
76         this.maxFracDigits = 0;
77     }
78
79     NumericalOutput(Expression expression,
80                     int minFracDigits,
81                     int maxFracDigits)
82     {
83         this.expression = expression;
84         hasFormat = true;
85         this.minFracDigits = minFracDigits;
86         this.maxFracDigits = maxFracDigits;
87     }
88
89     void accept(Environment env) throws TemplateException, IOException JavaDoc
90     {
91         Number JavaDoc num = EvaluationUtil.getNumber(expression, env);
92         
93         FormatHolder fmth = formatCache; // atomic sampling
94
if (fmth == null || !fmth.locale.equals(env.getLocale())) {
95             synchronized(this) {
96                 fmth = formatCache;
97                 if (fmth == null || !fmth.locale.equals(env.getLocale())) {
98                     NumberFormat JavaDoc fmt = NumberFormat.getNumberInstance(env.getLocale());
99                     if (hasFormat) {
100                         fmt.setMinimumFractionDigits(minFracDigits);
101                         fmt.setMaximumFractionDigits(maxFracDigits);
102                     } else {
103                         fmt.setMinimumFractionDigits(0);
104                         fmt.setMaximumFractionDigits(50);
105                     }
106                     fmt.setGroupingUsed(false);
107                     formatCache = new FormatHolder(fmt, env.getLocale());
108                     fmth = formatCache;
109                 }
110             }
111         }
112         // We must use Format even if hasFormat == false.
113
// Some locales may use non-Arabic digits, thus replacing the
114
// decimal separator in the result of toString() is not enough.
115
env.getOut().write(fmth.format.format(num));
116     }
117
118     public String JavaDoc getCanonicalForm() {
119         StringBuffer JavaDoc buf = new StringBuffer JavaDoc("#{");
120         buf.append(expression.getCanonicalForm());
121         if (hasFormat) {
122             buf.append(" ; ");
123             buf.append("m");
124             buf.append(minFracDigits);
125             buf.append("M");
126             buf.append(maxFracDigits);
127         }
128         buf.append("}");
129         return buf.toString();
130     }
131
132     public String JavaDoc getDescription() {
133         return getSource();
134     }
135
136     boolean heedsOpeningWhitespace() {
137         return true;
138     }
139
140     boolean heedsTrailingWhitespace() {
141         return true;
142     }
143     
144     private class FormatHolder {
145         final NumberFormat JavaDoc format;
146         final Locale JavaDoc locale;
147         
148         FormatHolder(NumberFormat JavaDoc format, Locale JavaDoc locale) {
149             this.format = format;
150             this.locale = locale;
151         }
152     }
153 }
154
Popular Tags