VCardBuilder.java revision 3d77102a83d0e412046ca0ff9dfdef1a44050ca3
14199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/* 24199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Copyright (C) 2009 The Android Open Source Project 34199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 44199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License"); you may not 54199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * use this file except in compliance with the License. You may obtain a copy of 64199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * the License at 74199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 84199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * http://www.apache.org/licenses/LICENSE-2.0 94199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software 114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * License for the specific language governing permissions and limitations under 144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * the License. 154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapackage com.android.vcard; 174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1836ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawaimport com.android.vcard.exception.VCardException; 1936ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa 204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentValues; 214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Email; 224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Event; 234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Im; 244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Nickname; 254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Note; 264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Organization; 274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Phone; 284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Photo; 294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Relation; 304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Website; 334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.telephony.PhoneNumberUtils; 344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.text.TextUtils; 354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Base64; 364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.CharsetUtils; 374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Log; 384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.UnsupportedEncodingException; 404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.nio.charset.UnsupportedCharsetException; 414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList; 424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Arrays; 434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Collections; 444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.HashMap; 454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.HashSet; 464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.List; 474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Map; 484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Set; 494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/** 514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The class which lets users create their own vCard String. Typical usage is as follows: 534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <pre class="prettyprint">final VCardBuilder builder = new VCardBuilder(vcardType); 554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE)) 564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE)) 574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE)) 584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE)) 594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE)) 604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE)) 614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE)) 624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE)) 634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE)) 644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE)) 654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE)) 664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE)); 674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * return builder.toString();</pre> 684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapublic class VCardBuilder { 704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String LOG_TAG = "VCardBuilder"; 714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // If you add the other element, please check all the columns are able to be 734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // converted to String. 744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // e.g. BLOB is not what we can handle here now. 764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final Set<String> sAllowedAndroidPropertySet = 774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Collections.unmodifiableSet(new HashSet<String>(Arrays.asList( 784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Nickname.CONTENT_ITEM_TYPE, Event.CONTENT_ITEM_TYPE, 794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Relation.CONTENT_ITEM_TYPE))); 804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final int DEFAULT_PHONE_TYPE = Phone.TYPE_HOME; 824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final int DEFAULT_POSTAL_TYPE = StructuredPostal.TYPE_HOME; 834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final int DEFAULT_EMAIL_TYPE = Email.TYPE_OTHER; 844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_DATA_VCARD = "VCARD"; 864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_DATA_PUBLIC = "PUBLIC"; 874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_PARAM_SEPARATOR = ";"; 894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_END_OF_LINE = "\r\n"; 904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_DATA_SEPARATOR = ":"; 914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_ITEM_SEPARATOR = ";"; 924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_WS = " "; 934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_PARAM_EQUAL = "="; 944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_PARAM_ENCODING_QP = 964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "ENCODING=" + VCardConstants.PARAM_ENCODING_QP; 974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_PARAM_ENCODING_BASE64_V21 = 984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "ENCODING=" + VCardConstants.PARAM_ENCODING_BASE64; 9936ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa private static final String VCARD_PARAM_ENCODING_BASE64_AS_B = 1004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "ENCODING=" + VCardConstants.PARAM_ENCODING_B; 1014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String SHIFT_JIS = "SHIFT_JIS"; 1034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final int mVCardType; 1054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 10636ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa private final boolean mIsV30OrV40; 1074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mIsJapaneseMobilePhone; 1084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mOnlyOneNoteFieldIsAvailable; 1094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mIsDoCoMo; 1104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mShouldUseQuotedPrintable; 1114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mUsesAndroidProperty; 1124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mUsesDefactProperty; 1134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mAppendTypeParamName; 1144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mRefrainsQPToNameProperties; 1154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mNeedsToConvertPhoneticString; 1164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mShouldAppendCharsetParam; 1184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final String mCharset; 1204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final String mVCardCharsetParameter; 1214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private StringBuilder mBuilder; 1234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private boolean mEndAppended; 1244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder(final int vcardType) { 1264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Default charset should be used 1274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(vcardType, null); 1284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param vcardType 1324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param charset If null, we use default charset for export. 13336ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa * @hide 1344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder(final int vcardType, String charset) { 1364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mVCardType = vcardType; 1374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 13836ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa Log.w(LOG_TAG, 13936ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa "Should not use vCard 4.0 when building vCard. " + 14036ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa "It is not officially published yet."); 14136ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa 14236ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa mIsV30OrV40 = VCardConfig.isVersion30(vcardType) || VCardConfig.isVersion40(vcardType); 1434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mShouldUseQuotedPrintable = VCardConfig.shouldUseQuotedPrintable(vcardType); 1444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); 1454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mIsJapaneseMobilePhone = VCardConfig.needsToConvertPhoneticString(vcardType); 1464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mOnlyOneNoteFieldIsAvailable = VCardConfig.onlyOneNoteFieldIsAvailable(vcardType); 1474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mUsesAndroidProperty = VCardConfig.usesAndroidSpecificProperty(vcardType); 1484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mUsesDefactProperty = VCardConfig.usesDefactProperty(vcardType); 1494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mRefrainsQPToNameProperties = VCardConfig.shouldRefrainQPToNameProperties(vcardType); 1504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mAppendTypeParamName = VCardConfig.appendTypeParamName(vcardType); 1514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mNeedsToConvertPhoneticString = VCardConfig.needsToConvertPhoneticString(vcardType); 1524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // vCard 2.1 requires charset. 1544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // vCard 3.0 does not allow it but we found some devices use it to determine 1554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // the exact charset. 1564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We currently append it only when charset other than UTF_8 is used. 15736ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa mShouldAppendCharsetParam = 15836ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa !(VCardConfig.isVersion30(vcardType) && "UTF-8".equalsIgnoreCase(charset)); 1594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (VCardConfig.isDoCoMo(vcardType)) { 1614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!SHIFT_JIS.equalsIgnoreCase(charset)) { 1624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, 1634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "The charset \"" + charset + "\" is used while " 1644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + SHIFT_JIS + " is needed to be used."); 1654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(charset)) { 1664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = SHIFT_JIS; 1674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 1684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 1694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(charset).name(); 1704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 1714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.i(LOG_TAG, 1724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Career-specific \"" + charset + "\" was not found (as usual). " 1734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use it as is."); 1744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 1764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 1784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 1794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 1804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); 1814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 1824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, 1834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "DoCoMo-specific SHIFT_JIS was not found. " 1844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use SHIFT_JIS as is."); 1854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = SHIFT_JIS; 1864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 1884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 1894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); 1904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 1914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, 1924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Career-specific SHIFT_JIS was not found. " 1934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use SHIFT_JIS as is."); 1944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = SHIFT_JIS; 1954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 1984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mVCardCharsetParameter = "CHARSET=" + SHIFT_JIS; 2004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(charset)) { 2024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.i(LOG_TAG, 2034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Use the charset \"" + VCardConfig.DEFAULT_EXPORT_CHARSET 2044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "\" for export."); 2054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = VCardConfig.DEFAULT_EXPORT_CHARSET; 2064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mVCardCharsetParameter = "CHARSET=" + VCardConfig.DEFAULT_EXPORT_CHARSET; 2074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 2094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(charset).name(); 2104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 2114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.i(LOG_TAG, 2124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Career-specific \"" + charset + "\" was not found (as usual). " 2134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use it as is."); 2144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 2164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mVCardCharsetParameter = "CHARSET=" + charset; 2174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa clear(); 2204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void clear() { 2234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder = new StringBuilder(); 2244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mEndAppended = false; 2254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_BEGIN, VCARD_DATA_VCARD); 22636ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa if (VCardConfig.isVersion40(mVCardType)) { 22736ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V40); 22836ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa } else if (VCardConfig.isVersion30(mVCardType)) { 2294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V30); 2304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 23136ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa if (!VCardConfig.isVersion21(mVCardType)) { 23236ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa Log.w(LOG_TAG, "Unknown vCard version detected."); 23336ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa } 2344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V21); 2354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private boolean containsNonEmptyName(final ContentValues contentValues) { 2394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME); 2404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME); 2414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME); 2424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String prefix = contentValues.getAsString(StructuredName.PREFIX); 2434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String suffix = contentValues.getAsString(StructuredName.SUFFIX); 2444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticFamilyName = 2454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME); 2464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticMiddleName = 2474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME); 2484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticGivenName = 2494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME); 2504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME); 2514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return !(TextUtils.isEmpty(familyName) && TextUtils.isEmpty(middleName) && 2524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa TextUtils.isEmpty(givenName) && TextUtils.isEmpty(prefix) && 2534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa TextUtils.isEmpty(suffix) && TextUtils.isEmpty(phoneticFamilyName) && 2544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa TextUtils.isEmpty(phoneticMiddleName) && TextUtils.isEmpty(phoneticGivenName) && 2554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa TextUtils.isEmpty(displayName)); 2564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private ContentValues getPrimaryContentValue(final List<ContentValues> contentValuesList) { 2594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ContentValues primaryContentValues = null; 2604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ContentValues subprimaryContentValues = null; 2614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 2624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null){ 2634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 2644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Integer isSuperPrimary = contentValues.getAsInteger(StructuredName.IS_SUPER_PRIMARY); 2664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isSuperPrimary != null && isSuperPrimary > 0) { 2674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We choose "super primary" ContentValues. 2684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryContentValues = contentValues; 2694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 2704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (primaryContentValues == null) { 2714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We choose the first "primary" ContentValues 2724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // if "super primary" ContentValues does not exist. 2734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isPrimary = contentValues.getAsInteger(StructuredName.IS_PRIMARY); 2744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary != null && isPrimary > 0 && 2754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa containsNonEmptyName(contentValues)) { 2764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryContentValues = contentValues; 2774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Do not break, since there may be ContentValues with "super primary" 2784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // afterword. 2794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (subprimaryContentValues == null && 2804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa containsNonEmptyName(contentValues)) { 2814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa subprimaryContentValues = contentValues; 2824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (primaryContentValues == null) { 2874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (subprimaryContentValues != null) { 2884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We choose the first ContentValues if any "primary" ContentValues does not exist. 2894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryContentValues = subprimaryContentValues; 2904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "All ContentValues given from database is empty."); 2924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryContentValues = new ContentValues(); 2934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return primaryContentValues; 2974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 3003d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa * To avoid unnecessary complication in logic, we use this method to construct N, FN 3013d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa * properties for vCard 4.0. 3023d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa */ 3033d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa private VCardBuilder appendNamePropertiesV40(final List<ContentValues> contentValuesList) { 3043d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa if (mIsDoCoMo || mNeedsToConvertPhoneticString) { 3053d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // Ignore all flags that look stale from the view of vCard 4.0 to 3063d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // simplify construction algorithm. Actually we don't have any vCard file 3073d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // available from real world yet, so we may need to re-enable some of these 3083d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // in the future. 3093d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa Log.w(LOG_TAG, "Invalid flag is used in vCard 4.0 construction. Ignored."); 3103d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa } 3113d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 3123d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa if (contentValuesList == null || contentValuesList.isEmpty()) { 3133d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_FN, ""); 3143d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa return this; 3153d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa } 3163d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 3173d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // We have difficulty here. How can we appropriately handle StructuredName with 3183d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // missing parts necessary for displaying while it has suppremental information. 3193d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // 3203d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // e.g. How to handle non-empty phonetic names with empty structured names? 3213d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 3223d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final ContentValues contentValues = getPrimaryContentValue(contentValuesList); 3233d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME); 3243d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME); 3253d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME); 3263d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String prefix = contentValues.getAsString(StructuredName.PREFIX); 3273d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String suffix = contentValues.getAsString(StructuredName.SUFFIX); 3283d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String formattedName = contentValues.getAsString(StructuredName.DISPLAY_NAME); 3293d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa if (TextUtils.isEmpty(familyName) 3303d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa && TextUtils.isEmpty(givenName) 3313d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa && TextUtils.isEmpty(middleName) 3323d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa && TextUtils.isEmpty(prefix) 3333d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa && TextUtils.isEmpty(suffix)) { 3343d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa if (TextUtils.isEmpty(formattedName)) { 3353d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_FN, ""); 3363d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa return this; 3373d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa } 3383d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa familyName = formattedName; 3393d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa } 3403d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 3413d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String phoneticFamilyName = 3423d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME); 3433d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String phoneticMiddleName = 3443d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME); 3453d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String phoneticGivenName = 3463d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME); 3473d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String escapedFamily = escapeCharacters(familyName); 3483d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String escapedGiven = escapeCharacters(givenName); 3493d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String escapedMiddle = escapeCharacters(middleName); 3503d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String escapedPrefix = escapeCharacters(prefix); 3513d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String escapedSuffix = escapeCharacters(suffix); 3523d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 3533d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_N); 3543d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 3553d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa if (!(TextUtils.isEmpty(phoneticFamilyName) && 3563d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa TextUtils.isEmpty(phoneticMiddleName) && 3573d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa TextUtils.isEmpty(phoneticGivenName))) { 3583d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 3593d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String sortAs = escapeCharacters(phoneticFamilyName) 3603d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa + ';' + escapeCharacters(phoneticGivenName) 3613d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa + ';' + escapeCharacters(phoneticMiddleName); 3623d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append("SORT-AS=").append( 3633d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa VCardUtils.toStringAsV40ParamValue(sortAs)); 3643d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa } 3653d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 3663d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 3673d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(escapedFamily); 3683d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 3693d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(escapedGiven); 3703d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 3713d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(escapedMiddle); 3723d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 3733d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(escapedPrefix); 3743d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 3753d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(escapedSuffix); 3763d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 3773d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 3783d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa if (TextUtils.isEmpty(formattedName)) { 3793d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // Note: 3803d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // DISPLAY_NAME doesn't exist while some other elements do, which is usually 3813d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // weird in Android, as DISPLAY_NAME should (usually) be constructed 3823d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // from the others using locale information and its code points. 3833d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa Log.w(LOG_TAG, "DISPLAY_NAME is empty."); 3843d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 3853d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String escaped = escapeCharacters(VCardUtils.constructNameFromElements( 3863d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa VCardConfig.getNameOrderType(mVCardType), 3873d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa familyName, middleName, givenName, prefix, suffix)); 3883d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_FN, escaped); 3893d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa } else { 3903d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String escapedFormatted = escapeCharacters(formattedName); 3913d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_FN); 3923d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 3933d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(escapedFormatted); 3943d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 3953d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa } 3963d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 3973d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // We may need X- properties for phonetic names. 3983d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa appendPhoneticNameFields(contentValues); 3993d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa return this; 4003d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa } 4013d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 4023d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa /** 4034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * For safety, we'll emit just one value around StructuredName, as external importers 4044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * may get confused with multiple "N", "FN", etc. properties, though it is valid in 4054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * vCard spec. 4064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 4074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendNameProperties(final List<ContentValues> contentValuesList) { 4083d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa if (VCardConfig.isVersion40(mVCardType)) { 4093d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa return appendNamePropertiesV40(contentValuesList); 4103d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa } 4113d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 4124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList == null || contentValuesList.isEmpty()) { 4133d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa if (VCardConfig.isVersion30(mVCardType)) { 4144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // vCard 3.0 requires "N" and "FN" properties. 41536ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa // vCard 4.0 does NOT require N, but we take care of possible backward 41636ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa // compatibility issues. 4174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_N, ""); 4184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_FN, ""); 41936ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa } else if (mIsDoCoMo) { 42036ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_N, ""); 4214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 4234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final ContentValues contentValues = getPrimaryContentValue(contentValuesList); 4264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME); 4274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME); 4284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME); 4294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String prefix = contentValues.getAsString(StructuredName.PREFIX); 4304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String suffix = contentValues.getAsString(StructuredName.SUFFIX); 4314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME); 4324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(familyName) || !TextUtils.isEmpty(givenName)) { 4344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyAppendCharsetParameterToName = 4354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa shouldAppendCharsetParam(familyName, givenName, middleName, prefix, suffix); 4364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintableToName = 4374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (!mRefrainsQPToNameProperties && 4384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !(VCardUtils.containsOnlyNonCrLfPrintableAscii(familyName) && 4394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardUtils.containsOnlyNonCrLfPrintableAscii(givenName) && 4404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardUtils.containsOnlyNonCrLfPrintableAscii(middleName) && 4414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardUtils.containsOnlyNonCrLfPrintableAscii(prefix) && 4424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardUtils.containsOnlyNonCrLfPrintableAscii(suffix))); 4434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String formattedName; 4454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(displayName)) { 4464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa formattedName = displayName; 4474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 4484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa formattedName = VCardUtils.constructNameFromElements( 4494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardConfig.getNameOrderType(mVCardType), 4504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa familyName, middleName, givenName, prefix, suffix); 4514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyAppendCharsetParameterToFN = 4534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa shouldAppendCharsetParam(formattedName); 4544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintableToFN = 4554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !mRefrainsQPToNameProperties && 4564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(formattedName); 4574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedFamily; 4594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedGiven; 4604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedMiddle; 4614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPrefix; 4624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedSuffix; 4634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintableToName) { 4644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedFamily = encodeQuotedPrintable(familyName); 4654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedGiven = encodeQuotedPrintable(givenName); 4664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedMiddle = encodeQuotedPrintable(middleName); 4674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPrefix = encodeQuotedPrintable(prefix); 4684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedSuffix = encodeQuotedPrintable(suffix); 4694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 4704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedFamily = escapeCharacters(familyName); 4714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedGiven = escapeCharacters(givenName); 4724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedMiddle = escapeCharacters(middleName); 4734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPrefix = escapeCharacters(prefix); 4744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedSuffix = escapeCharacters(suffix); 4754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedFormattedname = 4784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (reallyUseQuotedPrintableToFN ? 4794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodeQuotedPrintable(formattedName) : escapeCharacters(formattedName)); 4804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_N); 4824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 4834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyAppendCharsetParameterToName) { 4844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 4854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 4864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintableToName) { 4884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 4894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 4904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 4924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // DoCoMo phones require that all the elements in the "family name" field. 4934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(formattedName); 4944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 4954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 4964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 4974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 4984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 4994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyAppendCharsetParameterToName) { 5004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 5014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 5024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintableToName) { 5044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 5054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 5064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 5084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedFamily); 5094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedGiven); 5114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedMiddle); 5134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPrefix); 5154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedSuffix); 5174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 5194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // FN property 5214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_FN); 5224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyAppendCharsetParameterToFN) { 5234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 5244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 5254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintableToFN) { 5274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 5284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 5294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 5314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedFormattedname); 5324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 5334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (!TextUtils.isEmpty(displayName)) { 5344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintableToDisplayName = 5354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (!mRefrainsQPToNameProperties && 5364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(displayName)); 5374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedDisplayName = 5384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa reallyUseQuotedPrintableToDisplayName ? 5394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodeQuotedPrintable(displayName) : 5404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa escapeCharacters(displayName); 5414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5423d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // N 5434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_N); 5444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(displayName)) { 5454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 5464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 5474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintableToDisplayName) { 5494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 5504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 5514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 5534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedDisplayName); 5544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 5593d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa 5603d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // FN 5614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_FN); 5624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Note: "CHARSET" param is not allowed in vCard 3.0, but we may add it 5644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // when it would be useful or necessary for external importers, 5654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // assuming the external importer allows this vioration of the spec. 5664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(displayName)) { 5674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 5684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 5694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 5714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedDisplayName); 5724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 5733d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa } else if (VCardConfig.isVersion30(mVCardType)) { 5744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_N, ""); 5754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_FN, ""); 5764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (mIsDoCoMo) { 5774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_N, ""); 5784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPhoneticNameFields(contentValues); 5814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 5824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5843d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa /** 5853d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa * Emits SOUND;IRMC, SORT-STRING, and de-fact values for phonetic names like X-PHONETIC-FAMILY. 5863d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa */ 5874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendPhoneticNameFields(final ContentValues contentValues) { 5884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticFamilyName; 5894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticMiddleName; 5904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticGivenName; 5914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa { 5924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String tmpPhoneticFamilyName = 5934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME); 5944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String tmpPhoneticMiddleName = 5954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME); 5964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String tmpPhoneticGivenName = 5974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME); 5984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mNeedsToConvertPhoneticString) { 5994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticFamilyName = VCardUtils.toHalfWidthString(tmpPhoneticFamilyName); 6004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticMiddleName = VCardUtils.toHalfWidthString(tmpPhoneticMiddleName); 6014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticGivenName = VCardUtils.toHalfWidthString(tmpPhoneticGivenName); 6024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 6034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticFamilyName = tmpPhoneticFamilyName; 6044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticMiddleName = tmpPhoneticMiddleName; 6054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticGivenName = tmpPhoneticGivenName; 6064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(phoneticFamilyName) 6104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && TextUtils.isEmpty(phoneticMiddleName) 6114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && TextUtils.isEmpty(phoneticGivenName)) { 6124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 6134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_SOUND); 6144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 6154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PARAM_TYPE_X_IRMC_N); 6164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 6174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 6184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 6194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 6204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 6214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 6224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return; 6244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6263d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa if (VCardConfig.isVersion40(mVCardType)) { 6273d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa // We don't want SORT-STRING anyway. 6283d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa } else if (VCardConfig.isVersion30(mVCardType)) { 62936ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa final String sortString = 63036ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa VCardUtils.constructNameFromElements(mVCardType, 6314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticFamilyName, phoneticMiddleName, phoneticGivenName); 6324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_SORT_STRING); 63336ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa if (VCardConfig.isVersion30(mVCardType) && shouldAppendCharsetParam(sortString)) { 63436ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa // vCard 3.0 does not force us to use UTF-8 and actually we see some 63536ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa // programs which emit this value. It is incorrect from the view of 63636ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa // specification, but actually necessary for parsing vCard with non-UTF-8 63736ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa // charsets, expecting other parsers not get confused with this value. 6384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 6394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 6404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 6424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(escapeCharacters(sortString)); 6434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 6444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (mIsJapaneseMobilePhone) { 6454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Note: There is no appropriate property for expressing 6464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // phonetic name (Yomigana in Japanese) in vCard 2.1, while there is in 6474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // vCard 3.0 (SORT-STRING). 6484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We use DoCoMo's way when the device is Japanese one since it is already 6494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // supported by a lot of Japanese mobile phones. 6504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // This is "X-" property, so any parser hopefully would not get 6514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // confused with this. 6524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 6534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Also, DoCoMo's specification requires vCard composer to use just the first 6544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // column. 6554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // i.e. 6564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // good: SOUND;X-IRMC-N:Miyakawa Daisuke;;;; 6574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // bad : SOUND;X-IRMC-N:Miyakawa;Daisuke;;; 6584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_SOUND); 6594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 6604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PARAM_TYPE_X_IRMC_N); 6614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean reallyUseQuotedPrintable = 6634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (!mRefrainsQPToNameProperties 6644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && !(VCardUtils.containsOnlyNonCrLfPrintableAscii( 6654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticFamilyName) 6664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && VCardUtils.containsOnlyNonCrLfPrintableAscii( 6674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticMiddleName) 6684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && VCardUtils.containsOnlyNonCrLfPrintableAscii( 6694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticGivenName))); 6704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticFamilyName; 6724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticMiddleName; 6734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticGivenName; 6744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 6754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName); 6764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName); 6774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName); 6784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 6794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName); 6804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName); 6814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticGivenName = escapeCharacters(phoneticGivenName); 6824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(encodedPhoneticFamilyName, 6854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticMiddleName, encodedPhoneticGivenName)) { 6864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 6874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 6884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 6904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa { 6914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean first = true; 6924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(encodedPhoneticFamilyName)) { 6934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticFamilyName); 6944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa first = false; 6954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(encodedPhoneticMiddleName)) { 6974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (first) { 6984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa first = false; 6994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 7004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(' '); 7014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticMiddleName); 7034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(encodedPhoneticGivenName)) { 7054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!first) { 7064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(' '); 7074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticGivenName); 7094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); // family;given 7124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); // given;middle 7134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); // middle;prefix 7144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); // prefix;suffix 7154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 7164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 7183d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa Log.d("@@@", "hoge"); 7194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mUsesDefactProperty) { 7204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(phoneticGivenName)) { 7214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 7224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 7234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName)); 7244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticGivenName; 7254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 7264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName); 7274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 7284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticGivenName = escapeCharacters(phoneticGivenName); 7294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_FIRST_NAME); 7314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(phoneticGivenName)) { 7324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 7334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 7344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 7364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 7374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 7384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 7404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticGivenName); 7414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 7424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } // if (!TextUtils.isEmpty(phoneticGivenName)) 7434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(phoneticMiddleName)) { 7444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 7454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 7464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName)); 7474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticMiddleName; 7484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 7494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName); 7504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 7514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName); 7524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_MIDDLE_NAME); 7544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(phoneticMiddleName)) { 7554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 7564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 7574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 7594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 7604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 7614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 7634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticMiddleName); 7644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 7654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } // if (!TextUtils.isEmpty(phoneticGivenName)) 7664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(phoneticFamilyName)) { 7674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 7684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 7694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName)); 7704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticFamilyName; 7714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 7724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName); 7734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 7744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName); 7754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_LAST_NAME); 7774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(phoneticFamilyName)) { 7784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 7794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 7804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 7824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 7834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 7844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 7864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticFamilyName); 7874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 7884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } // if (!TextUtils.isEmpty(phoneticFamilyName)) 7894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 7924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendNickNames(final List<ContentValues> contentValuesList) { 7934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean useAndroidProperty; 79436ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa if (mIsV30OrV40) { // These specifications have NICKNAME property. 7954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa useAndroidProperty = false; 7964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (mUsesAndroidProperty) { 7974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa useAndroidProperty = true; 7984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 7994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // There's no way to add this field. 8004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 8014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 8034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 8044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String nickname = contentValues.getAsString(Nickname.NAME); 8054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(nickname)) { 8064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 8074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (useAndroidProperty) { 8094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendAndroidSpecificProperty(Nickname.CONTENT_ITEM_TYPE, contentValues); 8104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 8114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_NICKNAME, nickname); 8124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 8164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendPhones(final List<ContentValues> contentValuesList) { 8194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean phoneLineExists = false; 8204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 8214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Set<String> phoneSet = new HashSet<String>(); 8224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 8234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer typeAsObject = contentValues.getAsInteger(Phone.TYPE); 8244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String label = contentValues.getAsString(Phone.LABEL); 8254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isPrimaryAsInteger = contentValues.getAsInteger(Phone.IS_PRIMARY); 8264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary = (isPrimaryAsInteger != null ? 8274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isPrimaryAsInteger > 0) : false); 8284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String phoneNumber = contentValues.getAsString(Phone.NUMBER); 8294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (phoneNumber != null) { 8304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneNumber = phoneNumber.trim(); 8314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(phoneNumber)) { 8334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 8344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // PAGER number needs unformatted "phone number". 8374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int type = (typeAsObject != null ? typeAsObject : DEFAULT_PHONE_TYPE); 8384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (type == Phone.TYPE_PAGER || 8394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardConfig.refrainPhoneNumberFormatting(mVCardType)) { 8404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneLineExists = true; 8414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!phoneSet.contains(phoneNumber)) { 8424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneSet.add(phoneNumber); 8434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTelLine(type, label, phoneNumber, isPrimary); 8444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 8464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> phoneNumberList = splitAndTrimPhoneNumbers(phoneNumber); 8474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (phoneNumberList.isEmpty()) { 8484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 8494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneLineExists = true; 8514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (String actualPhoneNumber : phoneNumberList) { 8524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!phoneSet.contains(actualPhoneNumber)) { 8534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int format = VCardUtils.getPhoneNumberFormat(mVCardType); 8544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String formattedPhoneNumber = 8554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa PhoneNumberUtils.formatNumber(actualPhoneNumber, format); 8564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneSet.add(actualPhoneNumber); 8574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTelLine(type, label, formattedPhoneNumber, isPrimary); 8584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } // for (String actualPhoneNumber : phoneNumberList) { 8604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!phoneLineExists && mIsDoCoMo) { 8654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTelLine(Phone.TYPE_HOME, "", "", false); 8664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 8694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 8724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 8734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Splits a given string expressing phone numbers into several strings, and remove 8744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * unnecessary characters inside them. The size of a returned list becomes 1 when 8754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * no split is needed. 8764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 8774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 8784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The given number "may" have several phone numbers when the contact entry is corrupted 8794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * because of its original source. 8804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * e.g. "111-222-3333 (Miami)\n444-555-6666 (Broward; 305-653-6796 (Miami)" 8814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 8824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 8834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * This kind of "phone numbers" will not be created with Android vCard implementation, 8844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * but we may encounter them if the source of the input data has already corrupted 8854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * implementation. 8864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 8874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 8884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * To handle this case, this method first splits its input into multiple parts 8894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * (e.g. "111-222-3333 (Miami)", "444-555-6666 (Broward", and 305653-6796 (Miami)") and 8904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * removes unnecessary strings like "(Miami)". 8914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 8924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 8934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Do not call this method when trimming is inappropriate for its receivers. 8944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 8954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 8964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private List<String> splitAndTrimPhoneNumbers(final String phoneNumber) { 8974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> phoneList = new ArrayList<String>(); 8984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa StringBuilder builder = new StringBuilder(); 9004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int length = phoneNumber.length(); 9014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (int i = 0; i < length; i++) { 9024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final char ch = phoneNumber.charAt(i); 9034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (Character.isDigit(ch) || ch == '+') { 9044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append(ch); 9054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if ((ch == ';' || ch == '\n') && builder.length() > 0) { 9064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneList.add(builder.toString()); 9074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder = new StringBuilder(); 9084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (builder.length() > 0) { 9114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneList.add(builder.toString()); 9124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return phoneList; 9154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendEmails(final List<ContentValues> contentValuesList) { 9184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean emailAddressExists = false; 9194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 9204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Set<String> addressSet = new HashSet<String>(); 9214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 9224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String emailAddress = contentValues.getAsString(Email.DATA); 9234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (emailAddress != null) { 9244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa emailAddress = emailAddress.trim(); 9254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(emailAddress)) { 9274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 9284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Integer typeAsObject = contentValues.getAsInteger(Email.TYPE); 9304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int type = (typeAsObject != null ? 9314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsObject : DEFAULT_EMAIL_TYPE); 9324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String label = contentValues.getAsString(Email.LABEL); 9334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Integer isPrimaryAsInteger = contentValues.getAsInteger(Email.IS_PRIMARY); 9344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary = (isPrimaryAsInteger != null ? 9354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isPrimaryAsInteger > 0) : false); 9364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa emailAddressExists = true; 9374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!addressSet.contains(emailAddress)) { 9384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressSet.add(emailAddress); 9394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendEmailLine(type, label, emailAddress, isPrimary); 9404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!emailAddressExists && mIsDoCoMo) { 9454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendEmailLine(Email.TYPE_HOME, "", "", false); 9464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 9494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendPostals(final List<ContentValues> contentValuesList) { 9524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList == null || contentValuesList.isEmpty()) { 9534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 9544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_ADR); 9554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 9564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PARAM_TYPE_HOME); 9574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 9584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 9594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 9614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 9624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPostalsForDoCoMo(contentValuesList); 9634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 9644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPostalsForGeneric(contentValuesList); 9654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 9694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final Map<Integer, Integer> sPostalTypePriorityMap; 9724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa static { 9744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sPostalTypePriorityMap = new HashMap<Integer, Integer>(); 9754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sPostalTypePriorityMap.put(StructuredPostal.TYPE_HOME, 0); 9764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sPostalTypePriorityMap.put(StructuredPostal.TYPE_WORK, 1); 9774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sPostalTypePriorityMap.put(StructuredPostal.TYPE_OTHER, 2); 9784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sPostalTypePriorityMap.put(StructuredPostal.TYPE_CUSTOM, 3); 9794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 9824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Tries to append just one line. If there's no appropriate address 9834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * information, append an empty line. 9844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 9854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendPostalsForDoCoMo(final List<ContentValues> contentValuesList) { 9864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int currentPriority = Integer.MAX_VALUE; 9874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int currentType = Integer.MAX_VALUE; 9884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ContentValues currentContentValues = null; 9894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final ContentValues contentValues : contentValuesList) { 9904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null) { 9914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 9924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE); 9944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer priorityAsInteger = sPostalTypePriorityMap.get(typeAsInteger); 9954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int priority = 9964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (priorityAsInteger != null ? priorityAsInteger : Integer.MAX_VALUE); 9974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (priority < currentPriority) { 9984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa currentPriority = priority; 9994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa currentType = typeAsInteger; 10004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa currentContentValues = contentValues; 10014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (priority == 0) { 10024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 10034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 10074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (currentContentValues == null) { 10084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "Should not come here. Must have at least one postal data."); 10094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return; 10104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 10124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String label = currentContentValues.getAsString(StructuredPostal.LABEL); 10134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPostalLine(currentType, label, currentContentValues, false, true); 10144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 10164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendPostalsForGeneric(final List<ContentValues> contentValuesList) { 10174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final ContentValues contentValues : contentValuesList) { 10184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null) { 10194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 10204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE); 10224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int type = (typeAsInteger != null ? 10234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsInteger : DEFAULT_POSTAL_TYPE); 10244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String label = contentValues.getAsString(StructuredPostal.LABEL); 10254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isPrimaryAsInteger = 10264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsInteger(StructuredPostal.IS_PRIMARY); 10274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary = (isPrimaryAsInteger != null ? 10284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isPrimaryAsInteger > 0) : false); 10294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPostalLine(type, label, contentValues, isPrimary, false); 10304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 10334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static class PostalStruct { 10344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable; 10354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean appendCharset; 10364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String addressData; 10374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public PostalStruct(final boolean reallyUseQuotedPrintable, 10384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean appendCharset, final String addressData) { 10394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this.reallyUseQuotedPrintable = reallyUseQuotedPrintable; 10404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this.appendCharset = appendCharset; 10414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this.addressData = addressData; 10424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 10454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 10464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return null when there's no information available to construct the data. 10474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 10484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private PostalStruct tryConstructPostalStruct(ContentValues contentValues) { 10494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // adr-value = 0*6(text-value ";") text-value 10504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // ; PO Box, Extended Address, Street, Locality, Region, Postal 10514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // ; Code, Country Name 10524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawPoBox = contentValues.getAsString(StructuredPostal.POBOX); 10534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawNeighborhood = contentValues.getAsString(StructuredPostal.NEIGHBORHOOD); 10544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawStreet = contentValues.getAsString(StructuredPostal.STREET); 10554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawLocality = contentValues.getAsString(StructuredPostal.CITY); 10564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawRegion = contentValues.getAsString(StructuredPostal.REGION); 10574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawPostalCode = contentValues.getAsString(StructuredPostal.POSTCODE); 10584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawCountry = contentValues.getAsString(StructuredPostal.COUNTRY); 10594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String[] rawAddressArray = new String[]{ 10604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawPoBox, rawNeighborhood, rawStreet, rawLocality, 10614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawRegion, rawPostalCode, rawCountry}; 10624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!VCardUtils.areAllEmpty(rawAddressArray)) { 10634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 10644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 10654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawAddressArray)); 10664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean appendCharset = 10674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(rawAddressArray); 10684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPoBox; 10694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedStreet; 10704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedLocality; 10714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedRegion; 10724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPostalCode; 10734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedCountry; 10744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedNeighborhood; 10754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 10764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawLocality2; 10774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // This looks inefficient since we encode rawLocality and rawNeighborhood twice, 10784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // but this is intentional. 10794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 10804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // QP encoding may add line feeds when needed and the result of 10814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // - encodeQuotedPrintable(rawLocality + " " + rawNeighborhood) 10824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // may be different from 10834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // - encodedLocality + " " + encodedNeighborhood. 10844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 10854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We use safer way. 10864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(rawLocality)) { 10874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(rawNeighborhood)) { 10884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawLocality2 = ""; 10894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 10904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawLocality2 = rawNeighborhood; 10914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 10934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(rawNeighborhood)) { 10944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawLocality2 = rawLocality; 10954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 10964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawLocality2 = rawLocality + " " + rawNeighborhood; 10974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 11004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPoBox = encodeQuotedPrintable(rawPoBox); 11014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedStreet = encodeQuotedPrintable(rawStreet); 11024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedLocality = encodeQuotedPrintable(rawLocality2); 11034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedRegion = encodeQuotedPrintable(rawRegion); 11044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPostalCode = encodeQuotedPrintable(rawPostalCode); 11054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedCountry = encodeQuotedPrintable(rawCountry); 11064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 11074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPoBox = escapeCharacters(rawPoBox); 11084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedStreet = escapeCharacters(rawStreet); 11094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedLocality = escapeCharacters(rawLocality2); 11104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedRegion = escapeCharacters(rawRegion); 11114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPostalCode = escapeCharacters(rawPostalCode); 11124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedCountry = escapeCharacters(rawCountry); 11134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedNeighborhood = escapeCharacters(rawNeighborhood); 11144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final StringBuilder addressBuilder = new StringBuilder(); 11164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedPoBox); 11174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // PO BOX ; Extended Address 11184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Extended Address : Street 11194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedStreet); 11204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Street : Locality 11214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedLocality); 11224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Locality : Region 11234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedRegion); 11244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Region : Postal Code 11254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedPostalCode); 11264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Postal Code : Country 11274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedCountry); 11284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return new PostalStruct( 11294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa reallyUseQuotedPrintable, appendCharset, addressBuilder.toString()); 11304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { // VCardUtils.areAllEmpty(rawAddressArray) == true 11314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Try to use FORMATTED_ADDRESS instead. 11324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawFormattedAddress = 11334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredPostal.FORMATTED_ADDRESS); 11344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(rawFormattedAddress)) { 11354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return null; 11364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 11384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 11394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawFormattedAddress)); 11404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean appendCharset = 11414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(rawFormattedAddress); 11424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedFormattedAddress; 11434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 11444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedFormattedAddress = encodeQuotedPrintable(rawFormattedAddress); 11454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 11464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedFormattedAddress = escapeCharacters(rawFormattedAddress); 11474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 11494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We use the second value ("Extended Address") just because Japanese mobile phones 11504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // do so. If the other importer expects the value be in the other field, some flag may 11514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // be needed. 11524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final StringBuilder addressBuilder = new StringBuilder(); 11534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // PO BOX ; Extended Address 11544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedFormattedAddress); 11554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Extended Address : Street 11564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Street : Locality 11574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Locality : Region 11584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Region : Postal Code 11594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Postal Code : Country 11604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return new PostalStruct( 11614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa reallyUseQuotedPrintable, appendCharset, addressBuilder.toString()); 11624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 11654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendIms(final List<ContentValues> contentValuesList) { 11664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 11674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 11684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer protocolAsObject = contentValues.getAsInteger(Im.PROTOCOL); 11694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (protocolAsObject == null) { 11704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 11714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String propertyName = VCardUtils.getPropertyNameForIm(protocolAsObject); 11734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (propertyName == null) { 11744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 11754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String data = contentValues.getAsString(Im.DATA); 11774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (data != null) { 11784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa data = data.trim(); 11794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(data)) { 11814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 11824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String typeAsString; 11844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa { 11854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer typeAsInteger = contentValues.getAsInteger(Im.TYPE); 11864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa switch (typeAsInteger != null ? typeAsInteger : Im.TYPE_OTHER) { 11874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Im.TYPE_HOME: { 11884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_HOME; 11894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 11904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Im.TYPE_WORK: { 11924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_WORK; 11934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 11944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Im.TYPE_CUSTOM: { 11964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String label = contentValues.getAsString(Im.LABEL); 11974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = (label != null ? "X-" + label : null); 11984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 11994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Im.TYPE_OTHER: // Ignore 12014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa default: { 12024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = null; 12034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 12044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 12084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> parameterList = new ArrayList<String>(); 12094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(typeAsString)) { 12104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(typeAsString); 12114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isPrimaryAsInteger = contentValues.getAsInteger(Im.IS_PRIMARY); 12134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary = (isPrimaryAsInteger != null ? 12144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isPrimaryAsInteger > 0) : false); 12154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary) { 12164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PREF); 12174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 12194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(propertyName, parameterList, data); 12204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 12234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 12254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendWebsites(final List<ContentValues> contentValuesList) { 12264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 12274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 12284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String website = contentValues.getAsString(Website.URL); 12294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (website != null) { 12304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa website = website.trim(); 12314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 12334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Note: vCard 3.0 does not allow any parameter addition toward "URL" 12344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // property, while there's no document in vCard 2.1. 12354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(website)) { 12364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_URL, website); 12374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 12414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 12434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendOrganizations(final List<ContentValues> contentValuesList) { 12444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 12454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 12464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String company = contentValues.getAsString(Organization.COMPANY); 12474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (company != null) { 12484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa company = company.trim(); 12494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String department = contentValues.getAsString(Organization.DEPARTMENT); 12514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (department != null) { 12524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa department = department.trim(); 12534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String title = contentValues.getAsString(Organization.TITLE); 12554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (title != null) { 12564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa title = title.trim(); 12574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 12594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa StringBuilder orgBuilder = new StringBuilder(); 12604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(company)) { 12614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa orgBuilder.append(company); 12624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(department)) { 12644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (orgBuilder.length() > 0) { 12654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa orgBuilder.append(';'); 12664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa orgBuilder.append(department); 12684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String orgline = orgBuilder.toString(); 12704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_ORG, orgline, 12714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(orgline), 12724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 12734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(orgline))); 12744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 12754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(title)) { 12764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_TITLE, title, 12774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(title), 12784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 12794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(title))); 12804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 12844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 12864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendPhotos(final List<ContentValues> contentValuesList) { 12874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 12884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 12894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null) { 12904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 12914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa byte[] data = contentValues.getAsByteArray(Photo.PHOTO); 12934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (data == null) { 12944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 12954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String photoType = VCardUtils.guessImageType(data); 12974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (photoType == null) { 12984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.d(LOG_TAG, "Unknown photo type. Ignored."); 12994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 13004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // TODO: check this works fine. 13024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String photoString = new String(Base64.encode(data, Base64.NO_WRAP)); 13034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(photoString)) { 13044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPhotoLine(photoString, photoType); 13054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 13094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 13114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendNotes(final List<ContentValues> contentValuesList) { 13124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 13134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mOnlyOneNoteFieldIsAvailable) { 13144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final StringBuilder noteBuilder = new StringBuilder(); 13154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean first = true; 13164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final ContentValues contentValues : contentValuesList) { 13174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String note = contentValues.getAsString(Note.NOTE); 13184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (note == null) { 13194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa note = ""; 13204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (note.length() > 0) { 13224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (first) { 13234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa first = false; 13244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 13254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa noteBuilder.append('\n'); 13264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa noteBuilder.append(note); 13284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String noteStr = noteBuilder.toString(); 13314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // This means we scan noteStr completely twice, which is redundant. 13324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // But for now, we assume this is not so time-consuming.. 13334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean shouldAppendCharsetInfo = 13344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(noteStr); 13354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 13364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 13374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr)); 13384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_NOTE, noteStr, 13394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa shouldAppendCharsetInfo, reallyUseQuotedPrintable); 13404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 13414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 13424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String noteStr = contentValues.getAsString(Note.NOTE); 13434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(noteStr)) { 13444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean shouldAppendCharsetInfo = 13454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(noteStr); 13464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 13474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 13484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr)); 13494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_NOTE, noteStr, 13504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa shouldAppendCharsetInfo, reallyUseQuotedPrintable); 13514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 13564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 13584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendEvents(final List<ContentValues> contentValuesList) { 13594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // There's possibility where a given object may have more than one birthday, which 13604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // is inappropriate. We just build one birthday. 13614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 13624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String primaryBirthday = null; 13634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String secondaryBirthday = null; 13644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final ContentValues contentValues : contentValuesList) { 13654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null) { 13664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 13674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer eventTypeAsInteger = contentValues.getAsInteger(Event.TYPE); 13694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int eventType; 13704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (eventTypeAsInteger != null) { 13714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa eventType = eventTypeAsInteger; 13724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 13734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa eventType = Event.TYPE_OTHER; 13744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (eventType == Event.TYPE_BIRTHDAY) { 13764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String birthdayCandidate = contentValues.getAsString(Event.START_DATE); 13774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (birthdayCandidate == null) { 13784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 13794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isSuperPrimaryAsInteger = 13814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsInteger(Event.IS_SUPER_PRIMARY); 13824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isSuperPrimary = (isSuperPrimaryAsInteger != null ? 13834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isSuperPrimaryAsInteger > 0) : false); 13844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isSuperPrimary) { 13854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // "super primary" birthday should the prefered one. 13864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryBirthday = birthdayCandidate; 13874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 13884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isPrimaryAsInteger = 13904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsInteger(Event.IS_PRIMARY); 13914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary = (isPrimaryAsInteger != null ? 13924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isPrimaryAsInteger > 0) : false); 13934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary) { 13944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We don't break here since "super primary" birthday may exist later. 13954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryBirthday = birthdayCandidate; 13964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (secondaryBirthday == null) { 13974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // First entry is set to the "secondary" candidate. 13984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa secondaryBirthday = birthdayCandidate; 13994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (mUsesAndroidProperty) { 14014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Event types other than Birthday is not supported by vCard. 14024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendAndroidSpecificProperty(Event.CONTENT_ITEM_TYPE, contentValues); 14034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (primaryBirthday != null) { 14064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_BDAY, 14074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryBirthday.trim()); 14084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (secondaryBirthday != null){ 14094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_BDAY, 14104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa secondaryBirthday.trim()); 14114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 14144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 14164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendRelation(final List<ContentValues> contentValuesList) { 14174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mUsesAndroidProperty && contentValuesList != null) { 14184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final ContentValues contentValues : contentValuesList) { 14194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null) { 14204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 14214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendAndroidSpecificProperty(Relation.CONTENT_ITEM_TYPE, contentValues); 14234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 14264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 14284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 14294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param emitEveryTime If true, builder builds the line even when there's no entry. 14304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 14314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendPostalLine(final int type, final String label, 14324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final ContentValues contentValues, 14334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary, final boolean emitEveryTime) { 14344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable; 14354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean appendCharset; 14364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String addressValue; 14374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa { 14384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa PostalStruct postalStruct = tryConstructPostalStruct(contentValues); 14394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (postalStruct == null) { 14404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (emitEveryTime) { 14414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa reallyUseQuotedPrintable = false; 14424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendCharset = false; 14434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressValue = ""; 14444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 14454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return; 14464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 14484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa reallyUseQuotedPrintable = postalStruct.reallyUseQuotedPrintable; 14494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendCharset = postalStruct.appendCharset; 14504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressValue = postalStruct.addressData; 14514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 14544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa List<String> parameterList = new ArrayList<String>(); 14554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary) { 14564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PREF); 14574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa switch (type) { 14594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case StructuredPostal.TYPE_HOME: { 14604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_HOME); 14614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case StructuredPostal.TYPE_WORK: { 14644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_WORK); 14654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case StructuredPostal.TYPE_CUSTOM: { 14684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(label) 14694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && VCardUtils.containsOnlyAlphaDigitHyphen(label)) { 14704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We're not sure whether the label is valid in the spec 14714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // ("IANA-token" in the vCard 3.0 is unclear...) 14724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Just for safety, we add "X-" at the beggining of each label. 14734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Also checks the label obeys with vCard 3.0 spec. 14744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add("X-" + label); 14754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case StructuredPostal.TYPE_OTHER: { 14794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa default: { 14824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "Unknown StructuredPostal type: " + type); 14834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 14874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_ADR); 14884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!parameterList.isEmpty()) { 14894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 14904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameters(parameterList); 14914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (appendCharset) { 14934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Strictly, vCard 3.0 does not allow exporters to emit charset information, 14944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // but we will add it since the information should be useful for importers, 14954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 14964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Assume no parser does not emit error with this parameter in vCard 3.0. 14974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 14984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 14994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 15014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 15024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 15034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 15054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(addressValue); 15064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 15074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 15094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendEmailLine(final int type, final String label, 15104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawValue, final boolean isPrimary) { 15114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String typeAsString; 15124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa switch (type) { 15134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Email.TYPE_CUSTOM: { 15144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (VCardUtils.isMobilePhoneLabel(label)) { 15154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_CELL; 15164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (!TextUtils.isEmpty(label) 15174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && VCardUtils.containsOnlyAlphaDigitHyphen(label)) { 15184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = "X-" + label; 15194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 15204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = null; 15214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Email.TYPE_HOME: { 15254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_HOME; 15264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Email.TYPE_WORK: { 15294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_WORK; 15304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Email.TYPE_OTHER: { 15334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = null; 15344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Email.TYPE_MOBILE: { 15374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_CELL; 15384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa default: { 15414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "Unknown Email type: " + type); 15424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = null; 15434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 15474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> parameterList = new ArrayList<String>(); 15484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary) { 15494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PREF); 15504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(typeAsString)) { 15524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(typeAsString); 15534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 15554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_EMAIL, parameterList, 15564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawValue); 15574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 15594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendTelLine(final Integer typeAsInteger, final String label, 15604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedValue, boolean isPrimary) { 15614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_TEL); 15624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 15634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 15644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int type; 15654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (typeAsInteger == null) { 15664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa type = Phone.TYPE_OTHER; 15674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 15684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa type = typeAsInteger; 15694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 15714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ArrayList<String> parameterList = new ArrayList<String>(); 15724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa switch (type) { 15734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_HOME: { 15744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.addAll( 15754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Arrays.asList(VCardConstants.PARAM_TYPE_HOME)); 15764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_WORK: { 15794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.addAll( 15804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Arrays.asList(VCardConstants.PARAM_TYPE_WORK)); 15814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_FAX_HOME: { 15844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.addAll( 15854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Arrays.asList(VCardConstants.PARAM_TYPE_HOME, VCardConstants.PARAM_TYPE_FAX)); 15864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_FAX_WORK: { 15894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.addAll( 15904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Arrays.asList(VCardConstants.PARAM_TYPE_WORK, VCardConstants.PARAM_TYPE_FAX)); 15914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_MOBILE: { 15944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_CELL); 15954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_PAGER: { 15984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 15994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Not sure about the reason, but previous implementation had 16004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // used "VOICE" instead of "PAGER" 16014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_VOICE); 16024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 16034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PAGER); 16044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_OTHER: { 16084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_VOICE); 16094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_CAR: { 16124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_CAR); 16134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_COMPANY_MAIN: { 16164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // There's no relevant field in vCard (at least 2.1). 16174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_WORK); 16184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa isPrimary = true; 16194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_ISDN: { 16224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_ISDN); 16234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_MAIN: { 16264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa isPrimary = true; 16274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_OTHER_FAX: { 16304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_FAX); 16314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_TELEX: { 16344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_TLX); 16354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_WORK_MOBILE: { 16384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.addAll( 16394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Arrays.asList(VCardConstants.PARAM_TYPE_WORK, VCardConstants.PARAM_TYPE_CELL)); 16404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_WORK_PAGER: { 16434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_WORK); 16444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // See above. 16454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 16464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_VOICE); 16474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 16484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PAGER); 16494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_MMS: { 16534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_MSG); 16544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_CUSTOM: { 16574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(label)) { 16584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Just ignore the custom type. 16594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_VOICE); 16604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (VCardUtils.isMobilePhoneLabel(label)) { 16614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_CELL); 166236ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa } else if (mIsV30OrV40) { 16632bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // This label is appropriately encoded in appendTypeParameters. 16642bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa parameterList.add(label); 16654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 16664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String upperLabel = label.toUpperCase(); 16674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (VCardUtils.isValidInV21ButUnknownToContactsPhoteType(upperLabel)) { 16684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(upperLabel); 16694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (VCardUtils.containsOnlyAlphaDigitHyphen(label)) { 16704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Note: Strictly, vCard 2.1 does not allow "X-" parameter without 16714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // "TYPE=" string. 16724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add("X-" + label); 16734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_RADIO: 16784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_TTY_TDD: 16794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa default: { 16804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 16814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 16844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary) { 16854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PREF); 16864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 16884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (parameterList.isEmpty()) { 16894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendUncommonPhoneType(mBuilder, type); 16904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 16914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameters(parameterList); 16924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 16944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 16954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedValue); 16964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 16974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 16994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 17004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Appends phone type string which may not be available in some devices. 17014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 17024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendUncommonPhoneType(final StringBuilder builder, final Integer type) { 17034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 17044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // The previous implementation for DoCoMo had been conservative 17054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // about miscellaneous types. 17064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append(VCardConstants.PARAM_TYPE_VOICE); 17074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 17084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String phoneType = VCardUtils.getPhoneTypeString(type); 17094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (phoneType != null) { 17104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameter(phoneType); 17114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 17124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "Unknown or unsupported (by vCard) Phone type: " + type); 17134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 17184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param encodedValue Must be encoded by BASE64 17194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param photoType 17204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 17214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendPhotoLine(final String encodedValue, final String photoType) { 17224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa StringBuilder tmpBuilder = new StringBuilder(); 17234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCardConstants.PROPERTY_PHOTO); 17244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_PARAM_SEPARATOR); 172536ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa if (mIsV30OrV40) { 172636ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa tmpBuilder.append(VCARD_PARAM_ENCODING_BASE64_AS_B); 17274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 17284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_PARAM_ENCODING_BASE64_V21); 17294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_PARAM_SEPARATOR); 17314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameter(tmpBuilder, photoType); 17324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_DATA_SEPARATOR); 17334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(encodedValue); 17344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String tmpStr = tmpBuilder.toString(); 17364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder = new StringBuilder(); 17374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int lineCount = 0; 17384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int length = tmpStr.length(); 17394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int maxNumForFirstLine = VCardConstants.MAX_CHARACTER_NUMS_BASE64_V30 17404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa - VCARD_END_OF_LINE.length(); 17414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int maxNumInGeneral = maxNumForFirstLine - VCARD_WS.length(); 17424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int maxNum = maxNumForFirstLine; 17434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (int i = 0; i < length; i++) { 17444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(tmpStr.charAt(i)); 17454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa lineCount++; 17464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (lineCount > maxNum) { 17474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_END_OF_LINE); 17484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_WS); 17494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa maxNum = maxNumInGeneral; 17504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa lineCount = 0; 17514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(tmpBuilder.toString()); 17544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 17554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 17564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendAndroidSpecificProperty( 17594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String mimeType, ContentValues contentValues) { 17604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!sAllowedAndroidPropertySet.contains(mimeType)) { 17614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return; 17624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> rawValueList = new ArrayList<String>(); 17644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (int i = 1; i <= VCardConstants.MAX_DATA_COLUMN; i++) { 17654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String value = contentValues.getAsString("data" + i); 17664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (value == null) { 17674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa value = ""; 17684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawValueList.add(value); 17704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean needCharset = 17734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldAppendCharsetParam && 17744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); 17754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean reallyUseQuotedPrintable = 17764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 17774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); 17784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_X_ANDROID_CUSTOM); 17794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (needCharset) { 17804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 17814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 17824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 17844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 17854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 17864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 17884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mimeType); // Should not be encoded. 17894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (String rawValue : rawValueList) { 17904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedValue; 17914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 17924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = encodeQuotedPrintable(rawValue); 17934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 17944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // TODO: one line may be too huge, which may be invalid in vCard 3.0 17954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // (which says "When generating a content line, lines longer than 17964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 75 characters SHOULD be folded"), though several 17974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // (even well-known) applications do not care this. 17984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = escapeCharacters(rawValue); 17994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 18014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedValue); 18024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 18044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLineWithCharsetAndQPDetection(final String propertyName, 18074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawValue) { 18084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(propertyName, null, rawValue); 18094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLineWithCharsetAndQPDetection( 18124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String propertyName, final List<String> rawValueList) { 18134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(propertyName, null, rawValueList); 18144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLineWithCharsetAndQPDetection(final String propertyName, 18174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> parameterList, final String rawValue) { 18184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean needCharset = 18194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(rawValue); 18204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 18214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 18224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValue)); 18234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, parameterList, 18244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawValue, needCharset, reallyUseQuotedPrintable); 18254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLineWithCharsetAndQPDetection(final String propertyName, 18284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> parameterList, final List<String> rawValueList) { 18294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean needCharset = 18304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldAppendCharsetParam && 18314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); 18324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean reallyUseQuotedPrintable = 18334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 18344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); 18354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, parameterList, rawValueList, 18364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa needCharset, reallyUseQuotedPrintable); 18374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 18404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Appends one line with a given property name and value. 18414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 18424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final String rawValue) { 18434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, rawValue, false, false); 18444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final List<String> rawValueList) { 18474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, rawValueList, false, false); 18484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, 18514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawValue, final boolean needCharset, 18524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean reallyUseQuotedPrintable) { 18534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, null, rawValue, needCharset, reallyUseQuotedPrintable); 18544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final List<String> parameterList, 18574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawValue) { 18584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, parameterList, rawValue, false, false); 18594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final List<String> parameterList, 18624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawValue, final boolean needCharset, 18634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean reallyUseQuotedPrintable) { 18644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(propertyName); 18654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (parameterList != null && parameterList.size() > 0) { 18664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 18674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameters(parameterList); 18684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (needCharset) { 18704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 18714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 18724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedValue; 18754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 18764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 18774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 18784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = encodeQuotedPrintable(rawValue); 18794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 18804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // TODO: one line may be too huge, which may be invalid in vCard spec, though 18814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // several (even well-known) applications do not care that violation. 18824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = escapeCharacters(rawValue); 18834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 18864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedValue); 18874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 18884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final List<String> rawValueList, 18914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean needCharset, boolean needQuotedPrintable) { 18924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, null, rawValueList, needCharset, needQuotedPrintable); 18934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final List<String> parameterList, 18964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> rawValueList, final boolean needCharset, 18974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean needQuotedPrintable) { 18984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(propertyName); 18994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (parameterList != null && parameterList.size() > 0) { 19004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 19014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameters(parameterList); 19024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (needCharset) { 19044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 19054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 19064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (needQuotedPrintable) { 19084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 19094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 19104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 19134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean first = true; 19144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (String rawValue : rawValueList) { 19154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedValue; 19164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (needQuotedPrintable) { 19174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = encodeQuotedPrintable(rawValue); 19184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 19194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // TODO: one line may be too huge, which may be invalid in vCard 3.0 19204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // (which says "When generating a content line, lines longer than 19214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 75 characters SHOULD be folded"), though several 19224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // (even well-known) applications do not care this. 19234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = escapeCharacters(rawValue); 19244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (first) { 19274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa first = false; 19284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 19294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 19304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedValue); 19324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 19344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 19374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * VCARD_PARAM_SEPARATOR must be appended before this method being called. 19384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 19394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendTypeParameters(final List<String> types) { 19404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We may have to make this comma separated form like "TYPE=DOM,WORK" in the future, 19414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // which would be recommended way in vcard 3.0 though not valid in vCard 2.1. 19424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean first = true; 19434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final String typeValue : types) { 19442bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa if (VCardConfig.isVersion30(mVCardType)) { 19453d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa final String encoded = VCardUtils.toStringAsV30ParamValue(typeValue); 19462bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa if (TextUtils.isEmpty(encoded)) { 19472bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa continue; 19482bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } 19492bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa 19502bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // Note: vCard 3.0 specifies the different type of acceptable type Strings, but 19512bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // we don't emit that kind of vCard 3.0 specific type since there should be 19522bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // high probabilyty in which external importers cannot understand them. 19532bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // 19542bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // e.g. TYPE="\u578B\u306B\u3087" (vCard 3.0 allows non-Ascii characters if they 19552bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // are quoted.) 19562bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa if (first) { 19572bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa first = false; 19582bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } else { 19592bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 19602bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } 19612bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa appendTypeParameter(encoded); 19622bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } else { // vCard 2.1 19632bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa if (!VCardUtils.isV21Word(typeValue)) { 19642bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa continue; 19652bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } 19662bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa if (first) { 19672bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa first = false; 19682bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } else { 19692bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 19702bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } 19712bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa appendTypeParameter(typeValue); 19724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 19774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * VCARD_PARAM_SEPARATOR must be appended before this method being called. 19784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 19794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendTypeParameter(final String type) { 19804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameter(mBuilder, type); 19814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendTypeParameter(final StringBuilder builder, final String type) { 19844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Refrain from using appendType() so that "TYPE=" is not be appended when the 19854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // device is DoCoMo's (just for safety). 19864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 19874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Note: In vCard 3.0, Type strings also can be like this: "TYPE=HOME,PREF" 198836ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa if (VCardConfig.isVersion40(mVCardType) || 198936ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa ((VCardConfig.isVersion30(mVCardType) || mAppendTypeParamName) && !mIsDoCoMo)) { 19904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append(VCardConstants.PARAM_TYPE).append(VCARD_PARAM_EQUAL); 19914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append(type); 19934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 19964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Returns true when the property line should contain charset parameter 19974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * information. This method may return true even when vCard version is 3.0. 19984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 19994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Strictly, adding charset information is invalid in VCard 3.0. 20004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * However we'll add the info only when charset we use is not UTF-8 20014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * in vCard 3.0 format, since parser side may be able to use the charset 20024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * via this field, though we may encounter another problem by adding it. 20034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 20044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * e.g. Japanese mobile phones use Shift_Jis while RFC 2426 20054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * recommends UTF-8. By adding this field, parsers may be able 20064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * to know this text is NOT UTF-8 but Shift_Jis. 20074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 20084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private boolean shouldAppendCharsetParam(String...propertyValueList) { 20094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!mShouldAppendCharsetParam) { 20104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 20114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (String propertyValue : propertyValueList) { 20134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!VCardUtils.containsOnlyPrintableAscii(propertyValue)) { 20144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return true; 20154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 20184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 20204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private String encodeQuotedPrintable(final String str) { 20214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(str)) { 20224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 20234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 20254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final StringBuilder builder = new StringBuilder(); 20264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int index = 0; 20274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int lineCount = 0; 20284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa byte[] strArray = null; 20294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 20304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 20314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa strArray = str.getBytes(mCharset); 20324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedEncodingException e) { 20334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "Charset " + mCharset + " cannot be used. " 20344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Try default charset"); 20354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa strArray = str.getBytes(); 20364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa while (index < strArray.length) { 20384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append(String.format("=%02X", strArray[index])); 20394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa index += 1; 20404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa lineCount += 3; 20414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 20424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (lineCount >= 67) { 20434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Specification requires CRLF must be inserted before the 20444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // length of the line 20454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // becomes more than 76. 20464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Assuming that the next character is a multi-byte character, 20474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // it will become 20484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 6 bytes. 20494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 76 - 6 - 3 = 67 20504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append("=\r\n"); 20514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa lineCount = 0; 20524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 20554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return builder.toString(); 20564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 20584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 20594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Append '\' to the characters which should be escaped. The character set is different 20604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * not only between vCard 2.1 and vCard 3.0 but also among each device. 20614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 20624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Note that Quoted-Printable string must not be input here. 20634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 20644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa @SuppressWarnings("fallthrough") 20654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private String escapeCharacters(final String unescaped) { 20664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(unescaped)) { 20674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 20684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 20704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final StringBuilder tmpBuilder = new StringBuilder(); 20714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int length = unescaped.length(); 20724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (int i = 0; i < length; i++) { 20734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final char ch = unescaped.charAt(i); 20744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa switch (ch) { 20754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case ';': { 20764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append('\\'); 20774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(';'); 20784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 20794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case '\r': { 20814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (i + 1 < length) { 20824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa char nextChar = unescaped.charAt(i); 20834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (nextChar == '\n') { 20844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 20854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 20864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // fall through 20874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 20894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // fall through 20904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case '\n': { 20934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // In vCard 2.1, there's no specification about this, while 20944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // vCard 3.0 explicitly requires this should be encoded to "\n". 20954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append("\\n"); 20964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 20974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case '\\': { 209936ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa if (mIsV30OrV40) { 21004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append("\\\\"); 21014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 21024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 21034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // fall through 21044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case '<': 21074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case '>': { 21084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 21094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append('\\'); 21104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(ch); 21114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 21124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(ch); 21134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 21154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case ',': { 211736ba003879c5583609af3afcec8df22f51d94cd3Daisuke Miyakawa if (mIsV30OrV40) { 21184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append("\\,"); 21194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 21204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(ch); 21214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 21234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa default: { 21254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(ch); 21264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 21274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return tmpBuilder.toString(); 21314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 21334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa @Override 21344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public String toString() { 21354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!mEndAppended) { 21364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 21374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_X_CLASS, VCARD_DATA_PUBLIC); 21384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_X_REDUCTION, ""); 21394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_X_NO, ""); 21404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_X_DCM_HMN_MODE, ""); 21414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_END, VCARD_DATA_VCARD); 21434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mEndAppended = true; 21444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mBuilder.toString(); 21464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 21474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa} 2148