diff options
| author | Daisuke Miyakawa <dmiyakawa@google.com> | 2009-11-12 11:19:06 +0900 |
|---|---|---|
| committer | Daisuke Miyakawa <dmiyakawa@google.com> | 2009-11-13 08:33:11 +0900 |
| commit | 592988d307e8d305ca163c4e58da0fb350054194 (patch) | |
| tree | 15a0e545564b17d1af7ccdfe1906adeb363298fb /core/java/android/pim | |
| parent | f18a01c77e78209b74e34d05cfb352fa4a92db5f (diff) | |
| download | frameworks_base-592988d307e8d305ca163c4e58da0fb350054194.zip frameworks_base-592988d307e8d305ca163c4e58da0fb350054194.tar.gz frameworks_base-592988d307e8d305ca163c4e58da0fb350054194.tar.bz2 | |
Add unit tests for Japanization and fix several bugs.
Internal issue number: 2195990
Diffstat (limited to 'core/java/android/pim')
| -rw-r--r-- | core/java/android/pim/vcard/ContactStruct.java | 84 | ||||
| -rw-r--r-- | core/java/android/pim/vcard/VCardComposer.java | 82 | ||||
| -rw-r--r-- | core/java/android/pim/vcard/VCardConfig.java | 39 | ||||
| -rw-r--r-- | core/java/android/pim/vcard/VCardUtils.java | 70 |
4 files changed, 167 insertions, 108 deletions
diff --git a/core/java/android/pim/vcard/ContactStruct.java b/core/java/android/pim/vcard/ContactStruct.java index f01659e8..530d5ad 100644 --- a/core/java/android/pim/vcard/ContactStruct.java +++ b/core/java/android/pim/vcard/ContactStruct.java @@ -20,8 +20,10 @@ import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.OperationApplicationException; import android.database.Cursor; +import android.net.Uri; import android.os.RemoteException; import android.provider.ContactsContract; +import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.Groups; import android.provider.ContactsContract.RawContacts; @@ -675,16 +677,53 @@ public class ContactStruct { */ @SuppressWarnings("fallthrough") private void handlePhoneticNameFromSound(List<String> elems) { - // Family, Given, Middle. (1-3) - // This is not from specification but mere assumption. Some Japanese phones use this order. + if (!(TextUtils.isEmpty(mPhoneticFamilyName) && + TextUtils.isEmpty(mPhoneticMiddleName) && + TextUtils.isEmpty(mPhoneticGivenName))) { + // This means the other properties like "X-PHONETIC-FIRST-NAME" was already found. + // Ignore "SOUND;X-IRMC-N". + return; + } + int size; if (elems == null || (size = elems.size()) < 1) { return; } + + // Assume that the order is "Family, Given, Middle". + // This is not from specification but mere assumption. Some Japanese phones use this order. if (size > 3) { size = 3; } + if (elems.get(0).length() > 0) { + boolean onlyFirstElemIsNonEmpty = true; + for (int i = 1; i < size; i++) { + if (elems.get(i).length() > 0) { + onlyFirstElemIsNonEmpty = false; + break; + } + } + if (onlyFirstElemIsNonEmpty) { + final String[] namesArray = elems.get(0).split(" "); + final int nameArrayLength = namesArray.length; + if (nameArrayLength == 3) { + // Assume the string is "Family Middle Given". + mPhoneticFamilyName = namesArray[0]; + mPhoneticMiddleName = namesArray[1]; + mPhoneticGivenName = namesArray[2]; + } else if (nameArrayLength == 2) { + // Assume the string is "Family Given" based on the Japanese mobile + // phones' preference. + mPhoneticFamilyName = namesArray[0]; + mPhoneticGivenName = namesArray[1]; + } else { + mPhoneticFullName = elems.get(0); + } + return; + } + } + switch (size) { // fallthrough case 3: @@ -976,36 +1015,8 @@ public class ContactStruct { if (!TextUtils.isEmpty(mFullName)) { mDisplayName = mFullName; } else if (!(TextUtils.isEmpty(mFamilyName) && TextUtils.isEmpty(mGivenName))) { - StringBuilder builder = new StringBuilder(); - List<String> nameList; - switch (VCardConfig.getNameOrderType(mVCardType)) { - case VCardConfig.NAME_ORDER_JAPANESE: - if (VCardUtils.containsOnlyPrintableAscii(mFamilyName) && - VCardUtils.containsOnlyPrintableAscii(mGivenName)) { - nameList = Arrays.asList(mPrefix, mGivenName, mMiddleName, mFamilyName, mSuffix); - } else { - nameList = Arrays.asList(mPrefix, mFamilyName, mMiddleName, mGivenName, mSuffix); - } - break; - case VCardConfig.NAME_ORDER_EUROPE: - nameList = Arrays.asList(mPrefix, mMiddleName, mGivenName, mFamilyName, mSuffix); - break; - default: - nameList = Arrays.asList(mPrefix, mGivenName, mMiddleName, mFamilyName, mSuffix); - break; - } - boolean first = true; - for (String namePart : nameList) { - if (!TextUtils.isEmpty(namePart)) { - if (first) { - first = false; - } else { - builder.append(' '); - } - builder.append(namePart); - } - } - mDisplayName = builder.toString(); + mDisplayName = VCardUtils.constructNameFromElements(mVCardType, + mFamilyName, mMiddleName, mGivenName, mPrefix, mSuffix); } else if (!(TextUtils.isEmpty(mPhoneticFamilyName) && TextUtils.isEmpty(mPhoneticGivenName))) { mDisplayName = VCardUtils.constructNameFromElements(mVCardType, @@ -1282,6 +1293,15 @@ public class ContactStruct { } } + public static ContactStruct buildFromResolver(ContentResolver resolver) { + return buildFromResolver(resolver, Contacts.CONTENT_URI); + } + + public static ContactStruct buildFromResolver(ContentResolver resolver, Uri uri) { + + return null; + } + private boolean nameFieldsAreEmpty() { return (TextUtils.isEmpty(mFamilyName) && TextUtils.isEmpty(mMiddleName) diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java index 980dd05..b7ad7df 100644 --- a/core/java/android/pim/vcard/VCardComposer.java +++ b/core/java/android/pim/vcard/VCardComposer.java @@ -682,10 +682,18 @@ public class VCardComposer { final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME); final String prefix = contentValues.getAsString(StructuredName.PREFIX); final String suffix = contentValues.getAsString(StructuredName.SUFFIX); + final String phoneticFamilyName = + contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME); + final String phoneticMiddleName = + contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME); + final String phoneticGivenName = + contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME); final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME); return !(TextUtils.isEmpty(familyName) && TextUtils.isEmpty(middleName) && TextUtils.isEmpty(givenName) && TextUtils.isEmpty(prefix) && - TextUtils.isEmpty(suffix) && TextUtils.isEmpty(displayName)); + TextUtils.isEmpty(suffix) && TextUtils.isEmpty(phoneticFamilyName) && + TextUtils.isEmpty(phoneticMiddleName) && TextUtils.isEmpty(phoneticGivenName) && + TextUtils.isEmpty(displayName)); } private void appendStructuredNamesInternal(final StringBuilder builder, @@ -865,17 +873,18 @@ public class VCardComposer { builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_END_OF_LINE); - if (mIsV30) { - builder.append(Constants.PROPERTY_FN); - // TODO: Not allowed formally... - if (shouldAppendCharsetParameter(displayName)) { - builder.append(VCARD_PARAM_SEPARATOR); - builder.append(mVCardCharsetParameter); - } - builder.append(VCARD_DATA_SEPARATOR); - builder.append(encodedDisplayName); - builder.append(VCARD_END_OF_LINE); + builder.append(Constants.PROPERTY_FN); + + // Note: "CHARSET" param is not allowed in vCard 3.0, but we may add it + // when it would be useful for external importers, assuming no external + // importer allows this vioration. + if (shouldAppendCharsetParameter(displayName)) { + builder.append(VCARD_PARAM_SEPARATOR); + builder.append(mVCardCharsetParameter); } + builder.append(VCARD_DATA_SEPARATOR); + builder.append(encodedDisplayName); + builder.append(VCARD_END_OF_LINE); } else if (mIsV30) { // vCard 3.0 specification requires these fields. appendVCardLine(builder, Constants.PROPERTY_N, ""); @@ -913,15 +922,12 @@ public class VCardComposer { .constructNameFromElements(mVCardType, phoneticFamilyName, phoneticMiddleName, phoneticGivenName); builder.append(Constants.PROPERTY_SORT_STRING); - - // Do not need to care about QP, since vCard 3.0 does not allow it. - final String encodedSortString = escapeCharacters(sortString); - if (shouldAppendCharsetParameter(encodedSortString)) { + if (shouldAppendCharsetParameter(sortString)) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(mVCardCharsetParameter); } builder.append(VCARD_DATA_SEPARATOR); - builder.append(encodedSortString); + builder.append(escapeCharacters(sortString)); builder.append(VCARD_END_OF_LINE); } else if (mIsJapaneseMobilePhone) { // Note: There is no appropriate property for expressing @@ -964,11 +970,31 @@ public class VCardComposer { builder.append(mVCardCharsetParameter); } builder.append(VCARD_DATA_SEPARATOR); - builder.append(encodedPhoneticFamilyName); + // DoCoMo's specification requires vCard composer to use just the first + // column. + { + boolean first = true; + if (!TextUtils.isEmpty(encodedPhoneticFamilyName)) { + builder.append(encodedPhoneticFamilyName); + first = false; + } + if (!TextUtils.isEmpty(encodedPhoneticMiddleName)) { + if (first) { + first = false; + } else { + builder.append(' '); + } + builder.append(encodedPhoneticMiddleName); + } + if (!TextUtils.isEmpty(encodedPhoneticGivenName)) { + if (!first) { + builder.append(' '); + } + builder.append(encodedPhoneticGivenName); + } + } builder.append(VCARD_ITEM_SEPARATOR); - builder.append(encodedPhoneticGivenName); builder.append(VCARD_ITEM_SEPARATOR); - builder.append(encodedPhoneticMiddleName); builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_END_OF_LINE); @@ -988,7 +1014,8 @@ public class VCardComposer { if (mUsesDefactProperty) { if (!TextUtils.isEmpty(phoneticGivenName)) { final boolean reallyUseQuotedPrintable = - !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName); + (mUsesQuotedPrintable && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName)); final String encodedPhoneticGivenName; if (reallyUseQuotedPrintable) { encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName); @@ -996,7 +1023,7 @@ public class VCardComposer { encodedPhoneticGivenName = escapeCharacters(phoneticGivenName); } builder.append(Constants.PROPERTY_X_PHONETIC_FIRST_NAME); - if (shouldAppendCharsetParameter(encodedPhoneticGivenName)) { + if (shouldAppendCharsetParameter(phoneticGivenName)) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(mVCardCharsetParameter); } @@ -1010,7 +1037,8 @@ public class VCardComposer { } if (!TextUtils.isEmpty(phoneticMiddleName)) { final boolean reallyUseQuotedPrintable = - !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName); + (mUsesQuotedPrintable && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName)); final String encodedPhoneticMiddleName; if (reallyUseQuotedPrintable) { encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName); @@ -1018,7 +1046,7 @@ public class VCardComposer { encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName); } builder.append(Constants.PROPERTY_X_PHONETIC_MIDDLE_NAME); - if (shouldAppendCharsetParameter(encodedPhoneticMiddleName)) { + if (shouldAppendCharsetParameter(phoneticMiddleName)) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(mVCardCharsetParameter); } @@ -1032,7 +1060,8 @@ public class VCardComposer { } if (!TextUtils.isEmpty(phoneticFamilyName)) { final boolean reallyUseQuotedPrintable = - !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName); + (mUsesQuotedPrintable && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName)); final String encodedPhoneticFamilyName; if (reallyUseQuotedPrintable) { encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName); @@ -1040,7 +1069,7 @@ public class VCardComposer { encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName); } builder.append(Constants.PROPERTY_X_PHONETIC_LAST_NAME); - if (shouldAppendCharsetParameter(encodedPhoneticFamilyName)) { + if (shouldAppendCharsetParameter(phoneticFamilyName)) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(mVCardCharsetParameter); } @@ -2255,8 +2284,7 @@ public class VCardComposer { * to know this text is NOT UTF-8 but Shift_Jis. */ private boolean shouldAppendCharsetParameter(final String propertyValue) { - return (!VCardUtils.containsOnlyPrintableAscii(propertyValue) && - (!mIsV30 || !mUsesUtf8)); + return (!(mIsV30 && mUsesUtf8) && !VCardUtils.containsOnlyPrintableAscii(propertyValue)); } private boolean shouldAppendCharsetParameters(final List<String> propertyValueList) { diff --git a/core/java/android/pim/vcard/VCardConfig.java b/core/java/android/pim/vcard/VCardConfig.java index 545c09b..fff4c82 100644 --- a/core/java/android/pim/vcard/VCardConfig.java +++ b/core/java/android/pim/vcard/VCardConfig.java @@ -60,7 +60,8 @@ public class VCardConfig { // 0x10 is reserved for safety private static final int FLAG_CHARSET_UTF8 = 0; - private static final int FLAG_CHARSET_SHIFT_JIS = 0x20; + private static final int FLAG_CHARSET_SHIFT_JIS = 0x100; + private static final int FLAG_CHARSET_MASK = 0xF00; /** * The flag indicating the vCard composer will add some "X-" properties used only in Android @@ -349,8 +350,8 @@ public class VCardConfig { sJapaneseMobileTypeSet.add(VCARD_TYPE_DOCOMO); } - public static int getVCardTypeFromString(String vcardTypeString) { - String loweredKey = vcardTypeString.toLowerCase(); + public static int getVCardTypeFromString(final String vcardTypeString) { + final String loweredKey = vcardTypeString.toLowerCase(); if (sVCardTypeMap.containsKey(loweredKey)) { return sVCardTypeMap.get(loweredKey); } else { @@ -360,31 +361,31 @@ public class VCardConfig { } } - public static boolean isV30(int vcardType) { + public static boolean isV30(final int vcardType) { return ((vcardType & FLAG_V30) != 0); } - public static boolean usesQuotedPrintable(int vcardType) { + public static boolean usesQuotedPrintable(final int vcardType) { return !isV30(vcardType); } - public static boolean usesUtf8(int vcardType) { - return ((vcardType & FLAG_CHARSET_UTF8) != 0); + public static boolean usesUtf8(final int vcardType) { + return ((vcardType & FLAG_CHARSET_MASK) == FLAG_CHARSET_UTF8); } - public static boolean usesShiftJis(int vcardType) { - return ((vcardType & FLAG_CHARSET_SHIFT_JIS) != 0); + public static boolean usesShiftJis(final int vcardType) { + return ((vcardType & FLAG_CHARSET_MASK) == FLAG_CHARSET_SHIFT_JIS); } - - public static int getNameOrderType(int vcardType) { + + public static int getNameOrderType(final int vcardType) { return vcardType & NAME_ORDER_MASK; } - public static boolean usesAndroidSpecificProperty(int vcardType) { + public static boolean usesAndroidSpecificProperty(final int vcardType) { return ((vcardType & FLAG_USE_ANDROID_PROPERTY) != 0); } - public static boolean usesDefactProperty(int vcardType) { + public static boolean usesDefactProperty(final int vcardType) { return ((vcardType & FLAG_USE_DEFACT_PROPERTY) != 0); } @@ -392,12 +393,12 @@ public class VCardConfig { return (VCardConfig.LOG_LEVEL & VCardConfig.LOG_LEVEL_PERFORMANCE_MEASUREMENT) != 0; } - public static boolean refrainsQPToPrimaryProperties(int vcardType) { + public static boolean refrainsQPToPrimaryProperties(final int vcardType) { return (!usesQuotedPrintable(vcardType) || ((vcardType & FLAG_REFRAIN_QP_TO_PRIMARY_PROPERTIES) != 0)); } - public static boolean appendTypeParamName(int vcardType) { + public static boolean appendTypeParamName(final int vcardType) { return (isV30(vcardType) || ((vcardType & FLAG_APPEND_TYPE_PARAM) != 0)); } @@ -405,19 +406,19 @@ public class VCardConfig { * @return true if the device is Japanese and some Japanese convension is * applied to creating "formatted" something like FORMATTED_ADDRESS. */ - public static boolean isJapaneseDevice(int vcardType) { + public static boolean isJapaneseDevice(final int vcardType) { return sJapaneseMobileTypeSet.contains(vcardType); } - public static boolean needsToConvertPhoneticString(int vcardType) { + public static boolean needsToConvertPhoneticString(final int vcardType) { return ((vcardType & FLAG_CONVERT_PHONETIC_NAME_STRINGS) != 0); } - public static boolean onlyOneNoteFieldIsAvailable(int vcardType) { + public static boolean onlyOneNoteFieldIsAvailable(final int vcardType) { return vcardType == VCARD_TYPE_DOCOMO; } - public static boolean isDoCoMo(int vcardType) { + public static boolean isDoCoMo(final int vcardType) { return ((vcardType & FLAG_DOCOMO) != 0); } diff --git a/core/java/android/pim/vcard/VCardUtils.java b/core/java/android/pim/vcard/VCardUtils.java index 9e5dbb5..00679bd 100644 --- a/core/java/android/pim/vcard/VCardUtils.java +++ b/core/java/android/pim/vcard/VCardUtils.java @@ -23,6 +23,7 @@ import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; import android.telephony.PhoneNumberUtils; import android.text.TextUtils; +import android.util.Log; import java.util.ArrayList; import java.util.Collection; @@ -181,26 +182,36 @@ public class VCardUtils { sPhoneTypesSetUnknownToContacts.contains(phoneType)); } - public static String[] sortNameElements(int vcardType, - String familyName, String middleName, String givenName) { - String[] list = new String[3]; - switch (VCardConfig.getNameOrderType(vcardType)) { - case VCardConfig.NAME_ORDER_JAPANESE: - // TODO: Should handle Ascii case? - list[0] = familyName; - list[1] = middleName; - list[2] = givenName; - break; - case VCardConfig.NAME_ORDER_EUROPE: - list[0] = middleName; - list[1] = givenName; - list[2] = familyName; - break; - default: - list[0] = givenName; - list[1] = middleName; - list[2] = familyName; - break; + public static String[] sortNameElements(final int vcardType, + final String familyName, final String middleName, final String givenName) { + final String[] list = new String[3]; + final int nameOrderType = VCardConfig.getNameOrderType(vcardType); + switch (nameOrderType) { + case VCardConfig.NAME_ORDER_JAPANESE: { + if (containsOnlyPrintableAscii(familyName) && + containsOnlyPrintableAscii(givenName)) { + list[0] = givenName; + list[1] = middleName; + list[2] = familyName; + } else { + list[0] = familyName; + list[1] = middleName; + list[2] = givenName; + } + break; + } + case VCardConfig.NAME_ORDER_EUROPE: { + list[0] = middleName; + list[1] = givenName; + list[2] = familyName; + break; + } + default: { + list[0] = givenName; + list[1] = middleName; + list[2] = familyName; + break; + } } return list; } @@ -302,24 +313,23 @@ public class VCardUtils { return dataArray; } - public static String constructNameFromElements(int nameOrderType, - String familyName, String middleName, String givenName) { - return constructNameFromElements(nameOrderType, familyName, middleName, givenName, + public static String constructNameFromElements(final int vcardType, + final String familyName, final String middleName, final String givenName) { + return constructNameFromElements(vcardType, familyName, middleName, givenName, null, null); } - public static String constructNameFromElements(int nameOrderType, - String familyName, String middleName, String givenName, - String prefix, String suffix) { - StringBuilder builder = new StringBuilder(); - String[] nameList = sortNameElements(nameOrderType, - familyName, middleName, givenName); + public static String constructNameFromElements(final int vcardType, + final String familyName, final String middleName, final String givenName, + final String prefix, final String suffix) { + final StringBuilder builder = new StringBuilder(); + final String[] nameList = sortNameElements(vcardType, familyName, middleName, givenName); boolean first = true; if (!TextUtils.isEmpty(prefix)) { first = false; builder.append(prefix); } - for (String namePart : nameList) { + for (final String namePart : nameList) { if (!TextUtils.isEmpty(namePart)) { if (first) { first = false; |
