1b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein/*
2b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * Copyright (C) 2009 The Android Open Source Project
3b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein *
4b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * Licensed under the Apache License, Version 2.0 (the "License");
5b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * you may not use this file except in compliance with the License.
6b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * You may obtain a copy of the License at
7b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein *
8b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein *      http://www.apache.org/licenses/LICENSE-2.0
9b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein *
10b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * Unless required by applicable law or agreed to in writing, software
11b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * distributed under the License is distributed on an "AS IS" BASIS,
12b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * See the License for the specific language governing permissions and
14b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * limitations under the License.
15b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein */
16b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
17b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornsteinpackage android.util;
18b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
19b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornsteinimport android.os.Build;
20df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawaimport android.text.TextUtils;
21b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
22b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornsteinimport java.nio.charset.Charset;
23b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornsteinimport java.nio.charset.IllegalCharsetNameException;
24b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornsteinimport java.nio.charset.UnsupportedCharsetException;
25df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawaimport java.util.HashMap;
26df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawaimport java.util.Map;
27b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
28b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein/**
29df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa * <p>
30b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * A class containing utility methods related to character sets. This
31b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * class is primarily useful for code that wishes to be vendor-aware
32df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa * in its interpretation of Japanese charset names (used in DoCoMo,
33df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa * KDDI, and SoftBank).
34df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa * </p>
35df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa *
36df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa * <p>
37df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa * <b>Note:</b> Developers will need to add an appropriate mapping for
38df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa * each vendor-specific charset. You may need to modify the C libraries
39df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa * like icu4c in order to let Android support an additional charset.
40df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa * </p>
41df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa *
42b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein * @hide
43b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein */
44b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornsteinpublic final class CharsetUtils {
45b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    /**
46df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa     * name of the vendor "DoCoMo". <b>Note:</b> This isn't a public
47b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * constant, in order to keep this class from becoming a de facto
48b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * reference list of vendor names.
49b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     */
50b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    private static final String VENDOR_DOCOMO = "docomo";
51df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa    /**
52df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa     * Name of the vendor "KDDI".
53df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa     */
54df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa    private static final String VENDOR_KDDI = "kddi";
55df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa    /**
56df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa     * Name of the vendor "SoftBank".
57df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa     */
58df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa    private static final String VENDOR_SOFTBANK = "softbank";
59df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa
60df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa    /**
61df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa     * Represents one-to-one mapping from a vendor name to a charset specific to the vendor.
62df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa     */
63df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa    private static final Map<String, String> sVendorShiftJisMap = new HashMap<String, String>();
64df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa
65df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa    static {
66df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa        // These variants of Shift_JIS come from icu's mapping data (convrtrs.txt)
67df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa        sVendorShiftJisMap.put(VENDOR_DOCOMO, "docomo-shift_jis-2007");
68df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa        sVendorShiftJisMap.put(VENDOR_KDDI, "kddi-shift_jis-2007");
69df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa        sVendorShiftJisMap.put(VENDOR_SOFTBANK, "softbank-shift_jis-2007");
70df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa    }
71df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa
72b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    /**
73b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * This class is uninstantiable.
74b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     */
75b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    private CharsetUtils() {
76b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein        // This space intentionally left blank.
77b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    }
78b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
79b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    /**
80b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * Returns the name of the vendor-specific character set
81b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * corresponding to the given original character set name and
82b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * vendor. If there is no vendor-specific character set for the
83df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa     * given name/vendor pair, this returns the original character set name.
84df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa     *
85b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @param charsetName the base character set name
86df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa     * @param vendor the vendor to specialize for. All characters should be lower-cased.
87b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @return the specialized character set name, or {@code charsetName} if
88b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * there is no specialized name
89b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     */
90b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    public static String nameForVendor(String charsetName, String vendor) {
91df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa        if (!TextUtils.isEmpty(charsetName) && !TextUtils.isEmpty(vendor)) {
92df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa            // You can add your own mapping here.
93df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa            if (isShiftJis(charsetName)) {
94df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa                final String vendorShiftJis = sVendorShiftJisMap.get(vendor);
95df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa                if (vendorShiftJis != null) {
96df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa                    return vendorShiftJis;
97df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa                }
98df3f1cc3fe1b9b4f598a084d6ff385482836f7ecDaisuke Miyakawa            }
99b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein        }
100b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
101b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein        return charsetName;
102b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    }
103b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
104b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    /**
105b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * Returns the name of the vendor-specific character set
106b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * corresponding to the given original character set name and the
107b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * default vendor (that is, the targeted vendor of the device this
108b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * code is running on). This method merely calls through to
109b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * {@link #nameForVendor(String,String)}, passing the default vendor
110b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * as the second argument.
111b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     *
112b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @param charsetName the base character set name
113b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @return the specialized character set name, or {@code charsetName} if
114b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * there is no specialized name
115b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     */
116b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    public static String nameForDefaultVendor(String charsetName) {
117b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein        return nameForVendor(charsetName, getDefaultVendor());
118b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    }
119b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
120b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    /**
121b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * Returns the vendor-specific character set corresponding to the
122b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * given original character set name and vendor. If there is no
123b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * vendor-specific character set for the given name/vendor pair,
124b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * this returns the character set corresponding to the original
125b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * name. The vendor name is matched case-insensitively. This
126b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * method merely calls {@code Charset.forName()} on a name
127b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * transformed by a call to {@link #nameForVendor(String,String)}.
128b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     *
129b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @param charsetName the base character set name
130b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @param vendor the vendor to specialize for
131b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @return the specialized character set, or the one corresponding
132b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * directly to {@code charsetName} if there is no specialized
133b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * variant
134b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @throws UnsupportedCharsetException thrown if the named character
135b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * set is not supported by the system
136b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @throws IllegalCharsetNameException thrown if {@code charsetName}
137b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * has invalid syntax
138b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     */
139b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    public static Charset charsetForVendor(String charsetName, String vendor)
140b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein            throws UnsupportedCharsetException, IllegalCharsetNameException {
141b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein        charsetName = nameForVendor(charsetName, vendor);
142b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein        return Charset.forName(charsetName);
143b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    }
144b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
145b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    /**
146b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * Returns the vendor-specific character set corresponding to the
147b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * given original character set name and default vendor (that is,
148b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * the targeted vendor of the device this code is running on).
149b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * This method merely calls through to {@link
150b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * #charsetForVendor(String,String)}, passing the default vendor
151b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * as the second argument.
152b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     *
153b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @param charsetName the base character set name
154b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @return the specialized character set, or the one corresponding
155b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * directly to {@code charsetName} if there is no specialized
156b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * variant
157b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @throws UnsupportedCharsetException thrown if the named character
158b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * set is not supported by the system
159b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @throws IllegalCharsetNameException thrown if {@code charsetName}
160b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * has invalid syntax
161b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     */
162b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    public static Charset charsetForVendor(String charsetName)
163b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein            throws UnsupportedCharsetException, IllegalCharsetNameException {
164b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein        return charsetForVendor(charsetName, getDefaultVendor());
165b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    }
166b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
167b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    /**
168b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * Returns whether the given character set name indicates the Shift-JIS
169f0c6ab843e7261755483d1c48e4c03f630cc79b5Daisuke Miyakawa     * encoding. Returns false if the name is null.
170b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     *
171b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @param charsetName the character set name
172b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @return {@code true} if the name corresponds to Shift-JIS or
173b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * {@code false} if not
174b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     */
175b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    private static boolean isShiftJis(String charsetName) {
176f0c6ab843e7261755483d1c48e4c03f630cc79b5Daisuke Miyakawa        // Bail quickly if the length doesn't match.
177f0c6ab843e7261755483d1c48e4c03f630cc79b5Daisuke Miyakawa        if (charsetName == null) {
178f0c6ab843e7261755483d1c48e4c03f630cc79b5Daisuke Miyakawa            return false;
179f0c6ab843e7261755483d1c48e4c03f630cc79b5Daisuke Miyakawa        }
180f0c6ab843e7261755483d1c48e4c03f630cc79b5Daisuke Miyakawa        int length = charsetName.length();
181f0c6ab843e7261755483d1c48e4c03f630cc79b5Daisuke Miyakawa        if (length != 4 && length != 9) {
182b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein            return false;
183b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein        }
184b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
185b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein        return charsetName.equalsIgnoreCase("shift_jis")
186f0c6ab843e7261755483d1c48e4c03f630cc79b5Daisuke Miyakawa            || charsetName.equalsIgnoreCase("shift-jis")
187f0c6ab843e7261755483d1c48e4c03f630cc79b5Daisuke Miyakawa            || charsetName.equalsIgnoreCase("sjis");
188b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    }
189b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein
190b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    /**
191b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * Gets the default vendor for this build.
192b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     *
193b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     * @return the default vendor name
194b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein     */
195b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    private static String getDefaultVendor() {
196b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein        return Build.BRAND;
197b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein    }
198b4c218eafd382da778bcc0006de9b8fce267a9cdDan Bornstein}
199