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 
  27 package com.foo;
  28 
  29 import java.text.*;
  30 import java.text.spi.*;
  31 import java.util.*;
  32 
  33 import com.foobar.Utils;
  34 
  35 public 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 }