KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > base > util > UtilNumber


1 /*
2  * $Id:$
3  *
4  * Copyright (c) 2003-2006 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * @author Si Chen (sichen@opensourcestrategies.com)
25  * @author Leon Torres (leon@opensourcestrategies.com)
26  */

27
28 package org.ofbiz.base.util;
29
30 import java.math.BigDecimal JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Locale JavaDoc;
33
34 import com.ibm.icu.text.RuleBasedNumberFormat;
35
36 public class UtilNumber {
37
38     public static String JavaDoc module = UtilNumber.class.getName();
39
40     // properties file name for arithmetic configuration
41
private static final String JavaDoc arithmeticPropertiesFile = "arithmetic.properties";
42
43     // default scale and rounding mode for BigDecimals
44
private static final int DEFAULT_BD_SCALE = 2;
45     private static final int DEFAULT_BD_ROUNDING_MODE = BigDecimal.ROUND_HALF_UP;
46
47     /**
48      * Method to get BigDecimal scale factor from a property
49      * @param file - Name of the property file
50      * @param property - Name of the config property from arithmeticPropertiesFile (e.g., "invoice.decimals")
51      * @return int - Scale factor to pass to BigDecimal's methods. Defaults to DEFAULT_BD_SCALE (2)
52      */

53     public static int getBigDecimalScale(String JavaDoc file, String JavaDoc property) {
54         if ((file == null) || (file.length() == 0)) return DEFAULT_BD_SCALE;
55         if ((property == null) || (property.length() == 0)) return DEFAULT_BD_SCALE;
56
57         int scale = -1;
58         String JavaDoc value = UtilProperties.getPropertyValue(file, property);
59         if (value != null) {
60             try {
61                 scale = Integer.parseInt(value);
62             } catch (NumberFormatException JavaDoc e) {
63             }
64         }
65         if (scale == -1) {
66             Debug.logWarning("Could not set decimal precision from " + property + "=" + value + ". Using default scale of " + DEFAULT_BD_SCALE + ".", module);
67             scale = DEFAULT_BD_SCALE;
68         }
69         return scale;
70     }
71     
72     /**
73      * As above, but use the default properties file
74      */

75     public static int getBigDecimalScale(String JavaDoc property) {
76         return getBigDecimalScale(arithmeticPropertiesFile, property);
77     }
78
79     /**
80      * Method to get BigDecimal rounding mode from a property
81      * @param file - Name of the property file
82      * @param property - Name of the config property from arithmeticPropertiesFile (e.g., "invoice.rounding")
83      * @return int - Rounding mode to pass to BigDecimal's methods. Defaults to DEFAULT_BD_ROUNDING_MODE (BigDecimal.ROUND_HALF_UP)
84      */

85     public static int getBigDecimalRoundingMode(String JavaDoc file, String JavaDoc property) {
86         if ((file == null) || (file.length() == 0)) return DEFAULT_BD_SCALE;
87         if ((property == null) || (property.length() == 0)) return DEFAULT_BD_ROUNDING_MODE;
88
89         String JavaDoc value = UtilProperties.getPropertyValue(file, property);
90         int mode = roundingModeFromString(value);
91         if (mode == -1) {
92             Debug.logWarning("Could not set decimal rounding mode from " + property + "=" + value + ". Using default mode of " + DEFAULT_BD_SCALE + ".", module);
93             return DEFAULT_BD_ROUNDING_MODE;
94         }
95         return mode;
96     }
97
98     /**
99      * As above, but use the default properties file
100      */

101     public static int getBigDecimalRoundingMode(String JavaDoc property) {
102         return getBigDecimalRoundingMode(arithmeticPropertiesFile, property);
103     }
104
105     /**
106      * Method to get the BigDecimal rounding mode int value from a string name.
107      * @param value - The name of the mode (e.g., "ROUND_HALF_UP")
108      * @return int - The int value of the mode (e.g, BigDecimal.ROUND_HALF_UP) or -1 if the input was bad.
109      */

110     public static int roundingModeFromString(String JavaDoc value) {
111         if (value == null) return -1;
112         value = value.trim();
113         if ("ROUND_HALF_UP".equals(value)) return BigDecimal.ROUND_HALF_UP;
114         else if ("ROUND_HALF_DOWN".equals(value)) return BigDecimal.ROUND_HALF_DOWN;
115         else if ("ROUND_HALF_EVEN".equals(value)) return BigDecimal.ROUND_HALF_EVEN;
116         else if ("ROUND_UP".equals(value)) return BigDecimal.ROUND_UP;
117         else if ("ROUND_DOWN".equals(value)) return BigDecimal.ROUND_DOWN;
118         else if ("ROUND_CEILING".equals(value)) return BigDecimal.ROUND_CEILING;
119         else if ("ROUND_FLOOR".equals(value)) return BigDecimal.ROUND_FLOOR;
120         else if ("ROUND_UNNECCESSARY".equals(value)) return BigDecimal.ROUND_UNNECESSARY;
121         return -1;
122     }
123
124     // ICU4J rule sets for the en_US locale. To add more rules, expand this string.
125
// For reference, see the RbnfSampleRuleSets.java file distributed with ICU4J
126
public static final String JavaDoc ruleSet_en_US =
127         /*
128          * These rules format a number in one of the two styles often used
129          * on checks. %dollars-and-hundredths formats cents as hundredths of
130          * a dollar (23.40 comes out as "twenty-three and 40/100 dollars").
131          * %dollars-and-cents formats in dollars and cents (23.40 comes out as
132          * "twenty-three dollars and forty cents")
133          */

134         "%dollars-and-cents:\n"
135         + " x.0: << [and >%%cents>];\n"
136         + " 0.x: >%%cents>;\n"
137         + " 0: zero dollars; one dollar; =%%main= dollars;\n"
138         + "%%main:\n"
139         + " zero; one; two; three; four; five; six; seven; eight; nine;\n"
140         + " ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"
141         + " seventeen; eighteen; nineteen;\n"
142         + " 20: twenty[->>];\n"
143         + " 30: thirty[->>];\n"
144         + " 40: forty[->>];\n"
145         + " 50: fifty[->>];\n"
146         + " 60: sixty[->>];\n"
147         + " 70: seventy[->>];\n"
148         + " 80: eighty[->>];\n"
149         + " 90: ninety[->>];\n"
150         + " 100: << hundred[ >>];\n"
151         + " 1000: << thousand[ >>];\n"
152         + " 1,000,000: << million[ >>];\n"
153         + " 1,000,000,000: << billion[ >>];\n"
154         + " 1,000,000,000,000: << trillion[ >>];\n"
155         + " 1,000,000,000,000,000: =#,##0=;\n"
156         + "%%cents:\n"
157         + " 100: <%%main< cent[s];\n"
158         + "%dollars-and-hundredths:\n"
159         + " x.0: <%%main< and >%%hundredths>/100;\n" // this used to end in 'dollars' but that should be added later
160
+ "%%hundredths:\n"
161         + " 100: <00<;\n";
162
163     // hash map to store ICU4J rule sets keyed to Locale
164
public static HashMap JavaDoc rbnfRuleSets;
165     static {
166         rbnfRuleSets = new HashMap JavaDoc();
167         rbnfRuleSets.put(Locale.US, ruleSet_en_US);
168     }
169     
170     /**
171      * Method to format an amount using a custom rule set.
172      * Current rule sets available:
173      *
174      * en_US
175      * %dollars-and-cents - 1,225.25 becomes "one thousand two hundred twenty five dollars and twenty five cents" (useful for checks)
176      * %dollars-and-hundreths - 1,225.25 becomes "one thousand two hundred twenty five and 25/00" (alternate for checks)
177      *
178      * @param amount - the amount to format
179      * @param rule - the name of the rule set to use (e.g., %dollars-and-hundredths)
180      * @param locale - the Locale
181      * @return formatted string or an empty string if there was an error
182      */

183     public static String JavaDoc formatRuleBasedAmount(double amount, String JavaDoc rule, Locale JavaDoc locale) {
184         String JavaDoc ruleSet = (String JavaDoc) rbnfRuleSets.get(locale);
185         if (ruleSet == null) {
186             Debug.logWarning("Cannot format rule based amount for locale " + locale.toString() + " because rule set for that locale does not exist", module);
187             return "";
188         }
189         RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(ruleSet, locale);
190         String JavaDoc result = "";
191         try {
192             result = formatter.format(amount, rule);
193         } catch (Exception JavaDoc e) {
194             Debug.logError(e, "Failed to format amount " + amount + " using rule " + rule, module);
195         }
196         return result;
197     }
198
199     /**
200      * Method to turn a number such as "0.9853" into a nicely formatted percent, "98.53%".
201      *
202      * @param number The number object to format
203      * @param scale How many places after the decimal to include
204      * @param roundingMode The BigDecimal rounding mode to apply
205      * @return The formatted string or "" if there were errors.
206      */

207     public static String JavaDoc toPercentString(Number JavaDoc number, int scale, int roundingMode) {
208         // convert to BigDecimal
209
if (!(number instanceof BigDecimal JavaDoc)) {
210             number = new BigDecimal JavaDoc(number.doubleValue());
211         }
212
213         // cast it so we can use BigDecimal methods
214
BigDecimal JavaDoc bd = (BigDecimal JavaDoc) number;
215
216         // multiply by 100 and set the scale
217
bd = bd.multiply(new BigDecimal JavaDoc(100.0)).setScale(scale, roundingMode);
218
219         return (bd.toString() + "%");
220     }
221 }
222
Popular Tags