NativeDecimalFormat.java revision 1efbe3391e92e6188918122a600623090561364f
1f933441648ef6a71dee783d733aac17b9508b452Andreas Huber/*
2f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Copyright (C) 2008 The Android Open Source Project
3f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *
4f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * you may not use this file except in compliance with the License.
6f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * You may obtain a copy of the License at
7f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *
8f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *
10f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Unless required by applicable law or agreed to in writing, software
11f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * See the License for the specific language governing permissions and
14f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * limitations under the License.
15f933441648ef6a71dee783d733aac17b9508b452Andreas Huber */
16f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
17f933441648ef6a71dee783d733aac17b9508b452Andreas Huberpackage com.ibm.icu4jni.text;
18f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
19f933441648ef6a71dee783d733aac17b9508b452Andreas Huberimport com.ibm.icu4jni.util.LocaleData;
20f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
21f933441648ef6a71dee783d733aac17b9508b452Andreas Huberimport java.math.BigDecimal;
22a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hungimport java.math.BigInteger;
23f933441648ef6a71dee783d733aac17b9508b452Andreas Huberimport java.text.AttributedCharacterIterator;
24f933441648ef6a71dee783d733aac17b9508b452Andreas Huberimport java.text.AttributedString;
255bc087c573c70c84c6a39946457590b42d392a33Andreas Huberimport java.text.DecimalFormatSymbols;
26a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuimport java.text.FieldPosition;
2735d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiangimport java.text.Format;
285833b6aad2c46ba516bdc8262f4fc4667e8018edWei Jiaimport java.text.NumberFormat;
29bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiaimport java.text.ParsePosition;
30bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiaimport java.util.Currency;
313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangimport java.util.Locale;
32a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar
33dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnarpublic class DecimalFormat {
34095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar    /**
35095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar     * Constants corresponding to the native type UNumberFormatSymbol, for getSymbol/setSymbol.
36f933441648ef6a71dee783d733aac17b9508b452Andreas Huber     */
37f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static final int UNUM_DECIMAL_SEPARATOR_SYMBOL = 0;
38a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_GROUPING_SEPARATOR_SYMBOL = 1;
39a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_PATTERN_SEPARATOR_SYMBOL = 2;
40a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_PERCENT_SYMBOL = 3;
41a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_ZERO_DIGIT_SYMBOL = 4;
42a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_DIGIT_SYMBOL = 5;
43a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_MINUS_SIGN_SYMBOL = 6;
44a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_PLUS_SIGN_SYMBOL = 7;
45a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_CURRENCY_SYMBOL = 8;
46a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_INTL_CURRENCY_SYMBOL = 9;
47a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_MONETARY_SEPARATOR_SYMBOL = 10;
48a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_EXPONENTIAL_SYMBOL = 11;
49a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_PERMILL_SYMBOL = 12;
50288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung    private static final int UNUM_PAD_ESCAPE_SYMBOL = 13;
51288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung    private static final int UNUM_INFINITY_SYMBOL = 14;
52288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung    private static final int UNUM_NAN_SYMBOL = 15;
53179652ee2a508361df1aa18e99000373886f0816Andy Hung    private static final int UNUM_SIGNIFICANT_DIGIT_SYMBOL = 16;
54179652ee2a508361df1aa18e99000373886f0816Andy Hung    private static final int UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL = 17;
55179652ee2a508361df1aa18e99000373886f0816Andy Hung    private static final int UNUM_FORMAT_SYMBOL_COUNT = 18;
56a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
57a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    /**
58a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung     * Constants corresponding to the native type UNumberFormatAttribute, for
59a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung     * getAttribute/setAttribute.
60a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung     */
61a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_PARSE_INT_ONLY = 0;
62a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    private static final int UNUM_GROUPING_USED = 1;
63179652ee2a508361df1aa18e99000373886f0816Andy Hung    private static final int UNUM_DECIMAL_ALWAYS_SHOWN = 2;
64179652ee2a508361df1aa18e99000373886f0816Andy Hung    private static final int UNUM_MAX_INTEGER_DIGITS = 3;
65179652ee2a508361df1aa18e99000373886f0816Andy Hung    private static final int UNUM_MIN_INTEGER_DIGITS = 4;
66179652ee2a508361df1aa18e99000373886f0816Andy Hung    private static final int UNUM_INTEGER_DIGITS = 5;
67179652ee2a508361df1aa18e99000373886f0816Andy Hung    private static final int UNUM_MAX_FRACTION_DIGITS = 6;
68f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    private static final int UNUM_MIN_FRACTION_DIGITS = 7;
69f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    private static final int UNUM_FRACTION_DIGITS = 8;
70a5d316fd802cfc92954527f27e6f32206a896113Eric Laurent    private static final int UNUM_MULTIPLIER = 9;
71f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    private static final int UNUM_GROUPING_SIZE = 10;
72714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber    private static final int UNUM_ROUNDING_MODE = 11;
73f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    private static final int UNUM_ROUNDING_INCREMENT = 12;
74f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    private static final int UNUM_FORMAT_WIDTH = 13;
75f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    private static final int UNUM_PADDING_POSITION = 14;
76f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    private static final int UNUM_SECONDARY_GROUPING_SIZE = 15;
77f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    private static final int UNUM_SIGNIFICANT_DIGITS_USED = 16;
78f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    private static final int UNUM_MIN_SIGNIFICANT_DIGITS = 17;
79f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    private static final int UNUM_MAX_SIGNIFICANT_DIGITS = 18;
80f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    private static final int UNUM_LENIENT_PARSE = 19;
81f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
82714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber    /**
83714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber     * Constants corresponding to the native type UNumberFormatTextAttribute, for
84f933441648ef6a71dee783d733aac17b9508b452Andreas Huber     * getTextAttribute/setTextAttribute.
85f933441648ef6a71dee783d733aac17b9508b452Andreas Huber     */
86d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    private static final int UNUM_POSITIVE_PREFIX = 0;
87d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    private static final int UNUM_POSITIVE_SUFFIX = 1;
88f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static final int UNUM_NEGATIVE_PREFIX = 2;
89f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static final int UNUM_NEGATIVE_SUFFIX = 3;
90d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    private static final int UNUM_PADDING_CHARACTER = 4;
91f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static final int UNUM_CURRENCY_CODE = 5;
92f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static final int UNUM_DEFAULT_RULESET = 6;
93f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static final int UNUM_PUBLIC_RULESETS = 7;
94f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
95f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    /**
967b15cb33847e6282ea8352c98894683b796127f3Wei Jia     * The address of the ICU DecimalFormat* on the native heap.
977b15cb33847e6282ea8352c98894683b796127f3Wei Jia     */
983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    private final int addr;
99a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
100eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    /**
101f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar     * The last pattern we gave to ICU, so we can make repeated applications cheap.
102a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu     * This helps in cases like String.format("%.2f,%.2f\n", x, y) where the DecimalFormat is
103bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber     * reused.
104bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber     */
1057137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    private String lastPattern;
1067137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang
107bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber    // TODO: store all these in java.text.DecimalFormat instead!
108714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber    private boolean negPrefNull;
10909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    private boolean negSuffNull;
110f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    private boolean posPrefNull;
111cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    private boolean posSuffNull;
112cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
113f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    /**
114faeb0f291330134dc4468359a36e099aae508449Ronghua Wu     * Cache the BigDecimal form of the multiplier. This is null until we've
115d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar     * formatted a BigDecimal (with a multiplier that is not 1), or the user has
116f0e83644637bd05852c244df481f21a0d435ff66Andy Hung     * explicitly called {@link #setMultiplier(int)} with any multiplier.
117d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar     */
11835d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang    private BigDecimal multiplierBigDecimal = null;
119a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
12035d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang    public DecimalFormat(String pattern, Locale locale, DecimalFormatSymbols symbols) {
1217b15cb33847e6282ea8352c98894683b796127f3Wei Jia        this.addr = openDecimalFormat(locale.toString(), pattern);
1223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        this.lastPattern = pattern;
1233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setDecimalFormatSymbols(symbols);
124f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
125f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
126f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // Used to implement clone.
127bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    private DecimalFormat(DecimalFormat other) {
128bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        this.addr = cloneDecimalFormatImpl(other.addr);
129bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        this.lastPattern = other.lastPattern;
130bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        this.negPrefNull = other.negPrefNull;
131bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        this.negSuffNull = other.negSuffNull;
132f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        this.posPrefNull = other.posPrefNull;
133f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        this.posSuffNull = other.posSuffNull;
134f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
135f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
136f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // TODO: remove this and just have java.text.DecimalFormat.hashCode do the right thing itself.
137f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    @Override
1381d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    public int hashCode() {
1397b15cb33847e6282ea8352c98894683b796127f3Wei Jia        return this.getPositivePrefix().hashCode();
140f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1412d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber
142f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    @Override
143f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    public Object clone() {
144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return new DecimalFormat(this);
145f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
146f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
147f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    @Override
148f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    protected void finalize() {
1491d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        closeDecimalFormatImpl(this.addr);
1507b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
151f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
152f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    /**
153f933441648ef6a71dee783d733aac17b9508b452Andreas Huber     * Note: this doesn't check that the underlying native DecimalFormat objects' configured
154f933441648ef6a71dee783d733aac17b9508b452Andreas Huber     * native DecimalFormatSymbols objects are equal. It is assumed that the
155f933441648ef6a71dee783d733aac17b9508b452Andreas Huber     * caller (java.text.DecimalFormat) will check the java.text.DecimalFormatSymbols objects
1563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar     * instead, for performance.
1573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar     *
1583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar     * This is also unreasonably expensive, calling down to JNI multiple times.
1593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar     *
1603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar     * TODO: remove this and just have java.text.DecimalFormat.equals do the right thing itself.
1613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar     */
1623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    @Override
1633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    public boolean equals(Object object) {
1643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (object == this) {
1653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return true;
1663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
1673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (!(object instanceof DecimalFormat)) {
1683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return false;
1693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
1703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        DecimalFormat obj = (DecimalFormat) object;
1713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (obj.addr == this.addr) {
1723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return true;
1733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
1743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return obj.toPattern().equals(this.toPattern()) &&
1753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.isDecimalSeparatorAlwaysShown() == this.isDecimalSeparatorAlwaysShown() &&
1763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.getGroupingSize() == this.getGroupingSize() &&
1773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.getMultiplier() == this.getMultiplier() &&
1783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.getNegativePrefix().equals(this.getNegativePrefix()) &&
17927ea08e3811dc8057685258af52a7d40474eba16Wei Jia                obj.getNegativeSuffix().equals(this.getNegativeSuffix()) &&
1803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.getPositivePrefix().equals(this.getPositivePrefix()) &&
1813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.getPositiveSuffix().equals(this.getPositiveSuffix()) &&
1823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.getMaximumIntegerDigits() == this.getMaximumIntegerDigits() &&
1833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.getMaximumFractionDigits() == this.getMaximumFractionDigits() &&
1843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.getMinimumIntegerDigits() == this.getMinimumIntegerDigits() &&
1853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.getMinimumFractionDigits() == this.getMinimumFractionDigits() &&
1863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.isGroupingUsed() == this.isGroupingUsed() &&
1873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                obj.getCurrency() == this.getCurrency();
1883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
1903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    /**
1913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar     * Copies the java.text.DecimalFormatSymbols' settings into our native peer.
1923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar     */
1933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    public void setDecimalFormatSymbols(final java.text.DecimalFormatSymbols dfs) {
1943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_CURRENCY_SYMBOL, dfs.getCurrencySymbol());
1953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
1963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_DECIMAL_SEPARATOR_SYMBOL, dfs.getDecimalSeparator());
1973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_DIGIT_SYMBOL, dfs.getDigit());
1983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
1993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        char groupingSeparator = dfs.getGroupingSeparator();
2003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_GROUPING_SEPARATOR_SYMBOL, groupingSeparator);
2013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL, groupingSeparator);
2023a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2033a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_INFINITY_SYMBOL, dfs.getInfinity());
2043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_INTL_CURRENCY_SYMBOL, dfs.getInternationalCurrencySymbol());
20527ea08e3811dc8057685258af52a7d40474eba16Wei Jia        setSymbol(this.addr, UNUM_MINUS_SIGN_SYMBOL, dfs.getMinusSign());
2063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_MONETARY_SEPARATOR_SYMBOL, dfs.getMonetaryDecimalSeparator());
2073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_NAN_SYMBOL, dfs.getNaN());
2083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_PATTERN_SEPARATOR_SYMBOL, dfs.getPatternSeparator());
2093a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_PERCENT_SYMBOL, dfs.getPercent());
2103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_PERMILL_SYMBOL, dfs.getPerMill());
2113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setSymbol(this.addr, UNUM_ZERO_DIGIT_SYMBOL, dfs.getZeroDigit());
2123a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2143a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    private BigDecimal applyMultiplier(BigDecimal valBigDecimal) {
2153a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar       if (multiplierBigDecimal == null) {
2163a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar           multiplierBigDecimal = BigDecimal.valueOf(getMultiplier());
2173a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar       }
2183a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar       // Get new value by multiplying multiplier.
2193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar       return valBigDecimal.multiply(multiplierBigDecimal);
2203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    public StringBuffer format(Object value, StringBuffer buffer, FieldPosition field) {
2233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (!(value instanceof Number)) {
2243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            throw new IllegalArgumentException();
2253a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2263a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (buffer == null || field == null) {
2273a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            throw new NullPointerException();
2283a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2293a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        String fieldType = getFieldType(field.getFieldAttribute());
2303a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        Number number = (Number) value;
2313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (number instanceof BigInteger) {
2323a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            BigInteger valBigInteger = (BigInteger) number;
2333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            String result = format(this.addr, valBigInteger.toString(10), field, fieldType, null, 0);
2343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return buffer.append(result);
2353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        } else if (number instanceof BigDecimal) {
2363a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            BigDecimal valBigDecimal = (BigDecimal) number;
2373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (getMultiplier() != 1) {
2383a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                valBigDecimal = applyMultiplier(valBigDecimal);
2393a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
2403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            StringBuilder val = new StringBuilder();
2413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            val.append(valBigDecimal.unscaledValue().toString(10));
2423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            int scale = valBigDecimal.scale();
2433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            scale = makeScalePositive(scale, val);
2443a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            String result = format(this.addr, val.toString(), field, fieldType, null, scale);
2453a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return buffer.append(result);
2463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        } else if (number instanceof Double || number instanceof Float) {
2473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            double dv = number.doubleValue();
2483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            String result = format(this.addr, dv, field, fieldType, null);
2493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return buffer.append(result);
2503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        } else {
2513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            long lv = number.longValue();
2523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            String result = format(this.addr, lv, field, fieldType, null);
2533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return buffer.append(result);
2543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    public StringBuffer format(long value, StringBuffer buffer, FieldPosition field) {
2583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (buffer == null || field == null) {
2593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            throw new NullPointerException();
2603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2619816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        String fieldType = getFieldType(field.getFieldAttribute());
2629816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        buffer.append(format(this.addr, value, field, fieldType, null));
2637137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang        return buffer;
264f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
2657b15cb33847e6282ea8352c98894683b796127f3Wei Jia
266f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    public StringBuffer format(double value, StringBuffer buffer, FieldPosition field) {
2677137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang        if (buffer == null || field == null) {
2683b0cd26dbb0ce37d220db9ff0fa8172a7ef1c5cbWei Jia            throw new NullPointerException();
2697b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
2707b15cb33847e6282ea8352c98894683b796127f3Wei Jia        String fieldType = getFieldType(field.getFieldAttribute());
271f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        buffer.append(format(this.addr, value, field, fieldType, null));
2727137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang        return buffer;
2737b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
2747b15cb33847e6282ea8352c98894683b796127f3Wei Jia
275f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    public void applyLocalizedPattern(String pattern) {
2767b15cb33847e6282ea8352c98894683b796127f3Wei Jia        applyPattern(this.addr, true, pattern);
2777b15cb33847e6282ea8352c98894683b796127f3Wei Jia        lastPattern = null;
2787b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
2797b15cb33847e6282ea8352c98894683b796127f3Wei Jia
280f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    public void applyPattern(String pattern) {
281f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (lastPattern != null && pattern.equals(lastPattern)) {
2821d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar            return;
283f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
284f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        applyPattern(this.addr, false, pattern);
285f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        lastPattern = pattern;
286f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
287f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
28828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    public AttributedCharacterIterator formatToCharacterIterator(Object object) {
28928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        if (!(object instanceof Number)) {
29028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            throw new IllegalArgumentException();
2911d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        }
29228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        Number number = (Number) object;
29328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        String text = null;
294a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        StringBuffer attributes = new StringBuffer();
2951d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar
296a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        if(number instanceof BigInteger) {
297a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            BigInteger valBigInteger = (BigInteger) number;
298b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            text = format(this.addr, valBigInteger.toString(10), null, null, attributes, 0);
2991d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        } else if(number instanceof BigDecimal) {
300b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            BigDecimal valBigDecimal = (BigDecimal) number;
301b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            if (getMultiplier() != 1) {
302b408222bd9479c291874b607acae1425d6154fe7Andreas Huber                valBigDecimal = applyMultiplier(valBigDecimal);
3031d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar            }
304b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            StringBuilder val = new StringBuilder();
305b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            val.append(valBigDecimal.unscaledValue().toString(10));
306c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            int scale = valBigDecimal.scale();
3071d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar            scale = makeScalePositive(scale, val);
308c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            text = format(this.addr, val.toString(), null, null, attributes, scale);
309c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        } else if (number instanceof Double || number instanceof Float) {
310c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            double dv = number.doubleValue();
311c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            text = format(this.addr, dv, null, null, attributes);
312d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia        } else {
3137b15cb33847e6282ea8352c98894683b796127f3Wei Jia            long lv = number.longValue();
3149816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            text = format(this.addr, lv, null, null, attributes);
315a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        }
316a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3177b15cb33847e6282ea8352c98894683b796127f3Wei Jia        AttributedString as = new AttributedString(text);
3187b15cb33847e6282ea8352c98894683b796127f3Wei Jia
3197b15cb33847e6282ea8352c98894683b796127f3Wei Jia        String[] attrs = attributes.toString().split(";");
320a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        // add NumberFormat field attributes to the AttributedString
321a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        int size = attrs.length / 3;
3227b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if(size * 3 != attrs.length) {
323a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            return as.getIterator();
324a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        }
3257b15cb33847e6282ea8352c98894683b796127f3Wei Jia        for (int i = 0; i < size; i++) {
326a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            Format.Field attribute = getField(attrs[3*i]);
327a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            as.addAttribute(attribute, attribute, Integer.parseInt(attrs[3*i+1]),
328a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu                    Integer.parseInt(attrs[3*i+2]));
3297b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
3307b15cb33847e6282ea8352c98894683b796127f3Wei Jia
3317b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // return the CharacterIterator from AttributedString
3327b15cb33847e6282ea8352c98894683b796127f3Wei Jia        return as.getIterator();
333a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
334a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
335a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    private int makeScalePositive(int scale, StringBuilder val) {
3367b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if (scale < 0) {
337a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            scale = -scale;
338a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            for (int i = scale; i > 0; i--) {
339a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu                val.append('0');
340a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            }
3417b15cb33847e6282ea8352c98894683b796127f3Wei Jia            scale = 0;
342a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        }
343a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        return scale;
344a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
345202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung
3463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    public String toLocalizedPattern() {
3473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        return toPatternImpl(this.addr, true);
3483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
349202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung
350202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    public String toPattern() {
3511d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        return toPatternImpl(this.addr, false);
3523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
3533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    public Number parse(String string, ParsePosition position) {
3553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        return parse(addr, string, position);
3563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
3573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    // start getter and setter
3593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
360202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    public int getMaximumFractionDigits() {
361202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        return getAttribute(this.addr, UNUM_MAX_FRACTION_DIGITS);
362202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    }
363202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung
364202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    public int getMaximumIntegerDigits() {
365202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        return getAttribute(this.addr, UNUM_MAX_INTEGER_DIGITS);
366202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    }
367202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung
368202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    public int getMinimumFractionDigits() {
3693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        return getAttribute(this.addr, UNUM_MIN_FRACTION_DIGITS);
3703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
3713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3721d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    public int getMinimumIntegerDigits() {
3733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        return getAttribute(this.addr, UNUM_MIN_INTEGER_DIGITS);
3743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
3753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3763b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    public Currency getCurrency() {
3773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        String curr = getSymbol(this.addr, UNUM_INTL_CURRENCY_SYMBOL);
378f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (curr.equals("") || curr.equals("\u00a4\u00a4")) {
379f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            return null;
3803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
3813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        return Currency.getInstance(curr);
3823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
3833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    public int getGroupingSize() {
3853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        return getAttribute(this.addr, UNUM_GROUPING_SIZE);
3863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
3873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    public int getMultiplier() {
3893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        return getAttribute(this.addr, UNUM_MULTIPLIER);
3903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
3913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3923b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    public String getNegativePrefix() {
3933b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        if (negPrefNull) {
394202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            return null;
3953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
3963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        return getTextAttribute(this.addr, UNUM_NEGATIVE_PREFIX);
397202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    }
398202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung
3993b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    public String getNegativeSuffix() {
4003f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        if (negSuffNull) {
4013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            return null;
4023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        return getTextAttribute(this.addr, UNUM_NEGATIVE_SUFFIX);
4043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
4053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    public String getPositivePrefix() {
4073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        if (posPrefNull) {
4083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            return null;
4093f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        }
4103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        return getTextAttribute(this.addr, UNUM_POSITIVE_PREFIX);
4113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
4123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    public String getPositiveSuffix() {
4143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        if (posSuffNull) {
4153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            return null;
4163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        return getTextAttribute(this.addr, UNUM_POSITIVE_SUFFIX);
4183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
419bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
420bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    public boolean isDecimalSeparatorAlwaysShown() {
421bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return getAttribute(this.addr, UNUM_DECIMAL_ALWAYS_SHOWN) != 0;
422bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
423bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
424bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    public boolean isParseIntegerOnly() {
425f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return getAttribute(this.addr, UNUM_PARSE_INT_ONLY) != 0;
426f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
4273ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia
4283ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia    public boolean isGroupingUsed() {
429f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return getAttribute(this.addr, UNUM_GROUPING_USED) != 0;
4307b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
4317b15cb33847e6282ea8352c98894683b796127f3Wei Jia
432f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    public void setDecimalSeparatorAlwaysShown(boolean value) {
433f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        int i = value ? -1 : 0;
434f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        setAttribute(this.addr, UNUM_DECIMAL_ALWAYS_SHOWN, i);
435078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
436078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
437078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    public void setCurrency(Currency currency) {
438078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        setSymbol(this.addr, UNUM_CURRENCY_SYMBOL, currency.getSymbol());
439078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        setSymbol(this.addr, UNUM_INTL_CURRENCY_SYMBOL, currency.getCurrencyCode());
440078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
441078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
442078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    public void setGroupingSize(int value) {
443078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        setAttribute(this.addr, UNUM_GROUPING_SIZE, value);
444078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
445078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
446078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    public void setGroupingUsed(boolean value) {
447078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        int i = value ? -1 : 0;
448d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia        setAttribute(this.addr, UNUM_GROUPING_USED, i);
449d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia    }
450d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia
451078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    public void setMaximumFractionDigits(int value) {
452078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        setAttribute(this.addr, UNUM_MAX_FRACTION_DIGITS, value);
453078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
4547b15cb33847e6282ea8352c98894683b796127f3Wei Jia
455bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    public void setMaximumIntegerDigits(int value) {
456078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        setAttribute(this.addr, UNUM_MAX_INTEGER_DIGITS, value);
457f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
458f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
459f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    public void setMinimumFractionDigits(int value) {
460f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        setAttribute(this.addr, UNUM_MIN_FRACTION_DIGITS, value);
461f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
462f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
4637b15cb33847e6282ea8352c98894683b796127f3Wei Jia    public void setMinimumIntegerDigits(int value) {
4647b15cb33847e6282ea8352c98894683b796127f3Wei Jia        setAttribute(this.addr, UNUM_MIN_INTEGER_DIGITS, value);
465f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
466f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
467f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    public void setMultiplier(int value) {
468f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        setAttribute(this.addr, UNUM_MULTIPLIER, value);
469f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // Update the cached BigDecimal for multiplier.
470f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        multiplierBigDecimal = BigDecimal.valueOf(value);
471f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
4727b15cb33847e6282ea8352c98894683b796127f3Wei Jia
473f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    public void setNegativePrefix(String value) {
474f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        negPrefNull = value == null;
475f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (!negPrefNull) {
476d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            setTextAttribute(this.addr, UNUM_NEGATIVE_PREFIX, value);
477d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
478d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar    }
4797b15cb33847e6282ea8352c98894683b796127f3Wei Jia
4807b15cb33847e6282ea8352c98894683b796127f3Wei Jia    public void setNegativeSuffix(String value) {
481d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        negSuffNull = value == null;
482d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        if (!negSuffNull) {
483d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            setTextAttribute(this.addr, UNUM_NEGATIVE_SUFFIX, value);
484d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
4857b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
486d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
487d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar    public void setPositivePrefix(String value) {
488d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        posPrefNull = value == null;
489f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (!posPrefNull) {
490f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            setTextAttribute(this.addr, UNUM_POSITIVE_PREFIX, value);
491f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
492f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
493f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
494f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    public void setPositiveSuffix(String value) {
495f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        posSuffNull = value == null;
496f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (!posSuffNull) {
497f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            setTextAttribute(this.addr, UNUM_POSITIVE_SUFFIX, value);
498f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
499f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
500f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
5013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    public void setParseIntegerOnly(boolean value) {
5029816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        int i = value ? -1 : 0;
5033a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        setAttribute(this.addr, UNUM_PARSE_INT_ONLY, i);
5043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
5053a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    static protected String getFieldType(Format.Field field) {
5073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field == null) {
5083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return null;
5093a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field.equals(NumberFormat.Field.SIGN)) {
5113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return "sign";
5123a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field.equals(NumberFormat.Field.INTEGER)) {
5143a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return "integer";
5153a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5163a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field.equals(NumberFormat.Field.FRACTION)) {
5173a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return "fraction";
5183a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field.equals(NumberFormat.Field.EXPONENT)) {
5203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return "exponent";
5213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field.equals(NumberFormat.Field.EXPONENT_SIGN)) {
5233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return "exponent_sign";
5243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5253a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field.equals(NumberFormat.Field.EXPONENT_SYMBOL)) {
5263a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return "exponent_symbol";
5273a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5283a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field.equals(NumberFormat.Field.CURRENCY)) {
5293a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return "currency";
5303a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field.equals(NumberFormat.Field.GROUPING_SEPARATOR)) {
5323a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return "grouping_separator";
5333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field.equals(NumberFormat.Field.DECIMAL_SEPARATOR)) {
5353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return "decimal_separator";
5363a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field.equals(NumberFormat.Field.PERCENT)) {
5383a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return "percent";
5393a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(field.equals(NumberFormat.Field.PERMILLE)) {
5413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return "permille";
5423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return null;
5443a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
5453a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    protected Format.Field getField(String type) {
5473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(type.equals("")) {
5483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return null;
5493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(type.equals("sign")) {
5513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return NumberFormat.Field.SIGN;
5523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(type.equals("integer")) {
5543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return NumberFormat.Field.INTEGER;
5553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if(type.equals("fraction")) {
5573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return NumberFormat.Field.FRACTION;
5589816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        }
5599816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        if(type.equals("exponent")) {
5609816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            return NumberFormat.Field.EXPONENT;
561f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
562f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if(type.equals("exponent_sign")) {
563f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            return NumberFormat.Field.EXPONENT_SIGN;
564f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
565f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if(type.equals("exponent_symbol")) {
566f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            return NumberFormat.Field.EXPONENT_SYMBOL;
567bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
568bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if(type.equals("currency")) {
569bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            return NumberFormat.Field.CURRENCY;
570bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
571bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if(type.equals("grouping_separator")) {
572bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            return NumberFormat.Field.GROUPING_SEPARATOR;
573a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        }
574a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        if(type.equals("decimal_separator")) {
575a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            return NumberFormat.Field.DECIMAL_SEPARATOR;
576a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        }
577a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        if(type.equals("percent")) {
578a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            return NumberFormat.Field.PERCENT;
579b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
580b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        if(type.equals("permille")) {
581b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            return NumberFormat.Field.PERMILLE;
582b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
583b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        return null;
584b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
585b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
586b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    private static int openDecimalFormat(String locale, String pattern) {
587b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        try {
588b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            // FIXME: if we're about to override everything, should we just ask for the cheapest locale (presumably the root locale)?
589b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            return openDecimalFormatImpl(locale, pattern);
590b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        } catch (NullPointerException npe) {
591c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            throw npe;
592c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        } catch (RuntimeException re) {
593c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            throw new IllegalArgumentException("syntax error: " + re.getMessage() + ": " + pattern);
594c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
595c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
596c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
597c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    private static void applyPattern(int addr, boolean localized, String pattern) {
598c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        try {
599faeb0f291330134dc4468359a36e099aae508449Ronghua Wu            applyPatternImpl(addr, localized, pattern);
6003a2956d148d81194e297408179e84a47a309ef48Wei Jia        } catch (NullPointerException npe) {
601faeb0f291330134dc4468359a36e099aae508449Ronghua Wu            throw npe;
6023a2956d148d81194e297408179e84a47a309ef48Wei Jia        } catch (RuntimeException re) {
6033a2956d148d81194e297408179e84a47a309ef48Wei Jia            throw new IllegalArgumentException("syntax error: " + re.getMessage() + ": " + pattern);
6043a2956d148d81194e297408179e84a47a309ef48Wei Jia        }
605f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
606f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
607f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    private static native void applyPatternImpl(int addr, boolean localized, String pattern);
6087b15cb33847e6282ea8352c98894683b796127f3Wei Jia    private static native int cloneDecimalFormatImpl(int addr);
609f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    private static native void closeDecimalFormatImpl(int addr);
610f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    private static native String format(int addr, long value, FieldPosition position, String fieldType, StringBuffer attributes);
611f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    private static native String format(int addr, double value, FieldPosition position, String fieldType, StringBuffer attributes);
6120852917279f79a94907e9906d0533ae409a30f6aRonghua Wu    private static native String format(int addr, String value, FieldPosition position, String fieldType, StringBuffer attributes, int scale);
613faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    private static native int getAttribute(int addr, int symbol);
61435d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang    // FIXME: do we need getSymbol any more? the Java-side object should be the canonical source.
615f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    private static native String getSymbol(int addr, int symbol);
616f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    private static native String getTextAttribute(int addr, int symbol);
617f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    private static native int openDecimalFormatImpl(String locale, String pattern);
618f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static native Number parse(int addr, String string, ParsePosition position);
619f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static native void setSymbol(int addr, int symbol, String str);
620f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static native void setSymbol(int addr, int symbol, char ch);
621f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static native void setAttribute(int addr, int symbol, int i);
622f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static native void setTextAttribute(int addr, int symbol, String str);
623f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    private static native String toPatternImpl(int addr, boolean localized);
624bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
625005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung