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