1/*
2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23/*
24 *
25 */
26
27package com.foo;
28
29import java.text.*;
30import java.text.spi.*;
31import java.util.*;
32
33import com.foobar.Utils;
34
35public class NumberFormatProviderImpl extends NumberFormatProvider {
36
37    static Locale[] avail = {
38        Locale.JAPAN,
39        new Locale("ja", "JP", "osaka"),
40        new Locale("ja", "JP", "kyoto"),
41        new Locale("zz")};
42
43    static String[] dialect = {
44        "\u3067\u3059\u3002",
45        "\u3084\u3002",
46        "\u3069\u3059\u3002",
47        "-zz"
48    };
49
50    static String[] patterns = {
51        "#,##0.###{0};-#,##0.###{1}", // decimal pattern
52        "#{0};(#){1}", // integer pattern
53        "\u00A4#,##0{0};-\u00A4#,##0{1}", // currency pattern
54        "#,##0%{0}" // percent pattern
55    };
56    // Constants used by factory methods to specify a style of format.
57    static final int NUMBERSTYLE = 0;
58    static final int INTEGERSTYLE = 1;
59    static final int CURRENCYSTYLE = 2;
60    static final int PERCENTSTYLE = 3;
61
62    public Locale[] getAvailableLocales() {
63        return avail;
64    }
65
66    public NumberFormat getCurrencyInstance(Locale locale) {
67        for (int i = 0; i < avail.length; i ++) {
68            if (Utils.supportsLocale(avail[i], locale)) {
69                String pattern =
70                    MessageFormat.format(patterns[CURRENCYSTYLE],
71                                         dialect[i],
72                                         dialect[i]);
73                FooNumberFormat nf = new FooNumberFormat(pattern,
74                    DecimalFormatSymbols.getInstance(locale));
75                adjustForCurrencyDefaultFractionDigits(nf);
76                return nf;
77            }
78        }
79        throw new IllegalArgumentException("locale is not supported: "+locale);
80    }
81
82    public NumberFormat getIntegerInstance(Locale locale) {
83        for (int i = 0; i < avail.length; i ++) {
84            if (Utils.supportsLocale(avail[i], locale)) {
85                String pattern =
86                    MessageFormat.format(patterns[INTEGERSTYLE],
87                                         dialect[i],
88                                         dialect[i]);
89                FooNumberFormat nf = new FooNumberFormat(pattern,
90                    DecimalFormatSymbols.getInstance(locale));
91                nf.setMaximumFractionDigits(0);
92                nf.setDecimalSeparatorAlwaysShown(false);
93                nf.setParseIntegerOnly(true);
94                return nf;
95            }
96        }
97        throw new IllegalArgumentException("locale is not supported: "+locale);
98    }
99
100    public NumberFormat getNumberInstance(Locale locale) {
101        for (int i = 0; i < avail.length; i ++) {
102            if (Utils.supportsLocale(avail[i], locale)) {
103                String pattern =
104                    MessageFormat.format(patterns[NUMBERSTYLE],
105                                         dialect[i],
106                                         dialect[i]);
107                return new FooNumberFormat(pattern,
108                    DecimalFormatSymbols.getInstance(locale));
109            }
110        }
111        throw new IllegalArgumentException("locale is not supported: "+locale);
112    }
113
114    public NumberFormat getPercentInstance(Locale locale) {
115        for (int i = 0; i < avail.length; i ++) {
116            if (Utils.supportsLocale(avail[i], locale)) {
117                String pattern =
118                    MessageFormat.format(patterns[PERCENTSTYLE],
119                                         dialect[i]);
120                return new FooNumberFormat(pattern,
121                    DecimalFormatSymbols.getInstance(locale));
122            }
123        }
124        throw new IllegalArgumentException("locale is not supported: "+locale);
125    }
126
127    /**
128     * Adjusts the minimum and maximum fraction digits to values that
129     * are reasonable for the currency's default fraction digits.
130     */
131    void adjustForCurrencyDefaultFractionDigits(FooNumberFormat nf) {
132        DecimalFormatSymbols dfs = nf.getDecimalFormatSymbols();
133        Currency currency = dfs.getCurrency();
134        if (currency == null) {
135            try {
136                currency = Currency.getInstance(dfs.getInternationalCurrencySymbol());
137            } catch (IllegalArgumentException e) {
138            }
139        }
140        if (currency != null) {
141            int digits = currency.getDefaultFractionDigits();
142            if (digits != -1) {
143                int oldMinDigits = nf.getMinimumFractionDigits();
144                // Common patterns are "#.##", "#.00", "#".
145                // Try to adjust all of them in a reasonable way.
146                if (oldMinDigits == nf.getMaximumFractionDigits()) {
147                    nf.setMinimumFractionDigits(digits);
148                    nf.setMaximumFractionDigits(digits);
149                } else {
150                    nf.setMinimumFractionDigits(Math.min(digits, oldMinDigits));
151                    nf.setMaximumFractionDigits(digits);
152                }
153            }
154        }
155    }
156}
157