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