/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.util; import android.os.Build; import android.text.TextUtils; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; import java.util.HashMap; import java.util.Map; /** * <p> * A class containing utility methods related to character sets. This * class is primarily useful for code that wishes to be vendor-aware * in its interpretation of Japanese charset names (used in DoCoMo, * KDDI, and SoftBank). * </p> * * <p> * <b>Note:</b> Developers will need to add an appropriate mapping for * each vendor-specific charset. You may need to modify the C libraries * like icu4c in order to let Android support an additional charset. * </p> * * @hide */ public final class CharsetUtils { /** * name of the vendor "DoCoMo". <b>Note:</b> This isn't a public * constant, in order to keep this class from becoming a de facto * reference list of vendor names. */ private static final String VENDOR_DOCOMO = "docomo"; /** * Name of the vendor "KDDI". */ private static final String VENDOR_KDDI = "kddi"; /** * Name of the vendor "SoftBank". */ private static final String VENDOR_SOFTBANK = "softbank"; /** * Represents one-to-one mapping from a vendor name to a charset specific to the vendor. */ private static final Map<String, String> sVendorShiftJisMap = new HashMap<String, String>(); static { // These variants of Shift_JIS come from icu's mapping data (convrtrs.txt) sVendorShiftJisMap.put(VENDOR_DOCOMO, "docomo-shift_jis-2007"); sVendorShiftJisMap.put(VENDOR_KDDI, "kddi-shift_jis-2007"); sVendorShiftJisMap.put(VENDOR_SOFTBANK, "softbank-shift_jis-2007"); } /** * This class is uninstantiable. */ private CharsetUtils() { // This space intentionally left blank. } /** * Returns the name of the vendor-specific character set * corresponding to the given original character set name and * vendor. If there is no vendor-specific character set for the * given name/vendor pair, this returns the original character set name. * * @param charsetName the base character set name * @param vendor the vendor to specialize for. All characters should be lower-cased. * @return the specialized character set name, or {@code charsetName} if * there is no specialized name */ public static String nameForVendor(String charsetName, String vendor) { if (!TextUtils.isEmpty(charsetName) && !TextUtils.isEmpty(vendor)) { // You can add your own mapping here. if (isShiftJis(charsetName)) { final String vendorShiftJis = sVendorShiftJisMap.get(vendor); if (vendorShiftJis != null) { return vendorShiftJis; } } } return charsetName; } /** * Returns the name of the vendor-specific character set * corresponding to the given original character set name and the * default vendor (that is, the targeted vendor of the device this * code is running on). This method merely calls through to * {@link #nameForVendor(String,String)}, passing the default vendor * as the second argument. * * @param charsetName the base character set name * @return the specialized character set name, or {@code charsetName} if * there is no specialized name */ public static String nameForDefaultVendor(String charsetName) { return nameForVendor(charsetName, getDefaultVendor()); } /** * Returns the vendor-specific character set corresponding to the * given original character set name and vendor. If there is no * vendor-specific character set for the given name/vendor pair, * this returns the character set corresponding to the original * name. The vendor name is matched case-insensitively. This * method merely calls {@code Charset.forName()} on a name * transformed by a call to {@link #nameForVendor(String,String)}. * * @param charsetName the base character set name * @param vendor the vendor to specialize for * @return the specialized character set, or the one corresponding * directly to {@code charsetName} if there is no specialized * variant * @throws UnsupportedCharsetException thrown if the named character * set is not supported by the system * @throws IllegalCharsetNameException thrown if {@code charsetName} * has invalid syntax */ public static Charset charsetForVendor(String charsetName, String vendor) throws UnsupportedCharsetException, IllegalCharsetNameException { charsetName = nameForVendor(charsetName, vendor); return Charset.forName(charsetName); } /** * Returns the vendor-specific character set corresponding to the * given original character set name and default vendor (that is, * the targeted vendor of the device this code is running on). * This method merely calls through to {@link * #charsetForVendor(String,String)}, passing the default vendor * as the second argument. * * @param charsetName the base character set name * @return the specialized character set, or the one corresponding * directly to {@code charsetName} if there is no specialized * variant * @throws UnsupportedCharsetException thrown if the named character * set is not supported by the system * @throws IllegalCharsetNameException thrown if {@code charsetName} * has invalid syntax */ public static Charset charsetForVendor(String charsetName) throws UnsupportedCharsetException, IllegalCharsetNameException { return charsetForVendor(charsetName, getDefaultVendor()); } /** * Returns whether the given character set name indicates the Shift-JIS * encoding. Returns false if the name is null. * * @param charsetName the character set name * @return {@code true} if the name corresponds to Shift-JIS or * {@code false} if not */ private static boolean isShiftJis(String charsetName) { // Bail quickly if the length doesn't match. if (charsetName == null) { return false; } int length = charsetName.length(); if (length != 4 && length != 9) { return false; } return charsetName.equalsIgnoreCase("shift_jis") || charsetName.equalsIgnoreCase("shift-jis") || charsetName.equalsIgnoreCase("sjis"); } /** * Gets the default vendor for this build. * * @return the default vendor name */ private static String getDefaultVendor() { return Build.BRAND; } }