VCardBuilder.java revision 2bf85a1a15a3175119ab8415fc590fd5fe3d0752
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 184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentValues; 194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Email; 204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Event; 214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Im; 224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Nickname; 234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Note; 244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Organization; 254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Phone; 264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Photo; 274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Relation; 284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Website; 314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.telephony.PhoneNumberUtils; 324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.text.TextUtils; 334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Base64; 344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.CharsetUtils; 354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Log; 364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.UnsupportedEncodingException; 384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.nio.charset.UnsupportedCharsetException; 394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList; 404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Arrays; 414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Collections; 424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.HashMap; 434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.HashSet; 444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.List; 454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Map; 464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Set; 474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/** 494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The class which lets users create their own vCard String. Typical usage is as follows: 514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <pre class="prettyprint">final VCardBuilder builder = new VCardBuilder(vcardType); 534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE)) 544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE)) 554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE)) 564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE)) 574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE)) 584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE)) 594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE)) 604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE)) 614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE)) 624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE)) 634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE)) 644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE)); 654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * return builder.toString();</pre> 664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapublic class VCardBuilder { 684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String LOG_TAG = "VCardBuilder"; 694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // If you add the other element, please check all the columns are able to be 714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // converted to String. 724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // e.g. BLOB is not what we can handle here now. 744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final Set<String> sAllowedAndroidPropertySet = 754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Collections.unmodifiableSet(new HashSet<String>(Arrays.asList( 764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Nickname.CONTENT_ITEM_TYPE, Event.CONTENT_ITEM_TYPE, 774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Relation.CONTENT_ITEM_TYPE))); 784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final int DEFAULT_PHONE_TYPE = Phone.TYPE_HOME; 804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final int DEFAULT_POSTAL_TYPE = StructuredPostal.TYPE_HOME; 814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final int DEFAULT_EMAIL_TYPE = Email.TYPE_OTHER; 824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_DATA_VCARD = "VCARD"; 844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_DATA_PUBLIC = "PUBLIC"; 854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_PARAM_SEPARATOR = ";"; 874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_END_OF_LINE = "\r\n"; 884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_DATA_SEPARATOR = ":"; 894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_ITEM_SEPARATOR = ";"; 904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_WS = " "; 914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_PARAM_EQUAL = "="; 924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_PARAM_ENCODING_QP = 944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "ENCODING=" + VCardConstants.PARAM_ENCODING_QP; 954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_PARAM_ENCODING_BASE64_V21 = 964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "ENCODING=" + VCardConstants.PARAM_ENCODING_BASE64; 974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String VCARD_PARAM_ENCODING_BASE64_V30 = 984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "ENCODING=" + VCardConstants.PARAM_ENCODING_B; 994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String SHIFT_JIS = "SHIFT_JIS"; 1014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final int mVCardType; 1034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mIsV30; 1054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mIsJapaneseMobilePhone; 1064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mOnlyOneNoteFieldIsAvailable; 1074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mIsDoCoMo; 1084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mShouldUseQuotedPrintable; 1094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mUsesAndroidProperty; 1104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mUsesDefactProperty; 1114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mAppendTypeParamName; 1124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mRefrainsQPToNameProperties; 1134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mNeedsToConvertPhoneticString; 1144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mShouldAppendCharsetParam; 1164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final String mCharset; 1184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final String mVCardCharsetParameter; 1194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private StringBuilder mBuilder; 1214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private boolean mEndAppended; 1224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder(final int vcardType) { 1244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Default charset should be used 1254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(vcardType, null); 1264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param vcardType 1304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param charset If null, we use default charset for export. 1314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder(final int vcardType, String charset) { 1334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mVCardType = vcardType; 1344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 13576a4a3b4d2c3bf1d8c8618a8b353b5fc3c3a27abDaisuke Miyakawa // We don't allow currrent Android devices to build vCard files with version 4.0 13676a4a3b4d2c3bf1d8c8618a8b353b5fc3c3a27abDaisuke Miyakawa // while We allow them to parse/import them, as vCard 4.0 is not yet released 13776a4a3b4d2c3bf1d8c8618a8b353b5fc3c3a27abDaisuke Miyakawa // as formal specification. 13876a4a3b4d2c3bf1d8c8618a8b353b5fc3c3a27abDaisuke Miyakawa if (VCardConfig.isVersion40(vcardType)) { 13976a4a3b4d2c3bf1d8c8618a8b353b5fc3c3a27abDaisuke Miyakawa // We don't use VCardException since this exception should not be a part of 14076a4a3b4d2c3bf1d8c8618a8b353b5fc3c3a27abDaisuke Miyakawa // public API. 14176a4a3b4d2c3bf1d8c8618a8b353b5fc3c3a27abDaisuke Miyakawa throw new RuntimeException("Must not use vCard 4.0 when building vCard, because " + 14276a4a3b4d2c3bf1d8c8618a8b353b5fc3c3a27abDaisuke Miyakawa "it is not officially released."); 14376a4a3b4d2c3bf1d8c8618a8b353b5fc3c3a27abDaisuke Miyakawa } 144be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa mIsV30 = VCardConfig.isVersion30(vcardType); 1454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mShouldUseQuotedPrintable = VCardConfig.shouldUseQuotedPrintable(vcardType); 1464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); 1474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mIsJapaneseMobilePhone = VCardConfig.needsToConvertPhoneticString(vcardType); 1484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mOnlyOneNoteFieldIsAvailable = VCardConfig.onlyOneNoteFieldIsAvailable(vcardType); 1494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mUsesAndroidProperty = VCardConfig.usesAndroidSpecificProperty(vcardType); 1504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mUsesDefactProperty = VCardConfig.usesDefactProperty(vcardType); 1514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mRefrainsQPToNameProperties = VCardConfig.shouldRefrainQPToNameProperties(vcardType); 1524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mAppendTypeParamName = VCardConfig.appendTypeParamName(vcardType); 1534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mNeedsToConvertPhoneticString = VCardConfig.needsToConvertPhoneticString(vcardType); 1544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // vCard 2.1 requires charset. 1564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // vCard 3.0 does not allow it but we found some devices use it to determine 1574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // the exact charset. 1584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We currently append it only when charset other than UTF_8 is used. 1594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mShouldAppendCharsetParam = !(mIsV30 && "UTF-8".equalsIgnoreCase(charset)); 1604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (VCardConfig.isDoCoMo(vcardType)) { 1624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!SHIFT_JIS.equalsIgnoreCase(charset)) { 1634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, 1644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "The charset \"" + charset + "\" is used while " 1654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + SHIFT_JIS + " is needed to be used."); 1664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(charset)) { 1674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = SHIFT_JIS; 1684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 1694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 1704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(charset).name(); 1714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 1724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.i(LOG_TAG, 1734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Career-specific \"" + charset + "\" was not found (as usual). " 1744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use it as is."); 1754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 1774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 1794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 1804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 1814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); 1824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 1834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, 1844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "DoCoMo-specific SHIFT_JIS was not found. " 1854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use SHIFT_JIS as is."); 1864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = SHIFT_JIS; 1874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 1894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 1904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); 1914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 1924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, 1934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Career-specific SHIFT_JIS was not found. " 1944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use SHIFT_JIS as is."); 1954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = SHIFT_JIS; 1964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 1994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mVCardCharsetParameter = "CHARSET=" + SHIFT_JIS; 2014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(charset)) { 2034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.i(LOG_TAG, 2044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Use the charset \"" + VCardConfig.DEFAULT_EXPORT_CHARSET 2054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "\" for export."); 2064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = VCardConfig.DEFAULT_EXPORT_CHARSET; 2074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mVCardCharsetParameter = "CHARSET=" + VCardConfig.DEFAULT_EXPORT_CHARSET; 2084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 2104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(charset).name(); 2114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 2124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.i(LOG_TAG, 2134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Career-specific \"" + charset + "\" was not found (as usual). " 2144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use it as is."); 2154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 2174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mVCardCharsetParameter = "CHARSET=" + charset; 2184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa clear(); 2214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void clear() { 2244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder = new StringBuilder(); 2254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mEndAppended = false; 2264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_BEGIN, VCARD_DATA_VCARD); 2274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsV30) { 2284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V30); 2294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V21); 2314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private boolean containsNonEmptyName(final ContentValues contentValues) { 2354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME); 2364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME); 2374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME); 2384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String prefix = contentValues.getAsString(StructuredName.PREFIX); 2394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String suffix = contentValues.getAsString(StructuredName.SUFFIX); 2404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticFamilyName = 2414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME); 2424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticMiddleName = 2434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME); 2444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticGivenName = 2454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME); 2464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME); 2474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return !(TextUtils.isEmpty(familyName) && TextUtils.isEmpty(middleName) && 2484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa TextUtils.isEmpty(givenName) && TextUtils.isEmpty(prefix) && 2494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa TextUtils.isEmpty(suffix) && TextUtils.isEmpty(phoneticFamilyName) && 2504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa TextUtils.isEmpty(phoneticMiddleName) && TextUtils.isEmpty(phoneticGivenName) && 2514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa TextUtils.isEmpty(displayName)); 2524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private ContentValues getPrimaryContentValue(final List<ContentValues> contentValuesList) { 2554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ContentValues primaryContentValues = null; 2564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ContentValues subprimaryContentValues = null; 2574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 2584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null){ 2594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 2604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Integer isSuperPrimary = contentValues.getAsInteger(StructuredName.IS_SUPER_PRIMARY); 2624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isSuperPrimary != null && isSuperPrimary > 0) { 2634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We choose "super primary" ContentValues. 2644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryContentValues = contentValues; 2654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 2664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (primaryContentValues == null) { 2674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We choose the first "primary" ContentValues 2684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // if "super primary" ContentValues does not exist. 2694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isPrimary = contentValues.getAsInteger(StructuredName.IS_PRIMARY); 2704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary != null && isPrimary > 0 && 2714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa containsNonEmptyName(contentValues)) { 2724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryContentValues = contentValues; 2734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Do not break, since there may be ContentValues with "super primary" 2744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // afterword. 2754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (subprimaryContentValues == null && 2764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa containsNonEmptyName(contentValues)) { 2774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa subprimaryContentValues = contentValues; 2784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (primaryContentValues == null) { 2834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (subprimaryContentValues != null) { 2844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We choose the first ContentValues if any "primary" ContentValues does not exist. 2854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryContentValues = subprimaryContentValues; 2864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "All ContentValues given from database is empty."); 2884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryContentValues = new ContentValues(); 2894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return primaryContentValues; 2934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 2964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * For safety, we'll emit just one value around StructuredName, as external importers 2974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * may get confused with multiple "N", "FN", etc. properties, though it is valid in 2984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * vCard spec. 2994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 3004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendNameProperties(final List<ContentValues> contentValuesList) { 3014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList == null || contentValuesList.isEmpty()) { 3024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 3034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_N, ""); 3044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (mIsV30) { 3054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // vCard 3.0 requires "N" and "FN" properties. 3064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_N, ""); 3074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_FN, ""); 3084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 3104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final ContentValues contentValues = getPrimaryContentValue(contentValuesList); 3134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME); 3144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME); 3154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME); 3164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String prefix = contentValues.getAsString(StructuredName.PREFIX); 3174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String suffix = contentValues.getAsString(StructuredName.SUFFIX); 3184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME); 3194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(familyName) || !TextUtils.isEmpty(givenName)) { 3214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyAppendCharsetParameterToName = 3224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa shouldAppendCharsetParam(familyName, givenName, middleName, prefix, suffix); 3234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintableToName = 3244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (!mRefrainsQPToNameProperties && 3254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !(VCardUtils.containsOnlyNonCrLfPrintableAscii(familyName) && 3264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardUtils.containsOnlyNonCrLfPrintableAscii(givenName) && 3274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardUtils.containsOnlyNonCrLfPrintableAscii(middleName) && 3284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardUtils.containsOnlyNonCrLfPrintableAscii(prefix) && 3294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardUtils.containsOnlyNonCrLfPrintableAscii(suffix))); 3304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String formattedName; 3324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(displayName)) { 3334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa formattedName = displayName; 3344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 3354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa formattedName = VCardUtils.constructNameFromElements( 3364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardConfig.getNameOrderType(mVCardType), 3374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa familyName, middleName, givenName, prefix, suffix); 3384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyAppendCharsetParameterToFN = 3404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa shouldAppendCharsetParam(formattedName); 3414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintableToFN = 3424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !mRefrainsQPToNameProperties && 3434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(formattedName); 3444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedFamily; 3464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedGiven; 3474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedMiddle; 3484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPrefix; 3494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedSuffix; 3504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintableToName) { 3514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedFamily = encodeQuotedPrintable(familyName); 3524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedGiven = encodeQuotedPrintable(givenName); 3534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedMiddle = encodeQuotedPrintable(middleName); 3544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPrefix = encodeQuotedPrintable(prefix); 3554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedSuffix = encodeQuotedPrintable(suffix); 3564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 3574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedFamily = escapeCharacters(familyName); 3584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedGiven = escapeCharacters(givenName); 3594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedMiddle = escapeCharacters(middleName); 3604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPrefix = escapeCharacters(prefix); 3614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedSuffix = escapeCharacters(suffix); 3624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedFormattedname = 3654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (reallyUseQuotedPrintableToFN ? 3664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodeQuotedPrintable(formattedName) : escapeCharacters(formattedName)); 3674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_N); 3694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 3704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyAppendCharsetParameterToName) { 3714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 3724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 3734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintableToName) { 3754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 3764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 3774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 3794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // DoCoMo phones require that all the elements in the "family name" field. 3804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(formattedName); 3814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 3824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 3834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 3844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 3854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 3864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyAppendCharsetParameterToName) { 3874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 3884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 3894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintableToName) { 3914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 3924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 3934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 3954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedFamily); 3964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 3974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedGiven); 3984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 3994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedMiddle); 4004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 4014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPrefix); 4024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 4034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedSuffix); 4044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 4064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // FN property 4084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_FN); 4094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyAppendCharsetParameterToFN) { 4104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 4114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 4124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintableToFN) { 4144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 4154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 4164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 4184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedFormattedname); 4194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 4204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (!TextUtils.isEmpty(displayName)) { 4214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintableToDisplayName = 4224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (!mRefrainsQPToNameProperties && 4234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(displayName)); 4244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedDisplayName = 4254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa reallyUseQuotedPrintableToDisplayName ? 4264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodeQuotedPrintable(displayName) : 4274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa escapeCharacters(displayName); 4284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_N); 4304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(displayName)) { 4314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 4324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 4334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintableToDisplayName) { 4354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 4364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 4374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 4394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedDisplayName); 4404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 4414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 4424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 4434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 4444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 4454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_FN); 4464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Note: "CHARSET" param is not allowed in vCard 3.0, but we may add it 4484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // when it would be useful or necessary for external importers, 4494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // assuming the external importer allows this vioration of the spec. 4504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(displayName)) { 4514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 4524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 4534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 4554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedDisplayName); 4564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 4574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (mIsV30) { 4584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // vCard 3.0 specification requires these fields. 4594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_N, ""); 4604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_FN, ""); 4614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (mIsDoCoMo) { 4624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_N, ""); 4634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPhoneticNameFields(contentValues); 4664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 4674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendPhoneticNameFields(final ContentValues contentValues) { 4704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticFamilyName; 4714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticMiddleName; 4724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String phoneticGivenName; 4734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa { 4744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String tmpPhoneticFamilyName = 4754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME); 4764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String tmpPhoneticMiddleName = 4774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME); 4784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String tmpPhoneticGivenName = 4794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME); 4804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mNeedsToConvertPhoneticString) { 4814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticFamilyName = VCardUtils.toHalfWidthString(tmpPhoneticFamilyName); 4824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticMiddleName = VCardUtils.toHalfWidthString(tmpPhoneticMiddleName); 4834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticGivenName = VCardUtils.toHalfWidthString(tmpPhoneticGivenName); 4844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 4854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticFamilyName = tmpPhoneticFamilyName; 4864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticMiddleName = tmpPhoneticMiddleName; 4874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticGivenName = tmpPhoneticGivenName; 4884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(phoneticFamilyName) 4924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && TextUtils.isEmpty(phoneticMiddleName) 4934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && TextUtils.isEmpty(phoneticGivenName)) { 4944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 4954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_SOUND); 4964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 4974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PARAM_TYPE_X_IRMC_N); 4984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 4994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 5034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 5044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return; 5064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Try to emit the field(s) related to phonetic name. 5094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsV30) { 5104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String sortString = VCardUtils 5114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .constructNameFromElements(mVCardType, 5124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticFamilyName, phoneticMiddleName, phoneticGivenName); 5134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_SORT_STRING); 5144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(sortString)) { 5154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 5164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 5174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 5194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(escapeCharacters(sortString)); 5204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 5214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (mIsJapaneseMobilePhone) { 5224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Note: There is no appropriate property for expressing 5234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // phonetic name (Yomigana in Japanese) in vCard 2.1, while there is in 5244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // vCard 3.0 (SORT-STRING). 5254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We use DoCoMo's way when the device is Japanese one since it is already 5264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // supported by a lot of Japanese mobile phones. 5274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // This is "X-" property, so any parser hopefully would not get 5284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // confused with this. 5294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 5304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Also, DoCoMo's specification requires vCard composer to use just the first 5314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // column. 5324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // i.e. 5334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // good: SOUND;X-IRMC-N:Miyakawa Daisuke;;;; 5344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // bad : SOUND;X-IRMC-N:Miyakawa;Daisuke;;; 5354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_SOUND); 5364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 5374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PARAM_TYPE_X_IRMC_N); 5384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean reallyUseQuotedPrintable = 5404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (!mRefrainsQPToNameProperties 5414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && !(VCardUtils.containsOnlyNonCrLfPrintableAscii( 5424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticFamilyName) 5434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && VCardUtils.containsOnlyNonCrLfPrintableAscii( 5444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticMiddleName) 5454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && VCardUtils.containsOnlyNonCrLfPrintableAscii( 5464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneticGivenName))); 5474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticFamilyName; 5494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticMiddleName; 5504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticGivenName; 5514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 5524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName); 5534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName); 5544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName); 5554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 5564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName); 5574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName); 5584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticGivenName = escapeCharacters(phoneticGivenName); 5594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(encodedPhoneticFamilyName, 5624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticMiddleName, encodedPhoneticGivenName)) { 5634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 5644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 5654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 5674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa { 5684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean first = true; 5694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(encodedPhoneticFamilyName)) { 5704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticFamilyName); 5714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa first = false; 5724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(encodedPhoneticMiddleName)) { 5744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (first) { 5754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa first = false; 5764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 5774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(' '); 5784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticMiddleName); 5804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(encodedPhoneticGivenName)) { 5824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!first) { 5834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(' '); 5844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticGivenName); 5864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); // family;given 5894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); // given;middle 5904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); // middle;prefix 5914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); // prefix;suffix 5924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 5934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mUsesDefactProperty) { 5964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(phoneticGivenName)) { 5974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 5984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 5994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName)); 6004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticGivenName; 6014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 6024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName); 6034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 6044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticGivenName = escapeCharacters(phoneticGivenName); 6054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_FIRST_NAME); 6074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(phoneticGivenName)) { 6084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 6094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 6104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 6124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 6134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 6144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 6164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticGivenName); 6174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 6184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } // if (!TextUtils.isEmpty(phoneticGivenName)) 6194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(phoneticMiddleName)) { 6204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 6214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 6224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName)); 6234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticMiddleName; 6244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 6254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName); 6264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 6274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName); 6284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_MIDDLE_NAME); 6304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(phoneticMiddleName)) { 6314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 6324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 6334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 6354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 6364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 6374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 6394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticMiddleName); 6404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 6414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } // if (!TextUtils.isEmpty(phoneticGivenName)) 6424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(phoneticFamilyName)) { 6434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 6444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 6454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName)); 6464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPhoneticFamilyName; 6474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 6484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName); 6494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 6504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName); 6514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_LAST_NAME); 6534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (shouldAppendCharsetParam(phoneticFamilyName)) { 6544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 6554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 6564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 6584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 6594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 6604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 6624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedPhoneticFamilyName); 6634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 6644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } // if (!TextUtils.isEmpty(phoneticFamilyName)) 6654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendNickNames(final List<ContentValues> contentValuesList) { 6694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean useAndroidProperty; 6704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsV30) { 6714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa useAndroidProperty = false; 6724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (mUsesAndroidProperty) { 6734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa useAndroidProperty = true; 6744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 6754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // There's no way to add this field. 6764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 6774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 6794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 6804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String nickname = contentValues.getAsString(Nickname.NAME); 6814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(nickname)) { 6824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 6834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (useAndroidProperty) { 6854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendAndroidSpecificProperty(Nickname.CONTENT_ITEM_TYPE, contentValues); 6864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 6874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_NICKNAME, nickname); 6884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 6924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendPhones(final List<ContentValues> contentValuesList) { 6954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean phoneLineExists = false; 6964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 6974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Set<String> phoneSet = new HashSet<String>(); 6984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 6994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer typeAsObject = contentValues.getAsInteger(Phone.TYPE); 7004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String label = contentValues.getAsString(Phone.LABEL); 7014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isPrimaryAsInteger = contentValues.getAsInteger(Phone.IS_PRIMARY); 7024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary = (isPrimaryAsInteger != null ? 7034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isPrimaryAsInteger > 0) : false); 7044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String phoneNumber = contentValues.getAsString(Phone.NUMBER); 7054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (phoneNumber != null) { 7064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneNumber = phoneNumber.trim(); 7074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(phoneNumber)) { 7094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 7104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 7124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // PAGER number needs unformatted "phone number". 7134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int type = (typeAsObject != null ? typeAsObject : DEFAULT_PHONE_TYPE); 7144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (type == Phone.TYPE_PAGER || 7154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa VCardConfig.refrainPhoneNumberFormatting(mVCardType)) { 7164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneLineExists = true; 7174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!phoneSet.contains(phoneNumber)) { 7184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneSet.add(phoneNumber); 7194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTelLine(type, label, phoneNumber, isPrimary); 7204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 7224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> phoneNumberList = splitAndTrimPhoneNumbers(phoneNumber); 7234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (phoneNumberList.isEmpty()) { 7244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 7254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneLineExists = true; 7274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (String actualPhoneNumber : phoneNumberList) { 7284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!phoneSet.contains(actualPhoneNumber)) { 7294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int format = VCardUtils.getPhoneNumberFormat(mVCardType); 7304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String formattedPhoneNumber = 7314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa PhoneNumberUtils.formatNumber(actualPhoneNumber, format); 7324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneSet.add(actualPhoneNumber); 7334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTelLine(type, label, formattedPhoneNumber, isPrimary); 7344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } // for (String actualPhoneNumber : phoneNumberList) { 7364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 7404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!phoneLineExists && mIsDoCoMo) { 7414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTelLine(Phone.TYPE_HOME, "", "", false); 7424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 7444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 7454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 7474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 7484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 7494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Splits a given string expressing phone numbers into several strings, and remove 7504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * unnecessary characters inside them. The size of a returned list becomes 1 when 7514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * no split is needed. 7524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 7534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 7544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The given number "may" have several phone numbers when the contact entry is corrupted 7554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * because of its original source. 7564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * e.g. "111-222-3333 (Miami)\n444-555-6666 (Broward; 305-653-6796 (Miami)" 7574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 7584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 7594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * This kind of "phone numbers" will not be created with Android vCard implementation, 7604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * but we may encounter them if the source of the input data has already corrupted 7614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * implementation. 7624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 7634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 7644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * To handle this case, this method first splits its input into multiple parts 7654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * (e.g. "111-222-3333 (Miami)", "444-555-6666 (Broward", and 305653-6796 (Miami)") and 7664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * removes unnecessary strings like "(Miami)". 7674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 7684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 7694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Do not call this method when trimming is inappropriate for its receivers. 7704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 7714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 7724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private List<String> splitAndTrimPhoneNumbers(final String phoneNumber) { 7734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> phoneList = new ArrayList<String>(); 7744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 7754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa StringBuilder builder = new StringBuilder(); 7764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int length = phoneNumber.length(); 7774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (int i = 0; i < length; i++) { 7784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final char ch = phoneNumber.charAt(i); 7794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (Character.isDigit(ch) || ch == '+') { 7804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append(ch); 7814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if ((ch == ';' || ch == '\n') && builder.length() > 0) { 7824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneList.add(builder.toString()); 7834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder = new StringBuilder(); 7844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (builder.length() > 0) { 7874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa phoneList.add(builder.toString()); 7884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 7904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return phoneList; 7914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 7924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 7934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendEmails(final List<ContentValues> contentValuesList) { 7944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean emailAddressExists = false; 7954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 7964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Set<String> addressSet = new HashSet<String>(); 7974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 7984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String emailAddress = contentValues.getAsString(Email.DATA); 7994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (emailAddress != null) { 8004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa emailAddress = emailAddress.trim(); 8014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(emailAddress)) { 8034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 8044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Integer typeAsObject = contentValues.getAsInteger(Email.TYPE); 8064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int type = (typeAsObject != null ? 8074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsObject : DEFAULT_EMAIL_TYPE); 8084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String label = contentValues.getAsString(Email.LABEL); 8094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Integer isPrimaryAsInteger = contentValues.getAsInteger(Email.IS_PRIMARY); 8104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary = (isPrimaryAsInteger != null ? 8114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isPrimaryAsInteger > 0) : false); 8124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa emailAddressExists = true; 8134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!addressSet.contains(emailAddress)) { 8144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressSet.add(emailAddress); 8154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendEmailLine(type, label, emailAddress, isPrimary); 8164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!emailAddressExists && mIsDoCoMo) { 8214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendEmailLine(Email.TYPE_HOME, "", "", false); 8224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 8254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendPostals(final List<ContentValues> contentValuesList) { 8284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList == null || contentValuesList.isEmpty()) { 8294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 8304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_ADR); 8314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 8324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PARAM_TYPE_HOME); 8334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 8344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 8354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 8374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 8384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPostalsForDoCoMo(contentValuesList); 8394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 8404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPostalsForGeneric(contentValuesList); 8414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 8454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final Map<Integer, Integer> sPostalTypePriorityMap; 8484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa static { 8504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sPostalTypePriorityMap = new HashMap<Integer, Integer>(); 8514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sPostalTypePriorityMap.put(StructuredPostal.TYPE_HOME, 0); 8524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sPostalTypePriorityMap.put(StructuredPostal.TYPE_WORK, 1); 8534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sPostalTypePriorityMap.put(StructuredPostal.TYPE_OTHER, 2); 8544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sPostalTypePriorityMap.put(StructuredPostal.TYPE_CUSTOM, 3); 8554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 8584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Tries to append just one line. If there's no appropriate address 8594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * information, append an empty line. 8604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 8614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendPostalsForDoCoMo(final List<ContentValues> contentValuesList) { 8624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int currentPriority = Integer.MAX_VALUE; 8634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int currentType = Integer.MAX_VALUE; 8644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ContentValues currentContentValues = null; 8654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final ContentValues contentValues : contentValuesList) { 8664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null) { 8674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 8684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE); 8704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer priorityAsInteger = sPostalTypePriorityMap.get(typeAsInteger); 8714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int priority = 8724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (priorityAsInteger != null ? priorityAsInteger : Integer.MAX_VALUE); 8734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (priority < currentPriority) { 8744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa currentPriority = priority; 8754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa currentType = typeAsInteger; 8764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa currentContentValues = contentValues; 8774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (priority == 0) { 8784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 8794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (currentContentValues == null) { 8844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "Should not come here. Must have at least one postal data."); 8854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return; 8864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String label = currentContentValues.getAsString(StructuredPostal.LABEL); 8894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPostalLine(currentType, label, currentContentValues, false, true); 8904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 8924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendPostalsForGeneric(final List<ContentValues> contentValuesList) { 8934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final ContentValues contentValues : contentValuesList) { 8944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null) { 8954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 8964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 8974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE); 8984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int type = (typeAsInteger != null ? 8994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsInteger : DEFAULT_POSTAL_TYPE); 9004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String label = contentValues.getAsString(StructuredPostal.LABEL); 9014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isPrimaryAsInteger = 9024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsInteger(StructuredPostal.IS_PRIMARY); 9034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary = (isPrimaryAsInteger != null ? 9044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isPrimaryAsInteger > 0) : false); 9054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPostalLine(type, label, contentValues, isPrimary, false); 9064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static class PostalStruct { 9104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable; 9114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean appendCharset; 9124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String addressData; 9134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public PostalStruct(final boolean reallyUseQuotedPrintable, 9144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean appendCharset, final String addressData) { 9154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this.reallyUseQuotedPrintable = reallyUseQuotedPrintable; 9164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this.appendCharset = appendCharset; 9174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this.addressData = addressData; 9184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 9224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return null when there's no information available to construct the data. 9234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 9244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private PostalStruct tryConstructPostalStruct(ContentValues contentValues) { 9254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // adr-value = 0*6(text-value ";") text-value 9264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // ; PO Box, Extended Address, Street, Locality, Region, Postal 9274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // ; Code, Country Name 9284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawPoBox = contentValues.getAsString(StructuredPostal.POBOX); 9294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawNeighborhood = contentValues.getAsString(StructuredPostal.NEIGHBORHOOD); 9304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawStreet = contentValues.getAsString(StructuredPostal.STREET); 9314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawLocality = contentValues.getAsString(StructuredPostal.CITY); 9324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawRegion = contentValues.getAsString(StructuredPostal.REGION); 9334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawPostalCode = contentValues.getAsString(StructuredPostal.POSTCODE); 9344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawCountry = contentValues.getAsString(StructuredPostal.COUNTRY); 9354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String[] rawAddressArray = new String[]{ 9364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawPoBox, rawNeighborhood, rawStreet, rawLocality, 9374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawRegion, rawPostalCode, rawCountry}; 9384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!VCardUtils.areAllEmpty(rawAddressArray)) { 9394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 9404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 9414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawAddressArray)); 9424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean appendCharset = 9434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(rawAddressArray); 9444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPoBox; 9454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedStreet; 9464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedLocality; 9474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedRegion; 9484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedPostalCode; 9494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedCountry; 9504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedNeighborhood; 9514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 9524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawLocality2; 9534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // This looks inefficient since we encode rawLocality and rawNeighborhood twice, 9544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // but this is intentional. 9554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 9564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // QP encoding may add line feeds when needed and the result of 9574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // - encodeQuotedPrintable(rawLocality + " " + rawNeighborhood) 9584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // may be different from 9594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // - encodedLocality + " " + encodedNeighborhood. 9604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 9614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We use safer way. 9624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(rawLocality)) { 9634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(rawNeighborhood)) { 9644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawLocality2 = ""; 9654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 9664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawLocality2 = rawNeighborhood; 9674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 9694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(rawNeighborhood)) { 9704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawLocality2 = rawLocality; 9714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 9724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawLocality2 = rawLocality + " " + rawNeighborhood; 9734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 9764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPoBox = encodeQuotedPrintable(rawPoBox); 9774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedStreet = encodeQuotedPrintable(rawStreet); 9784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedLocality = encodeQuotedPrintable(rawLocality2); 9794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedRegion = encodeQuotedPrintable(rawRegion); 9804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPostalCode = encodeQuotedPrintable(rawPostalCode); 9814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedCountry = encodeQuotedPrintable(rawCountry); 9824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 9834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPoBox = escapeCharacters(rawPoBox); 9844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedStreet = escapeCharacters(rawStreet); 9854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedLocality = escapeCharacters(rawLocality2); 9864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedRegion = escapeCharacters(rawRegion); 9874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedPostalCode = escapeCharacters(rawPostalCode); 9884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedCountry = escapeCharacters(rawCountry); 9894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedNeighborhood = escapeCharacters(rawNeighborhood); 9904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 9914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final StringBuilder addressBuilder = new StringBuilder(); 9924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedPoBox); 9934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // PO BOX ; Extended Address 9944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Extended Address : Street 9954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedStreet); 9964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Street : Locality 9974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedLocality); 9984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Locality : Region 9994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedRegion); 10004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Region : Postal Code 10014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedPostalCode); 10024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Postal Code : Country 10034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedCountry); 10044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return new PostalStruct( 10054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa reallyUseQuotedPrintable, appendCharset, addressBuilder.toString()); 10064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { // VCardUtils.areAllEmpty(rawAddressArray) == true 10074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Try to use FORMATTED_ADDRESS instead. 10084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawFormattedAddress = 10094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsString(StructuredPostal.FORMATTED_ADDRESS); 10104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(rawFormattedAddress)) { 10114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return null; 10124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 10144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 10154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawFormattedAddress)); 10164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean appendCharset = 10174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(rawFormattedAddress); 10184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedFormattedAddress; 10194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 10204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedFormattedAddress = encodeQuotedPrintable(rawFormattedAddress); 10214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 10224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedFormattedAddress = escapeCharacters(rawFormattedAddress); 10234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 10254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We use the second value ("Extended Address") just because Japanese mobile phones 10264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // do so. If the other importer expects the value be in the other field, some flag may 10274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // be needed. 10284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final StringBuilder addressBuilder = new StringBuilder(); 10294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // PO BOX ; Extended Address 10304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(encodedFormattedAddress); 10314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Extended Address : Street 10324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Street : Locality 10334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Locality : Region 10344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Region : Postal Code 10354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressBuilder.append(VCARD_ITEM_SEPARATOR); // Postal Code : Country 10364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return new PostalStruct( 10374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa reallyUseQuotedPrintable, appendCharset, addressBuilder.toString()); 10384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 10414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendIms(final List<ContentValues> contentValuesList) { 10424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 10434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 10444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer protocolAsObject = contentValues.getAsInteger(Im.PROTOCOL); 10454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (protocolAsObject == null) { 10464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 10474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String propertyName = VCardUtils.getPropertyNameForIm(protocolAsObject); 10494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (propertyName == null) { 10504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 10514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String data = contentValues.getAsString(Im.DATA); 10534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (data != null) { 10544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa data = data.trim(); 10554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(data)) { 10574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 10584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String typeAsString; 10604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa { 10614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer typeAsInteger = contentValues.getAsInteger(Im.TYPE); 10624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa switch (typeAsInteger != null ? typeAsInteger : Im.TYPE_OTHER) { 10634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Im.TYPE_HOME: { 10644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_HOME; 10654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 10664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Im.TYPE_WORK: { 10684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_WORK; 10694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 10704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Im.TYPE_CUSTOM: { 10724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String label = contentValues.getAsString(Im.LABEL); 10734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = (label != null ? "X-" + label : null); 10744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 10754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Im.TYPE_OTHER: // Ignore 10774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa default: { 10784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = null; 10794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 10804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 10844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> parameterList = new ArrayList<String>(); 10854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(typeAsString)) { 10864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(typeAsString); 10874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isPrimaryAsInteger = contentValues.getAsInteger(Im.IS_PRIMARY); 10894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary = (isPrimaryAsInteger != null ? 10904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isPrimaryAsInteger > 0) : false); 10914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary) { 10924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PREF); 10934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 10954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(propertyName, parameterList, data); 10964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 10984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 10994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 11014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendWebsites(final List<ContentValues> contentValuesList) { 11024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 11034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 11044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String website = contentValues.getAsString(Website.URL); 11054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (website != null) { 11064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa website = website.trim(); 11074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 11094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Note: vCard 3.0 does not allow any parameter addition toward "URL" 11104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // property, while there's no document in vCard 2.1. 11114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(website)) { 11124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_URL, website); 11134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 11174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 11194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendOrganizations(final List<ContentValues> contentValuesList) { 11204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 11214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 11224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String company = contentValues.getAsString(Organization.COMPANY); 11234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (company != null) { 11244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa company = company.trim(); 11254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String department = contentValues.getAsString(Organization.DEPARTMENT); 11274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (department != null) { 11284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa department = department.trim(); 11294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String title = contentValues.getAsString(Organization.TITLE); 11314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (title != null) { 11324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa title = title.trim(); 11334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 11354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa StringBuilder orgBuilder = new StringBuilder(); 11364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(company)) { 11374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa orgBuilder.append(company); 11384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(department)) { 11404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (orgBuilder.length() > 0) { 11414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa orgBuilder.append(';'); 11424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa orgBuilder.append(department); 11444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String orgline = orgBuilder.toString(); 11464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_ORG, orgline, 11474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(orgline), 11484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 11494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(orgline))); 11504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 11514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(title)) { 11524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_TITLE, title, 11534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(title), 11544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 11554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(title))); 11564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 11604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 11624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendPhotos(final List<ContentValues> contentValuesList) { 11634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 11644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 11654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null) { 11664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 11674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa byte[] data = contentValues.getAsByteArray(Photo.PHOTO); 11694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (data == null) { 11704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 11714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String photoType = VCardUtils.guessImageType(data); 11734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (photoType == null) { 11744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.d(LOG_TAG, "Unknown photo type. Ignored."); 11754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 11764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // TODO: check this works fine. 11784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String photoString = new String(Base64.encode(data, Base64.NO_WRAP)); 11794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(photoString)) { 11804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendPhotoLine(photoString, photoType); 11814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 11854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 11874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendNotes(final List<ContentValues> contentValuesList) { 11884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 11894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mOnlyOneNoteFieldIsAvailable) { 11904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final StringBuilder noteBuilder = new StringBuilder(); 11914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean first = true; 11924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final ContentValues contentValues : contentValuesList) { 11934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String note = contentValues.getAsString(Note.NOTE); 11944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (note == null) { 11954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa note = ""; 11964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 11974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (note.length() > 0) { 11984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (first) { 11994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa first = false; 12004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 12014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa noteBuilder.append('\n'); 12024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa noteBuilder.append(note); 12044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String noteStr = noteBuilder.toString(); 12074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // This means we scan noteStr completely twice, which is redundant. 12084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // But for now, we assume this is not so time-consuming.. 12094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean shouldAppendCharsetInfo = 12104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(noteStr); 12114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 12124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 12134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr)); 12144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_NOTE, noteStr, 12154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa shouldAppendCharsetInfo, reallyUseQuotedPrintable); 12164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 12174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (ContentValues contentValues : contentValuesList) { 12184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String noteStr = contentValues.getAsString(Note.NOTE); 12194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(noteStr)) { 12204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean shouldAppendCharsetInfo = 12214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(noteStr); 12224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 12234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 12244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr)); 12254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_NOTE, noteStr, 12264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa shouldAppendCharsetInfo, reallyUseQuotedPrintable); 12274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 12324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 12344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendEvents(final List<ContentValues> contentValuesList) { 12354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // There's possibility where a given object may have more than one birthday, which 12364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // is inappropriate. We just build one birthday. 12374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList != null) { 12384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String primaryBirthday = null; 12394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String secondaryBirthday = null; 12404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final ContentValues contentValues : contentValuesList) { 12414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null) { 12424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 12434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer eventTypeAsInteger = contentValues.getAsInteger(Event.TYPE); 12454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int eventType; 12464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (eventTypeAsInteger != null) { 12474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa eventType = eventTypeAsInteger; 12484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 12494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa eventType = Event.TYPE_OTHER; 12504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (eventType == Event.TYPE_BIRTHDAY) { 12524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String birthdayCandidate = contentValues.getAsString(Event.START_DATE); 12534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (birthdayCandidate == null) { 12544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 12554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isSuperPrimaryAsInteger = 12574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsInteger(Event.IS_SUPER_PRIMARY); 12584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isSuperPrimary = (isSuperPrimaryAsInteger != null ? 12594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isSuperPrimaryAsInteger > 0) : false); 12604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isSuperPrimary) { 12614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // "super primary" birthday should the prefered one. 12624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryBirthday = birthdayCandidate; 12634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 12644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Integer isPrimaryAsInteger = 12664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValues.getAsInteger(Event.IS_PRIMARY); 12674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary = (isPrimaryAsInteger != null ? 12684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (isPrimaryAsInteger > 0) : false); 12694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary) { 12704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We don't break here since "super primary" birthday may exist later. 12714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryBirthday = birthdayCandidate; 12724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (secondaryBirthday == null) { 12734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // First entry is set to the "secondary" candidate. 12744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa secondaryBirthday = birthdayCandidate; 12754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (mUsesAndroidProperty) { 12774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Event types other than Birthday is not supported by vCard. 12784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendAndroidSpecificProperty(Event.CONTENT_ITEM_TYPE, contentValues); 12794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (primaryBirthday != null) { 12824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_BDAY, 12834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa primaryBirthday.trim()); 12844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (secondaryBirthday != null){ 12854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_BDAY, 12864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa secondaryBirthday.trim()); 12874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 12904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 12924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardBuilder appendRelation(final List<ContentValues> contentValuesList) { 12934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mUsesAndroidProperty && contentValuesList != null) { 12944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final ContentValues contentValues : contentValuesList) { 12954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValues == null) { 12964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa continue; 12974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 12984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendAndroidSpecificProperty(Relation.CONTENT_ITEM_TYPE, contentValues); 12994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return this; 13024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 13044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 13054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param emitEveryTime If true, builder builds the line even when there's no entry. 13064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 13074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendPostalLine(final int type, final String label, 13084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final ContentValues contentValues, 13094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean isPrimary, final boolean emitEveryTime) { 13104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable; 13114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean appendCharset; 13124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String addressValue; 13134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa { 13144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa PostalStruct postalStruct = tryConstructPostalStruct(contentValues); 13154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (postalStruct == null) { 13164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (emitEveryTime) { 13174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa reallyUseQuotedPrintable = false; 13184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendCharset = false; 13194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressValue = ""; 13204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 13214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return; 13224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 13244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa reallyUseQuotedPrintable = postalStruct.reallyUseQuotedPrintable; 13254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendCharset = postalStruct.appendCharset; 13264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa addressValue = postalStruct.addressData; 13274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 13304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa List<String> parameterList = new ArrayList<String>(); 13314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary) { 13324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PREF); 13334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa switch (type) { 13354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case StructuredPostal.TYPE_HOME: { 13364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_HOME); 13374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 13384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case StructuredPostal.TYPE_WORK: { 13404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_WORK); 13414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 13424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case StructuredPostal.TYPE_CUSTOM: { 13444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(label) 13454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && VCardUtils.containsOnlyAlphaDigitHyphen(label)) { 13464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We're not sure whether the label is valid in the spec 13474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // ("IANA-token" in the vCard 3.0 is unclear...) 13484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Just for safety, we add "X-" at the beggining of each label. 13494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Also checks the label obeys with vCard 3.0 spec. 13504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add("X-" + label); 13514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 13534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case StructuredPostal.TYPE_OTHER: { 13554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 13564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa default: { 13584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "Unknown StructuredPostal type: " + type); 13594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 13604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 13634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_ADR); 13644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!parameterList.isEmpty()) { 13654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 13664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameters(parameterList); 13674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (appendCharset) { 13694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Strictly, vCard 3.0 does not allow exporters to emit charset information, 13704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // but we will add it since the information should be useful for importers, 13714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 13724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Assume no parser does not emit error with this parameter in vCard 3.0. 13734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 13744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 13754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 13774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 13784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 13794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 13814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(addressValue); 13824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 13834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 13854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendEmailLine(final int type, final String label, 13864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawValue, final boolean isPrimary) { 13874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String typeAsString; 13884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa switch (type) { 13894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Email.TYPE_CUSTOM: { 13904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (VCardUtils.isMobilePhoneLabel(label)) { 13914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_CELL; 13924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (!TextUtils.isEmpty(label) 13934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && VCardUtils.containsOnlyAlphaDigitHyphen(label)) { 13944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = "X-" + label; 13954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 13964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = null; 13974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 13984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 13994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Email.TYPE_HOME: { 14014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_HOME; 14024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Email.TYPE_WORK: { 14054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_WORK; 14064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Email.TYPE_OTHER: { 14094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = null; 14104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Email.TYPE_MOBILE: { 14134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = VCardConstants.PARAM_TYPE_CELL; 14144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa default: { 14174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "Unknown Email type: " + type); 14184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa typeAsString = null; 14194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 14234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> parameterList = new ArrayList<String>(); 14244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary) { 14254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PREF); 14264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!TextUtils.isEmpty(typeAsString)) { 14284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(typeAsString); 14294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 14314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_EMAIL, parameterList, 14324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawValue); 14334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 14354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendTelLine(final Integer typeAsInteger, final String label, 14364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedValue, boolean isPrimary) { 14374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_TEL); 14384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 14394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 14404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int type; 14414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (typeAsInteger == null) { 14424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa type = Phone.TYPE_OTHER; 14434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 14444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa type = typeAsInteger; 14454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 14474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ArrayList<String> parameterList = new ArrayList<String>(); 14484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa switch (type) { 14494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_HOME: { 14504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.addAll( 14514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Arrays.asList(VCardConstants.PARAM_TYPE_HOME)); 14524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_WORK: { 14554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.addAll( 14564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Arrays.asList(VCardConstants.PARAM_TYPE_WORK)); 14574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_FAX_HOME: { 14604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.addAll( 14614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Arrays.asList(VCardConstants.PARAM_TYPE_HOME, VCardConstants.PARAM_TYPE_FAX)); 14624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_FAX_WORK: { 14654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.addAll( 14664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Arrays.asList(VCardConstants.PARAM_TYPE_WORK, VCardConstants.PARAM_TYPE_FAX)); 14674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_MOBILE: { 14704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_CELL); 14714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_PAGER: { 14744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 14754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Not sure about the reason, but previous implementation had 14764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // used "VOICE" instead of "PAGER" 14774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_VOICE); 14784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 14794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PAGER); 14804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_OTHER: { 14844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_VOICE); 14854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_CAR: { 14884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_CAR); 14894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_COMPANY_MAIN: { 14924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // There's no relevant field in vCard (at least 2.1). 14934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_WORK); 14944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa isPrimary = true; 14954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 14964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 14974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_ISDN: { 14984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_ISDN); 14994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_MAIN: { 15024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa isPrimary = true; 15034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_OTHER_FAX: { 15064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_FAX); 15074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_TELEX: { 15104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_TLX); 15114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_WORK_MOBILE: { 15144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.addAll( 15154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Arrays.asList(VCardConstants.PARAM_TYPE_WORK, VCardConstants.PARAM_TYPE_CELL)); 15164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_WORK_PAGER: { 15194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_WORK); 15204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // See above. 15214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 15224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_VOICE); 15234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 15244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PAGER); 15254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_MMS: { 15294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_MSG); 15304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_CUSTOM: { 15334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(label)) { 15344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Just ignore the custom type. 15354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_VOICE); 15364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (VCardUtils.isMobilePhoneLabel(label)) { 15374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_CELL); 15382bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } else if (mIsV30) { 15392bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // This label is appropriately encoded in appendTypeParameters. 15402bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa parameterList.add(label); 15414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 15424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String upperLabel = label.toUpperCase(); 15434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (VCardUtils.isValidInV21ButUnknownToContactsPhoteType(upperLabel)) { 15444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(upperLabel); 15454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else if (VCardUtils.containsOnlyAlphaDigitHyphen(label)) { 15464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Note: Strictly, vCard 2.1 does not allow "X-" parameter without 15474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // "TYPE=" string. 15484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add("X-" + label); 15494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_RADIO: 15544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case Phone.TYPE_TTY_TDD: 15554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa default: { 15564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 15574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 15604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (isPrimary) { 15614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa parameterList.add(VCardConstants.PARAM_TYPE_PREF); 15624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 15644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (parameterList.isEmpty()) { 15654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendUncommonPhoneType(mBuilder, type); 15664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 15674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameters(parameterList); 15684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 15704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 15714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedValue); 15724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 15734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 15754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 15764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Appends phone type string which may not be available in some devices. 15774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 15784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendUncommonPhoneType(final StringBuilder builder, final Integer type) { 15794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 15804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // The previous implementation for DoCoMo had been conservative 15814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // about miscellaneous types. 15824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append(VCardConstants.PARAM_TYPE_VOICE); 15834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 15844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String phoneType = VCardUtils.getPhoneTypeString(type); 15854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (phoneType != null) { 15864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameter(phoneType); 15874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 15884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "Unknown or unsupported (by vCard) Phone type: " + type); 15894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 15924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 15934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 15944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param encodedValue Must be encoded by BASE64 15954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param photoType 15964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 15974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendPhotoLine(final String encodedValue, final String photoType) { 15984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa StringBuilder tmpBuilder = new StringBuilder(); 15994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCardConstants.PROPERTY_PHOTO); 16004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_PARAM_SEPARATOR); 16014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsV30) { 16024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_PARAM_ENCODING_BASE64_V30); 16034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 16044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_PARAM_ENCODING_BASE64_V21); 16054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_PARAM_SEPARATOR); 16074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameter(tmpBuilder, photoType); 16084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_DATA_SEPARATOR); 16094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(encodedValue); 16104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 16114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String tmpStr = tmpBuilder.toString(); 16124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder = new StringBuilder(); 16134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int lineCount = 0; 16144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int length = tmpStr.length(); 16154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int maxNumForFirstLine = VCardConstants.MAX_CHARACTER_NUMS_BASE64_V30 16164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa - VCARD_END_OF_LINE.length(); 16174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int maxNumInGeneral = maxNumForFirstLine - VCARD_WS.length(); 16184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int maxNum = maxNumForFirstLine; 16194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (int i = 0; i < length; i++) { 16204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(tmpStr.charAt(i)); 16214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa lineCount++; 16224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (lineCount > maxNum) { 16234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_END_OF_LINE); 16244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(VCARD_WS); 16254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa maxNum = maxNumInGeneral; 16264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa lineCount = 0; 16274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(tmpBuilder.toString()); 16304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 16314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 16324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 16344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendAndroidSpecificProperty( 16354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String mimeType, ContentValues contentValues) { 16364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!sAllowedAndroidPropertySet.contains(mimeType)) { 16374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return; 16384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> rawValueList = new ArrayList<String>(); 16404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (int i = 1; i <= VCardConstants.MAX_DATA_COLUMN; i++) { 16414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String value = contentValues.getAsString("data" + i); 16424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (value == null) { 16434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa value = ""; 16444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawValueList.add(value); 16464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 16484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean needCharset = 16494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldAppendCharsetParam && 16504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); 16514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean reallyUseQuotedPrintable = 16524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 16534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); 16544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCardConstants.PROPERTY_X_ANDROID_CUSTOM); 16554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (needCharset) { 16564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 16574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 16584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 16604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 16614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 16624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 16644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mimeType); // Should not be encoded. 16654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (String rawValue : rawValueList) { 16664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedValue; 16674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 16684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = encodeQuotedPrintable(rawValue); 16694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 16704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // TODO: one line may be too huge, which may be invalid in vCard 3.0 16714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // (which says "When generating a content line, lines longer than 16724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 75 characters SHOULD be folded"), though several 16734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // (even well-known) applications do not care this. 16744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = escapeCharacters(rawValue); 16754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 16774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedValue); 16784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 16804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 16824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLineWithCharsetAndQPDetection(final String propertyName, 16834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawValue) { 16844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(propertyName, null, rawValue); 16854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 16874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLineWithCharsetAndQPDetection( 16884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String propertyName, final List<String> rawValueList) { 16894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLineWithCharsetAndQPDetection(propertyName, null, rawValueList); 16904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 16914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 16924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLineWithCharsetAndQPDetection(final String propertyName, 16934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> parameterList, final String rawValue) { 16944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean needCharset = 16954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyPrintableAscii(rawValue); 16964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean reallyUseQuotedPrintable = 16974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 16984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValue)); 16994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, parameterList, 17004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa rawValue, needCharset, reallyUseQuotedPrintable); 17014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLineWithCharsetAndQPDetection(final String propertyName, 17044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> parameterList, final List<String> rawValueList) { 17054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean needCharset = 17064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldAppendCharsetParam && 17074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); 17084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean reallyUseQuotedPrintable = 17094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa (mShouldUseQuotedPrintable && 17104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); 17114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, parameterList, rawValueList, 17124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa needCharset, reallyUseQuotedPrintable); 17134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 17164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Appends one line with a given property name and value. 17174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 17184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final String rawValue) { 17194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, rawValue, false, false); 17204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final List<String> rawValueList) { 17234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, rawValueList, false, false); 17244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, 17274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawValue, final boolean needCharset, 17284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean reallyUseQuotedPrintable) { 17294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, null, rawValue, needCharset, reallyUseQuotedPrintable); 17304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final List<String> parameterList, 17334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawValue) { 17344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, parameterList, rawValue, false, false); 17354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final List<String> parameterList, 17384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String rawValue, final boolean needCharset, 17394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean reallyUseQuotedPrintable) { 17404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(propertyName); 17414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (parameterList != null && parameterList.size() > 0) { 17424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 17434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameters(parameterList); 17444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (needCharset) { 17464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 17474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 17484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedValue; 17514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (reallyUseQuotedPrintable) { 17524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 17534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 17544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = encodeQuotedPrintable(rawValue); 17554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 17564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // TODO: one line may be too huge, which may be invalid in vCard spec, though 17574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // several (even well-known) applications do not care that violation. 17584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = escapeCharacters(rawValue); 17594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 17624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedValue); 17634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 17644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final List<String> rawValueList, 17674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean needCharset, boolean needQuotedPrintable) { 17684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(propertyName, null, rawValueList, needCharset, needQuotedPrintable); 17694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void appendLine(final String propertyName, final List<String> parameterList, 17724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<String> rawValueList, final boolean needCharset, 17734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean needQuotedPrintable) { 17744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(propertyName); 17754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (parameterList != null && parameterList.size() > 0) { 17764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 17774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameters(parameterList); 17784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (needCharset) { 17804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 17814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(mVCardCharsetParameter); 17824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (needQuotedPrintable) { 17844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 17854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_PARAM_ENCODING_QP); 17864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 17874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 17884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_DATA_SEPARATOR); 17894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean first = true; 17904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (String rawValue : rawValueList) { 17914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String encodedValue; 17924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (needQuotedPrintable) { 17934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = encodeQuotedPrintable(rawValue); 17944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 17954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // TODO: one line may be too huge, which may be invalid in vCard 3.0 17964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // (which says "When generating a content line, lines longer than 17974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 75 characters SHOULD be folded"), though several 17984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // (even well-known) applications do not care this. 17994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa encodedValue = escapeCharacters(rawValue); 18004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (first) { 18034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa first = false; 18044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 18054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_ITEM_SEPARATOR); 18064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(encodedValue); 18084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mBuilder.append(VCARD_END_OF_LINE); 18104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 18134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * VCARD_PARAM_SEPARATOR must be appended before this method being called. 18144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 18154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendTypeParameters(final List<String> types) { 18164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We may have to make this comma separated form like "TYPE=DOM,WORK" in the future, 18174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // which would be recommended way in vcard 3.0 though not valid in vCard 2.1. 18184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa boolean first = true; 18194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (final String typeValue : types) { 18202bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa if (VCardConfig.isVersion30(mVCardType)) { 18212bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa final String encoded = VCardUtils.toStringAvailableAsV30ParamValue(typeValue); 18222bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa if (TextUtils.isEmpty(encoded)) { 18232bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa continue; 18242bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } 18252bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa 18262bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // Note: vCard 3.0 specifies the different type of acceptable type Strings, but 18272bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // we don't emit that kind of vCard 3.0 specific type since there should be 18282bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // high probabilyty in which external importers cannot understand them. 18292bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // 18302bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // e.g. TYPE="\u578B\u306B\u3087" (vCard 3.0 allows non-Ascii characters if they 18312bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa // are quoted.) 18322bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa if (first) { 18332bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa first = false; 18342bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } else { 18352bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 18362bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } 18372bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa appendTypeParameter(encoded); 18382bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } else { // vCard 2.1 18392bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa if (!VCardUtils.isV21Word(typeValue)) { 18402bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa continue; 18412bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } 18422bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa if (first) { 18432bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa first = false; 18442bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } else { 18452bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa mBuilder.append(VCARD_PARAM_SEPARATOR); 18462bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa } 18472bf85a1a15a3175119ab8415fc590fd5fe3d0752Daisuke Miyakawa appendTypeParameter(typeValue); 18484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 18534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * VCARD_PARAM_SEPARATOR must be appended before this method being called. 18544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 18554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendTypeParameter(final String type) { 18564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendTypeParameter(mBuilder, type); 18574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private void appendTypeParameter(final StringBuilder builder, final String type) { 18604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Refrain from using appendType() so that "TYPE=" is not be appended when the 18614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // device is DoCoMo's (just for safety). 18624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 18634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Note: In vCard 3.0, Type strings also can be like this: "TYPE=HOME,PREF" 18644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if ((mIsV30 || mAppendTypeParamName) && !mIsDoCoMo) { 18654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append(VCardConstants.PARAM_TYPE).append(VCARD_PARAM_EQUAL); 18664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append(type); 18684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 18714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Returns true when the property line should contain charset parameter 18724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * information. This method may return true even when vCard version is 3.0. 18734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 18744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Strictly, adding charset information is invalid in VCard 3.0. 18754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * However we'll add the info only when charset we use is not UTF-8 18764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * in vCard 3.0 format, since parser side may be able to use the charset 18774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * via this field, though we may encounter another problem by adding it. 18784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 18794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * e.g. Japanese mobile phones use Shift_Jis while RFC 2426 18804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * recommends UTF-8. By adding this field, parsers may be able 18814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * to know this text is NOT UTF-8 but Shift_Jis. 18824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 18834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private boolean shouldAppendCharsetParam(String...propertyValueList) { 18844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!mShouldAppendCharsetParam) { 18854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 18864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (String propertyValue : propertyValueList) { 18884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!VCardUtils.containsOnlyPrintableAscii(propertyValue)) { 18894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return true; 18904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 18934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private String encodeQuotedPrintable(final String str) { 18964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(str)) { 18974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 18984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 18994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final StringBuilder builder = new StringBuilder(); 19014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int index = 0; 19024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa int lineCount = 0; 19034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa byte[] strArray = null; 19044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 19064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa strArray = str.getBytes(mCharset); 19074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedEncodingException e) { 19084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "Charset " + mCharset + " cannot be used. " 19094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Try default charset"); 19104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa strArray = str.getBytes(); 19114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa while (index < strArray.length) { 19134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append(String.format("=%02X", strArray[index])); 19144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa index += 1; 19154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa lineCount += 3; 19164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (lineCount >= 67) { 19184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Specification requires CRLF must be inserted before the 19194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // length of the line 19204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // becomes more than 76. 19214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Assuming that the next character is a multi-byte character, 19224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // it will become 19234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 6 bytes. 19244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // 76 - 6 - 3 = 67 19254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.append("=\r\n"); 19264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa lineCount = 0; 19274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return builder.toString(); 19314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 19344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Append '\' to the characters which should be escaped. The character set is different 19354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * not only between vCard 2.1 and vCard 3.0 but also among each device. 19364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 19374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Note that Quoted-Printable string must not be input here. 19384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 19394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa @SuppressWarnings("fallthrough") 19404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private String escapeCharacters(final String unescaped) { 19414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(unescaped)) { 19424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 19434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 19454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final StringBuilder tmpBuilder = new StringBuilder(); 19464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final int length = unescaped.length(); 19474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (int i = 0; i < length; i++) { 19484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final char ch = unescaped.charAt(i); 19494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa switch (ch) { 19504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case ';': { 19514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append('\\'); 19524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(';'); 19534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 19544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case '\r': { 19564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (i + 1 < length) { 19574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa char nextChar = unescaped.charAt(i); 19584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (nextChar == '\n') { 19594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 19604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 19614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // fall through 19624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 19644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // fall through 19654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case '\n': { 19684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // In vCard 2.1, there's no specification about this, while 19694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // vCard 3.0 explicitly requires this should be encoded to "\n". 19704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append("\\n"); 19714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 19724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case '\\': { 19744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsV30) { 19754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append("\\\\"); 19764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 19774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 19784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // fall through 19794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case '<': 19824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case '>': { 19834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 19844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append('\\'); 19854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(ch); 19864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 19874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(ch); 19884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 19904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa case ',': { 19924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsV30) { 19934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append("\\,"); 19944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 19954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(ch); 19964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 19984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 19994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa default: { 20004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa tmpBuilder.append(ch); 20014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa break; 20024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return tmpBuilder.toString(); 20064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 20084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa @Override 20094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public String toString() { 20104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!mEndAppended) { 20114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 20124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_X_CLASS, VCARD_DATA_PUBLIC); 20134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_X_REDUCTION, ""); 20144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_X_NO, ""); 20154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_X_DCM_HMN_MODE, ""); 20164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa appendLine(VCardConstants.PROPERTY_END, VCARD_DATA_VCARD); 20184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mEndAppended = true; 20194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mBuilder.toString(); 20214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 20224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa} 2023