Merge change I11526e6c into eclair-mr2
* changes: Clean up codes and remove/modify stale codes/comments.
This commit is contained in:
@@ -89,7 +89,7 @@ public class VCardBuilder {
|
||||
private final boolean mIsJapaneseMobilePhone;
|
||||
private final boolean mOnlyOneNoteFieldIsAvailable;
|
||||
private final boolean mIsDoCoMo;
|
||||
private final boolean mUsesQuotedPrintable;
|
||||
private final boolean mShouldUseQuotedPrintable;
|
||||
private final boolean mUsesAndroidProperty;
|
||||
private final boolean mUsesDefactProperty;
|
||||
private final boolean mUsesUtf8;
|
||||
@@ -110,7 +110,7 @@ public class VCardBuilder {
|
||||
mVCardType = vcardType;
|
||||
|
||||
mIsV30 = VCardConfig.isV30(vcardType);
|
||||
mUsesQuotedPrintable = VCardConfig.usesQuotedPrintable(vcardType);
|
||||
mShouldUseQuotedPrintable = VCardConfig.shouldUseQuotedPrintable(vcardType);
|
||||
mIsDoCoMo = VCardConfig.isDoCoMo(vcardType);
|
||||
mIsJapaneseMobilePhone = VCardConfig.needsToConvertPhoneticString(vcardType);
|
||||
mOnlyOneNoteFieldIsAvailable = VCardConfig.onlyOneNoteFieldIsAvailable(vcardType);
|
||||
@@ -529,7 +529,7 @@ public class VCardBuilder {
|
||||
if (mUsesDefactProperty) {
|
||||
if (!TextUtils.isEmpty(phoneticGivenName)) {
|
||||
final boolean reallyUseQuotedPrintable =
|
||||
(mUsesQuotedPrintable &&
|
||||
(mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName));
|
||||
final String encodedPhoneticGivenName;
|
||||
if (reallyUseQuotedPrintable) {
|
||||
@@ -552,7 +552,7 @@ public class VCardBuilder {
|
||||
}
|
||||
if (!TextUtils.isEmpty(phoneticMiddleName)) {
|
||||
final boolean reallyUseQuotedPrintable =
|
||||
(mUsesQuotedPrintable &&
|
||||
(mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName));
|
||||
final String encodedPhoneticMiddleName;
|
||||
if (reallyUseQuotedPrintable) {
|
||||
@@ -575,7 +575,7 @@ public class VCardBuilder {
|
||||
}
|
||||
if (!TextUtils.isEmpty(phoneticFamilyName)) {
|
||||
final boolean reallyUseQuotedPrintable =
|
||||
(mUsesQuotedPrintable &&
|
||||
(mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName));
|
||||
final String encodedPhoneticFamilyName;
|
||||
if (reallyUseQuotedPrintable) {
|
||||
@@ -846,7 +846,7 @@ public class VCardBuilder {
|
||||
if (!appendCharset && !VCardUtils.containsOnlyPrintableAscii(data)) {
|
||||
appendCharset = true;
|
||||
}
|
||||
if (mUsesQuotedPrintable &&
|
||||
if (mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(data)) {
|
||||
reallyUseQuotedPrintable = true;
|
||||
break;
|
||||
@@ -1017,13 +1017,13 @@ public class VCardBuilder {
|
||||
final String orgline = orgBuilder.toString();
|
||||
appendLine(VCardConstants.PROPERTY_ORG, orgline,
|
||||
!VCardUtils.containsOnlyPrintableAscii(orgline),
|
||||
(mUsesQuotedPrintable &&
|
||||
(mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(orgline)));
|
||||
|
||||
if (!TextUtils.isEmpty(title)) {
|
||||
appendLine(VCardConstants.PROPERTY_TITLE, title,
|
||||
!VCardUtils.containsOnlyPrintableAscii(title),
|
||||
(mUsesQuotedPrintable &&
|
||||
(mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(title)));
|
||||
}
|
||||
}
|
||||
@@ -1094,7 +1094,7 @@ public class VCardBuilder {
|
||||
final boolean shouldAppendCharsetInfo =
|
||||
!VCardUtils.containsOnlyPrintableAscii(noteStr);
|
||||
final boolean reallyUseQuotedPrintable =
|
||||
(mUsesQuotedPrintable &&
|
||||
(mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr));
|
||||
appendLine(VCardConstants.PROPERTY_NOTE, noteStr,
|
||||
shouldAppendCharsetInfo, reallyUseQuotedPrintable);
|
||||
@@ -1105,7 +1105,7 @@ public class VCardBuilder {
|
||||
final boolean shouldAppendCharsetInfo =
|
||||
!VCardUtils.containsOnlyPrintableAscii(noteStr);
|
||||
final boolean reallyUseQuotedPrintable =
|
||||
(mUsesQuotedPrintable &&
|
||||
(mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr));
|
||||
appendLine(VCardConstants.PROPERTY_NOTE, noteStr,
|
||||
shouldAppendCharsetInfo, reallyUseQuotedPrintable);
|
||||
@@ -1541,9 +1541,10 @@ public class VCardBuilder {
|
||||
public void appendLineWithCharsetAndQPDetection(final String propertyName,
|
||||
final List<String> parameterList, final String rawValue) {
|
||||
final boolean needCharset =
|
||||
(mUsesQuotedPrintable && !VCardUtils.containsOnlyPrintableAscii(rawValue));
|
||||
!VCardUtils.containsOnlyPrintableAscii(rawValue);
|
||||
final boolean reallyUseQuotedPrintable =
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValue);
|
||||
(mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValue));
|
||||
appendLine(propertyName, parameterList,
|
||||
rawValue, needCharset, reallyUseQuotedPrintable);
|
||||
}
|
||||
@@ -1553,7 +1554,7 @@ public class VCardBuilder {
|
||||
boolean needCharset = false;
|
||||
boolean reallyUseQuotedPrintable = false;
|
||||
for (String rawValue : rawValueList) {
|
||||
if (!needCharset && mUsesQuotedPrintable &&
|
||||
if (!needCharset && mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyPrintableAscii(rawValue)) {
|
||||
needCharset = true;
|
||||
}
|
||||
|
||||
@@ -27,10 +27,7 @@ import java.util.Set;
|
||||
* but in VCardUtils.
|
||||
*/
|
||||
public class VCardConfig {
|
||||
private static final String LOG_TAG = "vcard.VCardConfig";
|
||||
|
||||
// TODO: may be better to make the instance of this available and stop using static methods and
|
||||
// one integer.
|
||||
private static final String LOG_TAG = "VCardConfig";
|
||||
|
||||
/* package */ static final int LOG_LEVEL_NONE = 0;
|
||||
/* package */ static final int LOG_LEVEL_PERFORMANCE_MEASUREMENT = 0x1;
|
||||
@@ -44,9 +41,6 @@ public class VCardConfig {
|
||||
// decode the unicode to the original charset. If not, this setting will cause some bug.
|
||||
public static final String DEFAULT_CHARSET = "iso-8859-1";
|
||||
|
||||
// TODO: make the other codes use this flag
|
||||
public static final boolean IGNORE_CASE_EXCEPT_VALUE = true;
|
||||
|
||||
public static final int FLAG_V21 = 0;
|
||||
public static final int FLAG_V30 = 1;
|
||||
|
||||
@@ -319,7 +313,7 @@ public class VCardConfig {
|
||||
FLAG_CONVERT_PHONETIC_NAME_STRINGS |
|
||||
FLAG_REFRAIN_QP_TO_PRIMARY_PROPERTIES);
|
||||
|
||||
public static final String VCARD_TYPE_V21_JAPANESE_MOBILE_STR = "v21_japanese_mobile";
|
||||
/* package */ static final String VCARD_TYPE_V21_JAPANESE_MOBILE_STR = "v21_japanese_mobile";
|
||||
|
||||
/**
|
||||
* <P>
|
||||
@@ -334,7 +328,7 @@ public class VCardConfig {
|
||||
public static final int VCARD_TYPE_DOCOMO =
|
||||
(VCARD_TYPE_V21_JAPANESE_MOBILE | FLAG_DOCOMO);
|
||||
|
||||
private static final String VCARD_TYPE_DOCOMO_STR = "docomo";
|
||||
/* package */ static final String VCARD_TYPE_DOCOMO_STR = "docomo";
|
||||
|
||||
public static int VCARD_TYPE_DEFAULT = VCARD_TYPE_V21_GENERIC_UTF8;
|
||||
|
||||
@@ -369,7 +363,6 @@ public class VCardConfig {
|
||||
if (sVCardTypeMap.containsKey(loweredKey)) {
|
||||
return sVCardTypeMap.get(loweredKey);
|
||||
} else {
|
||||
// XXX: should return the value indicating the input is invalid?
|
||||
Log.e(LOG_TAG, "Unknown vCard type String: \"" + vcardTypeString + "\"");
|
||||
return VCARD_TYPE_DEFAULT;
|
||||
}
|
||||
@@ -379,7 +372,7 @@ public class VCardConfig {
|
||||
return ((vcardType & FLAG_V30) != 0);
|
||||
}
|
||||
|
||||
public static boolean usesQuotedPrintable(final int vcardType) {
|
||||
public static boolean shouldUseQuotedPrintable(final int vcardType) {
|
||||
return !isV30(vcardType);
|
||||
}
|
||||
|
||||
@@ -408,7 +401,7 @@ public class VCardConfig {
|
||||
}
|
||||
|
||||
public static boolean refrainsQPToPrimaryProperties(final int vcardType) {
|
||||
return (!usesQuotedPrintable(vcardType) ||
|
||||
return (!shouldUseQuotedPrintable(vcardType) ||
|
||||
((vcardType & FLAG_REFRAIN_QP_TO_PRIMARY_PROPERTIES) != 0));
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ import android.util.Log;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -57,11 +58,11 @@ import java.util.Map;
|
||||
public class VCardEntry {
|
||||
private static final String LOG_TAG = "VCardEntry";
|
||||
|
||||
private final static int DEFAULT_ORGANIZATION_TYPE = Organization.TYPE_WORK;
|
||||
|
||||
private static final String ACCOUNT_TYPE_GOOGLE = "com.google";
|
||||
private static final String GOOGLE_MY_CONTACTS_GROUP = "System Group: My Contacts";
|
||||
|
||||
// Key: the name shown in VCard. e.g. "X-AIM", "X-ICQ"
|
||||
// Value: the result of {@link Contacts.ContactMethods#encodePredefinedImProtocol}
|
||||
private static final Map<String, Integer> sImMap = new HashMap<String, Integer>();
|
||||
|
||||
static {
|
||||
@@ -107,9 +108,6 @@ public class VCardEntry {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide only for testing
|
||||
*/
|
||||
static public class EmailData {
|
||||
public final int type;
|
||||
public final String data;
|
||||
@@ -154,17 +152,12 @@ public class VCardEntry {
|
||||
public final String region;
|
||||
public final String postalCode;
|
||||
public final String country;
|
||||
|
||||
public final int type;
|
||||
|
||||
// Used only when type variable is TYPE_CUSTOM.
|
||||
public final String label;
|
||||
|
||||
// isPrimary is changable only when there's no appropriate one existing in
|
||||
// the original VCard.
|
||||
public boolean isPrimary;
|
||||
public PostalData(int type, List<String> propValueList,
|
||||
String label, boolean isPrimary) {
|
||||
|
||||
public PostalData(final int type, final List<String> propValueList,
|
||||
final String label, boolean isPrimary) {
|
||||
this.type = type;
|
||||
dataArray = new String[ADDR_MAX_DATA_SIZE];
|
||||
|
||||
@@ -173,9 +166,9 @@ public class VCardEntry {
|
||||
size = ADDR_MAX_DATA_SIZE;
|
||||
}
|
||||
|
||||
// adr-value = 0*6(text-value ";") text-value
|
||||
// ; PO Box, Extended Address, Street, Locality, Region, Postal
|
||||
// ; Code, Country Name
|
||||
// adr-value = 0*6(text-value ";") text-value
|
||||
// ; PO Box, Extended Address, Street, Locality, Region, Postal
|
||||
// ; Code, Country Name
|
||||
//
|
||||
// Use Iterator assuming List may be LinkedList, though actually it is
|
||||
// always ArrayList in the current implementation.
|
||||
@@ -197,7 +190,6 @@ public class VCardEntry {
|
||||
this.region = dataArray[4];
|
||||
this.postalCode = dataArray[5];
|
||||
this.country = dataArray[6];
|
||||
|
||||
this.label = label;
|
||||
this.isPrimary = isPrimary;
|
||||
}
|
||||
@@ -207,15 +199,15 @@ public class VCardEntry {
|
||||
if (!(obj instanceof PostalData)) {
|
||||
return false;
|
||||
}
|
||||
PostalData postalData = (PostalData)obj;
|
||||
final PostalData postalData = (PostalData)obj;
|
||||
return (Arrays.equals(dataArray, postalData.dataArray) &&
|
||||
(type == postalData.type &&
|
||||
(type == StructuredPostal.TYPE_CUSTOM ?
|
||||
(label == postalData.label) : true)) &&
|
||||
(isPrimary == postalData.isPrimary));
|
||||
}
|
||||
|
||||
public String getFormattedAddress(int vcardType) {
|
||||
|
||||
public String getFormattedAddress(final int vcardType) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
boolean empty = true;
|
||||
if (VCardConfig.isJapaneseDevice(vcardType)) {
|
||||
@@ -225,9 +217,10 @@ public class VCardEntry {
|
||||
if (!TextUtils.isEmpty(addressPart)) {
|
||||
if (!empty) {
|
||||
builder.append(' ');
|
||||
} else {
|
||||
empty = false;
|
||||
}
|
||||
builder.append(addressPart);
|
||||
empty = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -236,9 +229,10 @@ public class VCardEntry {
|
||||
if (!TextUtils.isEmpty(addressPart)) {
|
||||
if (!empty) {
|
||||
builder.append(' ');
|
||||
} else {
|
||||
empty = false;
|
||||
}
|
||||
builder.append(addressPart);
|
||||
empty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,17 +246,16 @@ public class VCardEntry {
|
||||
type, label, isPrimary);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public class OrganizationData {
|
||||
public final int type;
|
||||
// non-final is Intended: we may change the values since this info is separated into
|
||||
// non-final is Intentional: we may change the values since this info is separated into
|
||||
// two parts in vCard: "ORG" + "TITLE".
|
||||
public String companyName;
|
||||
public String departmentName;
|
||||
public String titleName;
|
||||
// isPrimary is changable only when there's no appropriate one existing in
|
||||
// the original VCard.
|
||||
public boolean isPrimary;
|
||||
|
||||
public OrganizationData(int type,
|
||||
String companyName,
|
||||
String departmentName,
|
||||
@@ -302,16 +295,16 @@ public class VCardEntry {
|
||||
public final int type;
|
||||
public final String data;
|
||||
public final boolean isPrimary;
|
||||
|
||||
public ImData(int protocol, String customProtocol, int type,
|
||||
String data, boolean isPrimary) {
|
||||
|
||||
public ImData(final int protocol, final String customProtocol, final int type,
|
||||
final String data, final boolean isPrimary) {
|
||||
this.protocol = protocol;
|
||||
this.customProtocol = customProtocol;
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
this.isPrimary = isPrimary;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof ImData)) {
|
||||
@@ -324,7 +317,7 @@ public class VCardEntry {
|
||||
&& (data != null ? data.equals(imData.data) : (imData.data == null))
|
||||
&& isPrimary == imData.isPrimary);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
@@ -333,7 +326,7 @@ public class VCardEntry {
|
||||
}
|
||||
}
|
||||
|
||||
static public class PhotoData {
|
||||
public static class PhotoData {
|
||||
public static final String FORMAT_FLASH = "SWF";
|
||||
public final int type;
|
||||
public final String formatName; // used when type is not defined in ContactsContract.
|
||||
@@ -367,13 +360,13 @@ public class VCardEntry {
|
||||
}
|
||||
}
|
||||
|
||||
static /* package */ class Property {
|
||||
/* package */ static class Property {
|
||||
private String mPropertyName;
|
||||
private Map<String, Collection<String>> mParameterMap =
|
||||
new HashMap<String, Collection<String>>();
|
||||
private List<String> mPropertyValueList = new ArrayList<String>();
|
||||
private byte[] mPropertyBytes;
|
||||
|
||||
|
||||
public void setPropertyName(final String propertyName) {
|
||||
mPropertyName = propertyName;
|
||||
}
|
||||
@@ -464,18 +457,12 @@ public class VCardEntry {
|
||||
mAccount = account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a phone info to phoneList.
|
||||
* @param data phone number
|
||||
* @param type type col of content://contacts/phones
|
||||
* @param label lable col of content://contacts/phones
|
||||
*/
|
||||
private void addPhone(int type, String data, String label, boolean isPrimary){
|
||||
private void addPhone(int type, String data, String label, boolean isPrimary) {
|
||||
if (mPhoneList == null) {
|
||||
mPhoneList = new ArrayList<PhoneData>();
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String trimed = data.trim();
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final String trimed = data.trim();
|
||||
final String formattedNumber;
|
||||
if (type == Phone.TYPE_PAGER) {
|
||||
formattedNumber = trimed;
|
||||
@@ -532,13 +519,15 @@ public class VCardEntry {
|
||||
departmentName, titleName, isPrimary));
|
||||
}
|
||||
|
||||
private static final List<String> sEmptyList = new ArrayList<String>(0);
|
||||
|
||||
private static final List<String> sEmptyList =
|
||||
Collections.unmodifiableList(new ArrayList<String>(0));
|
||||
|
||||
/**
|
||||
* Set "ORG" related values to the appropriate data. If there's more than one
|
||||
* OrganizationData objects, this input data are attached to the last one which does not
|
||||
* have valid values (not including empty but only null). If there's no
|
||||
* OrganizationData object, a new OrganizationData is created, whose title is set to null.
|
||||
* {@link OrganizationData} objects, this input data are attached to the last one which
|
||||
* does not have valid values (not including empty but only null). If there's no
|
||||
* {@link OrganizationData} object, a new {@link OrganizationData} is created,
|
||||
* whose title is set to null.
|
||||
*/
|
||||
private void handleOrgValue(final int type, List<String> orgList, boolean isPrimary) {
|
||||
if (orgList == null) {
|
||||
@@ -596,8 +585,6 @@ public class VCardEntry {
|
||||
addNewOrganization(type, companyName, departmentName, null, isPrimary);
|
||||
}
|
||||
|
||||
private final static int DEFAULT_ORGANIZATION_TYPE = Organization.TYPE_WORK;
|
||||
|
||||
/**
|
||||
* Set "title" value to the appropriate data. If there's more than one
|
||||
* OrganizationData objects, this input is attached to the last one which does not
|
||||
@@ -658,25 +645,20 @@ public class VCardEntry {
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
// fallthrough
|
||||
case 5:
|
||||
mSuffix = elems.get(4);
|
||||
case 4:
|
||||
mPrefix = elems.get(3);
|
||||
case 3:
|
||||
mMiddleName = elems.get(2);
|
||||
case 2:
|
||||
mGivenName = elems.get(1);
|
||||
default:
|
||||
mFamilyName = elems.get(0);
|
||||
// fallthrough
|
||||
case 5: mSuffix = elems.get(4);
|
||||
case 4: mPrefix = elems.get(3);
|
||||
case 3: mMiddleName = elems.get(2);
|
||||
case 2: mGivenName = elems.get(1);
|
||||
default: mFamilyName = elems.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some Japanese mobile phones use this field for phonetic name,
|
||||
* since vCard 2.1 does not have "SORT-STRING" type.
|
||||
* Also, in some cases, the field has some ';'s in it.
|
||||
* Assume the ';' means the same meaning in N property
|
||||
* Note: Some Japanese mobile phones use this field for phonetic name,
|
||||
* since vCard 2.1 does not have "SORT-STRING" type.
|
||||
* Also, in some cases, the field has some ';'s in it.
|
||||
* Assume the ';' means the same meaning in N property
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
private void handlePhoneticNameFromSound(List<String> elems) {
|
||||
@@ -728,18 +710,15 @@ public class VCardEntry {
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
// fallthrough
|
||||
case 3:
|
||||
mPhoneticMiddleName = elems.get(2);
|
||||
case 2:
|
||||
mPhoneticGivenName = elems.get(1);
|
||||
default:
|
||||
mPhoneticFamilyName = elems.get(0);
|
||||
// fallthrough
|
||||
case 3: mPhoneticMiddleName = elems.get(2);
|
||||
case 2: mPhoneticGivenName = elems.get(1);
|
||||
default: mPhoneticFamilyName = elems.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void addProperty(Property property) {
|
||||
String propName = property.mPropertyName;
|
||||
public void addProperty(final Property property) {
|
||||
final String propName = property.mPropertyName;
|
||||
final Map<String, Collection<String>> paramMap = property.mParameterMap;
|
||||
final List<String> propValueList = property.mPropertyValueList;
|
||||
byte[] propBytes = property.mPropertyBytes;
|
||||
|
||||
@@ -19,26 +19,29 @@ import android.content.ContentResolver;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* EntryHandler implementation which commits the entry to ContentResolver.
|
||||
*
|
||||
* Note:
|
||||
* <P>
|
||||
* {@link VCardEntryHandler} implementation which commits the entry to ContentResolver.
|
||||
* </P>
|
||||
* <P>
|
||||
* Note:<BR />
|
||||
* Each vCard may contain big photo images encoded by BASE64,
|
||||
* If we store all vCard entries in memory, OutOfMemoryError may be thrown.
|
||||
* Thus, this class push each VCard entry into ContentResolver immediately.
|
||||
* </P>
|
||||
*/
|
||||
public class VCardEntryCommitter implements VCardEntryHandler {
|
||||
public static String LOG_TAG = "vcard.EntryComitter";
|
||||
public static String LOG_TAG = "VCardEntryComitter";
|
||||
|
||||
private ContentResolver mContentResolver;
|
||||
private final ContentResolver mContentResolver;
|
||||
private long mTimeToCommit;
|
||||
|
||||
|
||||
public VCardEntryCommitter(ContentResolver resolver) {
|
||||
mContentResolver = resolver;
|
||||
}
|
||||
|
||||
public void onStart() {
|
||||
}
|
||||
|
||||
|
||||
public void onEnd() {
|
||||
if (VCardConfig.showPerformanceLog()) {
|
||||
Log.d(LOG_TAG, String.format("time to commit entries: %d ms", mTimeToCommit));
|
||||
|
||||
@@ -32,69 +32,60 @@ import java.util.List;
|
||||
|
||||
public class VCardEntryConstructor implements VCardInterpreter {
|
||||
private static String LOG_TAG = "VCardEntryConstructor";
|
||||
|
||||
|
||||
/**
|
||||
* If there's no other information available, this class uses this charset for encoding
|
||||
* byte arrays.
|
||||
* byte arrays to String.
|
||||
*/
|
||||
static public String TARGET_CHARSET = "UTF-8";
|
||||
/* package */ static final String DEFAULT_CHARSET_FOR_DECODED_BYTES = "UTF-8";
|
||||
|
||||
private VCardEntry.Property mCurrentProperty = new VCardEntry.Property();
|
||||
private VCardEntry mCurrentContactStruct;
|
||||
private String mParamType;
|
||||
|
||||
/**
|
||||
* The charset using which VParser parses the text.
|
||||
* The charset using which {@link VCardInterpreter} parses the text.
|
||||
*/
|
||||
private String mSourceCharset;
|
||||
|
||||
private String mInputCharset;
|
||||
|
||||
/**
|
||||
* The charset with which byte array is encoded to String.
|
||||
*/
|
||||
private String mTargetCharset;
|
||||
private boolean mStrictLineBreakParsing;
|
||||
|
||||
final private String mCharsetForDecodedBytes;
|
||||
final private boolean mStrictLineBreakParsing;
|
||||
final private int mVCardType;
|
||||
final private Account mAccount;
|
||||
|
||||
// Just for testing.
|
||||
/** For measuring performance. */
|
||||
private long mTimePushIntoContentResolver;
|
||||
|
||||
private List<VCardEntryHandler> mEntryHandlers = new ArrayList<VCardEntryHandler>();
|
||||
|
||||
|
||||
final private List<VCardEntryHandler> mEntryHandlers = new ArrayList<VCardEntryHandler>();
|
||||
|
||||
public VCardEntryConstructor() {
|
||||
this(null, null, false, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8, null);
|
||||
}
|
||||
|
||||
public VCardEntryConstructor(int vcardType) {
|
||||
public VCardEntryConstructor(final int vcardType) {
|
||||
this(null, null, false, vcardType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public VCardEntryConstructor(String charset,
|
||||
boolean strictLineBreakParsing, int vcardType, Account account) {
|
||||
public VCardEntryConstructor(final String charset, final boolean strictLineBreakParsing,
|
||||
final int vcardType, final Account account) {
|
||||
this(null, charset, strictLineBreakParsing, vcardType, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public VCardEntryConstructor(String sourceCharset,
|
||||
String targetCharset,
|
||||
boolean strictLineBreakParsing,
|
||||
int vcardType,
|
||||
Account account) {
|
||||
if (sourceCharset != null) {
|
||||
mSourceCharset = sourceCharset;
|
||||
public VCardEntryConstructor(final String inputCharset, final String charsetForDetodedBytes,
|
||||
final boolean strictLineBreakParsing, final int vcardType,
|
||||
final Account account) {
|
||||
if (inputCharset != null) {
|
||||
mInputCharset = inputCharset;
|
||||
} else {
|
||||
mSourceCharset = VCardConfig.DEFAULT_CHARSET;
|
||||
mInputCharset = VCardConfig.DEFAULT_CHARSET;
|
||||
}
|
||||
if (targetCharset != null) {
|
||||
mTargetCharset = targetCharset;
|
||||
if (charsetForDetodedBytes != null) {
|
||||
mCharsetForDecodedBytes = charsetForDetodedBytes;
|
||||
} else {
|
||||
mTargetCharset = TARGET_CHARSET;
|
||||
mCharsetForDecodedBytes = DEFAULT_CHARSET_FOR_DECODED_BYTES;
|
||||
}
|
||||
mStrictLineBreakParsing = strictLineBreakParsing;
|
||||
mVCardType = vcardType;
|
||||
@@ -118,11 +109,7 @@ public class VCardEntryConstructor implements VCardInterpreter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the parse failed between startRecord() and endRecord().
|
||||
* Currently it happens only when the vCard format is 3.0.
|
||||
* (VCardVersionException is thrown by VCardParser_V21 and this object is reused by
|
||||
* VCardParser_V30. At that time, startRecord() is called twice before endRecord() is called.)
|
||||
* TODO: Should this be in VCardBuilder interface?
|
||||
* Called when the parse failed between {@link #startEntry()} and {@link #endEntry()}.
|
||||
*/
|
||||
public void clear() {
|
||||
mCurrentContactStruct = null;
|
||||
@@ -132,22 +119,14 @@ public class VCardEntryConstructor implements VCardInterpreter {
|
||||
/**
|
||||
* Assume that VCard is not nested. In other words, this code does not accept
|
||||
*/
|
||||
public void startRecord(String type) {
|
||||
// TODO: add the method clear() instead of using null for reducing GC?
|
||||
public void startEntry() {
|
||||
if (mCurrentContactStruct != null) {
|
||||
// This means startRecord() is called inside startRecord() - endRecord() block.
|
||||
// TODO: should throw some Exception
|
||||
Log.e(LOG_TAG, "Nested VCard code is not supported now.");
|
||||
}
|
||||
if (!type.equalsIgnoreCase("VCARD")) {
|
||||
// TODO: add test case for this
|
||||
Log.e(LOG_TAG, "This is not VCARD!");
|
||||
}
|
||||
|
||||
mCurrentContactStruct = new VCardEntry(mVCardType, mAccount);
|
||||
}
|
||||
|
||||
public void endRecord() {
|
||||
public void endEntry() {
|
||||
mCurrentContactStruct.consolidateFields();
|
||||
for (VCardEntryHandler entryHandler : mEntryHandlers) {
|
||||
entryHandler.onEntryCreated(mCurrentContactStruct);
|
||||
@@ -168,9 +147,8 @@ public class VCardEntryConstructor implements VCardInterpreter {
|
||||
}
|
||||
|
||||
public void propertyGroup(String group) {
|
||||
// ContactStruct does not support Group.
|
||||
}
|
||||
|
||||
|
||||
public void propertyParamType(String type) {
|
||||
if (mParamType != null) {
|
||||
Log.e(LOG_TAG, "propertyParamType() is called more than once " +
|
||||
@@ -187,26 +165,26 @@ public class VCardEntryConstructor implements VCardInterpreter {
|
||||
mCurrentProperty.addParameter(mParamType, value);
|
||||
mParamType = null;
|
||||
}
|
||||
|
||||
private String encodeString(String originalString, String targetCharset) {
|
||||
if (mSourceCharset.equalsIgnoreCase(targetCharset)) {
|
||||
|
||||
private String encodeString(String originalString, String charsetForDecodedBytes) {
|
||||
if (mInputCharset.equalsIgnoreCase(charsetForDecodedBytes)) {
|
||||
return originalString;
|
||||
}
|
||||
Charset charset = Charset.forName(mSourceCharset);
|
||||
Charset charset = Charset.forName(mInputCharset);
|
||||
ByteBuffer byteBuffer = charset.encode(originalString);
|
||||
// byteBuffer.array() "may" return byte array which is larger than
|
||||
// byteBuffer.remaining(). Here, we keep on the safe side.
|
||||
byte[] bytes = new byte[byteBuffer.remaining()];
|
||||
byteBuffer.get(bytes);
|
||||
try {
|
||||
return new String(bytes, targetCharset);
|
||||
return new String(bytes, charsetForDecodedBytes);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
|
||||
Log.e(LOG_TAG, "Failed to encode: charset=" + charsetForDecodedBytes);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String handleOneValue(String value, String targetCharset, String encoding) {
|
||||
|
||||
private String handleOneValue(String value, String charsetForDecodedBytes, String encoding) {
|
||||
if (encoding != null) {
|
||||
if (encoding.equals("BASE64") || encoding.equals("B")) {
|
||||
mCurrentProperty.setPropertyBytes(Base64.decodeBase64(value.getBytes()));
|
||||
@@ -272,9 +250,9 @@ public class VCardEntryConstructor implements VCardInterpreter {
|
||||
}
|
||||
byte[] bytes;
|
||||
try {
|
||||
bytes = builder.toString().getBytes(mSourceCharset);
|
||||
bytes = builder.toString().getBytes(mInputCharset);
|
||||
} catch (UnsupportedEncodingException e1) {
|
||||
Log.e(LOG_TAG, "Failed to encode: charset=" + mSourceCharset);
|
||||
Log.e(LOG_TAG, "Failed to encode: charset=" + mInputCharset);
|
||||
bytes = builder.toString().getBytes();
|
||||
}
|
||||
|
||||
@@ -286,38 +264,37 @@ public class VCardEntryConstructor implements VCardInterpreter {
|
||||
}
|
||||
|
||||
try {
|
||||
return new String(bytes, targetCharset);
|
||||
return new String(bytes, charsetForDecodedBytes);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
|
||||
Log.e(LOG_TAG, "Failed to encode: charset=" + charsetForDecodedBytes);
|
||||
return new String(bytes);
|
||||
}
|
||||
}
|
||||
// Unknown encoding. Fall back to default.
|
||||
}
|
||||
return encodeString(value, targetCharset);
|
||||
return encodeString(value, charsetForDecodedBytes);
|
||||
}
|
||||
|
||||
public void propertyValues(List<String> values) {
|
||||
if (values == null || values.size() == 0) {
|
||||
if (values == null || values.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Collection<String> charsetCollection = mCurrentProperty.getParameters("CHARSET");
|
||||
String charset =
|
||||
final String charset =
|
||||
((charsetCollection != null) ? charsetCollection.iterator().next() : null);
|
||||
String targetCharset = CharsetUtils.nameForDefaultVendor(charset);
|
||||
|
||||
final Collection<String> encodingCollection = mCurrentProperty.getParameters("ENCODING");
|
||||
String encoding =
|
||||
final String encoding =
|
||||
((encodingCollection != null) ? encodingCollection.iterator().next() : null);
|
||||
|
||||
if (targetCharset == null || targetCharset.length() == 0) {
|
||||
targetCharset = mTargetCharset;
|
||||
|
||||
String charsetForDecodedBytes = CharsetUtils.nameForDefaultVendor(charset);
|
||||
if (charsetForDecodedBytes == null || charsetForDecodedBytes.length() == 0) {
|
||||
charsetForDecodedBytes = mCharsetForDecodedBytes;
|
||||
}
|
||||
|
||||
for (String value : values) {
|
||||
|
||||
for (final String value : values) {
|
||||
mCurrentProperty.addToPropertyValueList(
|
||||
handleOneValue(value, targetCharset, encoding));
|
||||
handleOneValue(value, charsetForDecodedBytes, encoding));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ package android.pim.vcard;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The class which just counts the number of vCard entries in the specified input.
|
||||
*/
|
||||
public class VCardEntryCounter implements VCardInterpreter {
|
||||
private int mCount;
|
||||
|
||||
@@ -30,10 +33,10 @@ public class VCardEntryCounter implements VCardInterpreter {
|
||||
public void end() {
|
||||
}
|
||||
|
||||
public void startRecord(String type) {
|
||||
public void startEntry() {
|
||||
}
|
||||
|
||||
public void endRecord() {
|
||||
public void endEntry() {
|
||||
mCount++;
|
||||
}
|
||||
|
||||
@@ -57,4 +60,4 @@ public class VCardEntryCounter implements VCardInterpreter {
|
||||
|
||||
public void propertyValues(List<String> values) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
*/
|
||||
package android.pim.vcard;
|
||||
|
||||
/**
|
||||
* The interface called by {@link VCardEntryConstructor}. Useful when you don't want to
|
||||
* handle detailed information as what {@link VCardParser} provides via {@link VCardInterpreter}.
|
||||
*/
|
||||
public interface VCardEntryHandler {
|
||||
/**
|
||||
* Called when the parsing started.
|
||||
|
||||
@@ -17,48 +17,86 @@ package android.pim.vcard;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <P>
|
||||
* The interface which should be implemented by the classes which have to analyze each
|
||||
* vCard entry more minutely than {@link VCardEntry} class analysis.
|
||||
* </P>
|
||||
* <P>
|
||||
* Here, there are several terms specific to vCard (and this library).
|
||||
* </P>
|
||||
* <P>
|
||||
* The term "entry" is one vCard representation in the input, which should start with "BEGIN:VCARD"
|
||||
* and end with "END:VCARD".
|
||||
* </P>
|
||||
* <P>
|
||||
* The term "property" is one line in vCard entry, which consists of "group", "property name",
|
||||
* "parameter(param) names and values", and "property values".
|
||||
* </P>
|
||||
* <P>
|
||||
* e.g. group1.propName;paramName1=paramValue1;paramName2=paramValue2;propertyValue1;propertyValue2...
|
||||
* </P>
|
||||
*/
|
||||
public interface VCardInterpreter {
|
||||
/**
|
||||
* Called when vCard interpretation started.
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Called when vCard interpretation finished.
|
||||
*/
|
||||
void end();
|
||||
|
||||
/**
|
||||
* BEGIN:VCARD
|
||||
* Called when parsing one vCard entry started.
|
||||
* More specifically, this method is called when "BEGIN:VCARD" is read.
|
||||
*/
|
||||
void startRecord(String type);
|
||||
void startEntry();
|
||||
|
||||
/** END:VCARD */
|
||||
void endRecord();
|
||||
/**
|
||||
* Called when parsing one vCard entry ended.
|
||||
* More specifically, this method is called when "END:VCARD" is read.
|
||||
* Note that {@link #startEntry()} may be called since
|
||||
* vCard (especially 2.1) allows nested vCard.
|
||||
*/
|
||||
void endEntry();
|
||||
|
||||
/**
|
||||
* Called when reading one property started.
|
||||
*/
|
||||
void startProperty();
|
||||
|
||||
/**
|
||||
* Called when reading one property ended.
|
||||
*/
|
||||
void endProperty();
|
||||
|
||||
/**
|
||||
* @param group
|
||||
* @param group A group name. This method may be called more than once or may not be
|
||||
* called at all, depending on how many gruoups are appended to the property.
|
||||
*/
|
||||
void propertyGroup(String group);
|
||||
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* N <br>
|
||||
* N
|
||||
* @param name A property name like "N", "FN", "ADR", etc.
|
||||
*/
|
||||
void propertyName(String name);
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* LANGUAGE \ ENCODING <br>
|
||||
* ;LANGUage= \ ;ENCODING=
|
||||
* @param type A parameter name like "ENCODING", "CHARSET", etc.
|
||||
*/
|
||||
void propertyParamType(String type);
|
||||
|
||||
/**
|
||||
* @param value
|
||||
* FR-EN \ GBK <br>
|
||||
* FR-EN \ GBK
|
||||
* @param value A parameter value. This method may be called without
|
||||
* {@link #propertyParamType(String)} being called (when the vCard is vCard 2.1).
|
||||
*/
|
||||
void propertyParamValue(String value);
|
||||
|
||||
/**
|
||||
* @param values List of property values. The size of values would be 1 unless
|
||||
* coressponding property name is "N", "ADR", or "ORG".
|
||||
*/
|
||||
void propertyValues(List<String> values);
|
||||
}
|
||||
|
||||
@@ -18,81 +18,84 @@ package android.pim.vcard;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class VCardInterPreterCollection implements VCardInterpreter {
|
||||
/**
|
||||
* The {@link VCardInterpreter} implementation which aggregates more than one
|
||||
* {@link VCardInterpreter} objects and make a user object treat them as one
|
||||
* {@link VCardInterpreter} object.
|
||||
*/
|
||||
public class VCardInterpreterCollection implements VCardInterpreter {
|
||||
private final Collection<VCardInterpreter> mInterpreterCollection;
|
||||
|
||||
public VCardInterpreterCollection(Collection<VCardInterpreter> interpreterCollection) {
|
||||
mInterpreterCollection = interpreterCollection;
|
||||
}
|
||||
|
||||
private final Collection<VCardInterpreter> mVCardBuilderCollection;
|
||||
|
||||
public VCardInterPreterCollection(Collection<VCardInterpreter> vBuilderCollection) {
|
||||
mVCardBuilderCollection = vBuilderCollection;
|
||||
}
|
||||
|
||||
public Collection<VCardInterpreter> getCollection() {
|
||||
return mVCardBuilderCollection;
|
||||
return mInterpreterCollection;
|
||||
}
|
||||
|
||||
|
||||
public void start() {
|
||||
for (VCardInterpreter builder : mVCardBuilderCollection) {
|
||||
for (VCardInterpreter builder : mInterpreterCollection) {
|
||||
builder.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void end() {
|
||||
for (VCardInterpreter builder : mVCardBuilderCollection) {
|
||||
for (VCardInterpreter builder : mInterpreterCollection) {
|
||||
builder.end();
|
||||
}
|
||||
}
|
||||
|
||||
public void startRecord(String type) {
|
||||
for (VCardInterpreter builder : mVCardBuilderCollection) {
|
||||
builder.startRecord(type);
|
||||
public void startEntry() {
|
||||
for (VCardInterpreter builder : mInterpreterCollection) {
|
||||
builder.startEntry();
|
||||
}
|
||||
}
|
||||
|
||||
public void endRecord() {
|
||||
for (VCardInterpreter builder : mVCardBuilderCollection) {
|
||||
builder.endRecord();
|
||||
|
||||
public void endEntry() {
|
||||
for (VCardInterpreter builder : mInterpreterCollection) {
|
||||
builder.endEntry();
|
||||
}
|
||||
}
|
||||
|
||||
public void startProperty() {
|
||||
for (VCardInterpreter builder : mVCardBuilderCollection) {
|
||||
for (VCardInterpreter builder : mInterpreterCollection) {
|
||||
builder.startProperty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void endProperty() {
|
||||
for (VCardInterpreter builder : mVCardBuilderCollection) {
|
||||
for (VCardInterpreter builder : mInterpreterCollection) {
|
||||
builder.endProperty();
|
||||
}
|
||||
}
|
||||
|
||||
public void propertyGroup(String group) {
|
||||
for (VCardInterpreter builder : mVCardBuilderCollection) {
|
||||
for (VCardInterpreter builder : mInterpreterCollection) {
|
||||
builder.propertyGroup(group);
|
||||
}
|
||||
}
|
||||
|
||||
public void propertyName(String name) {
|
||||
for (VCardInterpreter builder : mVCardBuilderCollection) {
|
||||
for (VCardInterpreter builder : mInterpreterCollection) {
|
||||
builder.propertyName(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void propertyParamType(String type) {
|
||||
for (VCardInterpreter builder : mVCardBuilderCollection) {
|
||||
for (VCardInterpreter builder : mInterpreterCollection) {
|
||||
builder.propertyParamType(type);
|
||||
}
|
||||
}
|
||||
|
||||
public void propertyParamValue(String value) {
|
||||
for (VCardInterpreter builder : mVCardBuilderCollection) {
|
||||
for (VCardInterpreter builder : mInterpreterCollection) {
|
||||
builder.propertyParamValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void propertyValues(List<String> values) {
|
||||
for (VCardInterpreter builder : mVCardBuilderCollection) {
|
||||
for (VCardInterpreter builder : mInterpreterCollection) {
|
||||
builder.propertyValues(values);
|
||||
}
|
||||
}
|
||||
@@ -39,43 +39,48 @@ public abstract class VCardParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* <P>
|
||||
* Parses the given stream and send the VCard data into VCardBuilderBase object.
|
||||
*
|
||||
* </P.
|
||||
* <P>
|
||||
* Note that vCard 2.1 specification allows "CHARSET" parameter, and some career sets
|
||||
* local encoding to it. For example, Japanese phone career uses Shift_JIS, which is
|
||||
* formally allowed in VCard 2.1, but not recommended in VCard 3.0. In VCard 2.1,
|
||||
* In some exreme case, some VCard may have different charsets in one VCard (though
|
||||
* we do not see any device which emits such kind of malicious data)
|
||||
*
|
||||
* </P>
|
||||
* <P>
|
||||
* In order to avoid "misunderstanding" charset as much as possible, this method
|
||||
* use "ISO-8859-1" for reading the stream. When charset is specified in some property
|
||||
* (with "CHARSET=..." parameter), the string is decoded to raw bytes and encoded to
|
||||
* the charset. This method assumes that "ISO-8859-1" has 1 to 1 mapping in all 8bit
|
||||
* characters, which is not completely sure. In some cases, this "decoding-encoding"
|
||||
* scheme may fail. To avoid the case,
|
||||
*
|
||||
* We recommend you to use VCardSourceDetector and detect which kind of source the
|
||||
* </P>
|
||||
* <P>
|
||||
* We recommend you to use {@link VCardSourceDetector} and detect which kind of source the
|
||||
* VCard comes from and explicitly specify a charset using the result.
|
||||
*
|
||||
* </P>
|
||||
*
|
||||
* @param is The source to parse.
|
||||
* @param builder The VCardBuilderBase object which used to construct data. If you want to
|
||||
* include multiple VCardBuilderBase objects in this field, consider using
|
||||
* {#link VCardBuilderCollection} class.
|
||||
* @param interepreter A {@link VCardInterpreter} object which used to construct data.
|
||||
* @return Returns true for success. Otherwise returns false.
|
||||
* @throws IOException, VCardException
|
||||
*/
|
||||
public abstract boolean parse(InputStream is, VCardInterpreter builder)
|
||||
public abstract boolean parse(InputStream is, VCardInterpreter interepreter)
|
||||
throws IOException, VCardException;
|
||||
|
||||
/**
|
||||
* <P>
|
||||
* The method variants which accept charset.
|
||||
*
|
||||
* </P>
|
||||
* <P>
|
||||
* RFC 2426 "recommends" (not forces) to use UTF-8, so it may be OK to use
|
||||
* UTF-8 as an encoding when parsing vCard 3.0. But note that some Japanese
|
||||
* phone uses Shift_JIS as a charset (e.g. W61SH), and another uses
|
||||
* "CHARSET=SHIFT_JIS", which is explicitly prohibited in vCard 3.0 specification
|
||||
* (e.g. W53K).
|
||||
*
|
||||
* "CHARSET=SHIFT_JIS", which is explicitly prohibited in vCard 3.0 specification (e.g. W53K).
|
||||
* </P>
|
||||
*
|
||||
* @param is The source to parse.
|
||||
* @param charset Charset to be used.
|
||||
* @param builder The VCardBuilderBase object.
|
||||
@@ -87,8 +92,6 @@ public abstract class VCardParser {
|
||||
|
||||
/**
|
||||
* The method variants which tells this object the operation is already canceled.
|
||||
* XXX: Is this really necessary?
|
||||
* @hide
|
||||
*/
|
||||
public abstract void parse(InputStream is, String charset,
|
||||
VCardInterpreter builder, boolean canceled)
|
||||
|
||||
@@ -31,13 +31,14 @@ import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class is used to parse vcard. Please refer to vCard Specification 2.1.
|
||||
* This class is used to parse vCard. Please refer to vCard Specification 2.1 for more detail.
|
||||
*/
|
||||
public class VCardParser_V21 extends VCardParser {
|
||||
private static final String LOG_TAG = "vcard.VCardParser_V21";
|
||||
|
||||
private static final String LOG_TAG = "VCardParser_V21";
|
||||
|
||||
/** Store the known-type */
|
||||
private static final HashSet<String> sKnownTypeSet = new HashSet<String>(
|
||||
Arrays.asList("DOM", "INTL", "POSTAL", "PARCEL", "HOME", "WORK",
|
||||
@@ -52,7 +53,7 @@ public class VCardParser_V21 extends VCardParser {
|
||||
/** Store the known-value */
|
||||
private static final HashSet<String> sKnownValueSet = new HashSet<String>(
|
||||
Arrays.asList("INLINE", "URL", "CONTENT-ID", "CID"));
|
||||
|
||||
|
||||
/** Store the property names available in vCard 2.1 */
|
||||
private static final HashSet<String> sAvailablePropertyNameSetV21 =
|
||||
new HashSet<String>(Arrays.asList(
|
||||
@@ -82,7 +83,7 @@ public class VCardParser_V21 extends VCardParser {
|
||||
|
||||
protected final String sDefaultEncoding = "8BIT";
|
||||
|
||||
// Should not directly read a line from this. Use getLine() instead.
|
||||
// Should not directly read a line from this object. Use getLine() instead.
|
||||
protected BufferedReader mReader;
|
||||
|
||||
// In some cases, vCard is nested. Currently, we only consider the most interior vCard data.
|
||||
@@ -91,16 +92,16 @@ public class VCardParser_V21 extends VCardParser {
|
||||
|
||||
// In order to reduce warning message as much as possible, we hold the value which made Logger
|
||||
// emit a warning message.
|
||||
protected HashSet<String> mUnknownTypeMap = new HashSet<String>();
|
||||
protected HashSet<String> mUnknownValueMap = new HashSet<String>();
|
||||
protected Set<String> mUnknownTypeMap = new HashSet<String>();
|
||||
protected Set<String> mUnknownValueMap = new HashSet<String>();
|
||||
|
||||
// It seems Windows Mobile 6.5 uses "AGENT" property with completely wrong usage.
|
||||
// We should just ignore just one line.
|
||||
// e.g.
|
||||
// "AGENT;CHARSET=SHIFT_JIS:some text"
|
||||
private boolean mIgnoreAgentLine = false;
|
||||
private boolean mIgnoreInvalidAgentLine = false;
|
||||
|
||||
// Just for debugging
|
||||
// For measuring performance.
|
||||
private long mTimeTotal;
|
||||
private long mTimeReadStartRecord;
|
||||
private long mTimeReadEndRecord;
|
||||
@@ -114,9 +115,6 @@ public class VCardParser_V21 extends VCardParser {
|
||||
private long mTimeHandleQuotedPrintable;
|
||||
private long mTimeHandleBase64;
|
||||
|
||||
/**
|
||||
* Create a new VCard parser.
|
||||
*/
|
||||
public VCardParser_V21() {
|
||||
this(null, PARSER_MODE_DEFAULT);
|
||||
}
|
||||
@@ -139,17 +137,18 @@ public class VCardParser_V21 extends VCardParser {
|
||||
if (type == VCardSourceDetector.TYPE_FOMA) {
|
||||
mNestCount = 1;
|
||||
} else if (type == VCardSourceDetector.TYPE_JAPANESE_MOBILE_PHONE) {
|
||||
mIgnoreAgentLine = true;
|
||||
mIgnoreInvalidAgentLine = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (parserMode == PARSER_MODE_SCAN) {
|
||||
mIgnoreAgentLine = true;
|
||||
mIgnoreInvalidAgentLine = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the file at the given position
|
||||
* Parses the file at the given position.
|
||||
*
|
||||
* vcard_file = [wsls] vcard [wsls]
|
||||
*/
|
||||
protected void parseVCardFile() throws IOException, VCardException {
|
||||
@@ -225,11 +224,11 @@ public class VCardParser_V21 extends VCardParser {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF
|
||||
* items *CRLF
|
||||
* "END" [ws] ":" [ws] "VCARD"
|
||||
* vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF
|
||||
* items *CRLF
|
||||
* "END" [ws] ":" [ws] "VCARD"
|
||||
*/
|
||||
private boolean parseOneVCard(boolean firstReading) throws IOException, VCardException {
|
||||
boolean allowGarbage = false;
|
||||
@@ -250,7 +249,7 @@ public class VCardParser_V21 extends VCardParser {
|
||||
long start;
|
||||
if (mBuilder != null) {
|
||||
start = System.currentTimeMillis();
|
||||
mBuilder.startRecord("VCARD");
|
||||
mBuilder.startEntry();
|
||||
mTimeReadStartRecord += System.currentTimeMillis() - start;
|
||||
}
|
||||
start = System.currentTimeMillis();
|
||||
@@ -259,7 +258,7 @@ public class VCardParser_V21 extends VCardParser {
|
||||
readEndVCard(true, false);
|
||||
if (mBuilder != null) {
|
||||
start = System.currentTimeMillis();
|
||||
mBuilder.endRecord();
|
||||
mBuilder.endEntry();
|
||||
mTimeReadEndRecord += System.currentTimeMillis() - start;
|
||||
}
|
||||
return true;
|
||||
@@ -270,8 +269,7 @@ public class VCardParser_V21 extends VCardParser {
|
||||
* @throws IOException
|
||||
* @throws VCardException
|
||||
*/
|
||||
protected boolean readBeginVCard(boolean allowGarbage)
|
||||
throws IOException, VCardException {
|
||||
protected boolean readBeginVCard(boolean allowGarbage) throws IOException, VCardException {
|
||||
String line;
|
||||
do {
|
||||
while (true) {
|
||||
@@ -286,8 +284,9 @@ public class VCardParser_V21 extends VCardParser {
|
||||
int length = strArray.length;
|
||||
|
||||
// Though vCard 2.1/3.0 specification does not allow lower cases,
|
||||
// some data may have them, so we allow it (Actually, previous code
|
||||
// had explicitly allowed "BEGIN:vCard" though there's no example).
|
||||
// vCard file emitted by some external vCard expoter have such invalid Strings.
|
||||
// So we allow it.
|
||||
// e.g. BEGIN:vCard
|
||||
if (length == 2 &&
|
||||
strArray[0].trim().equalsIgnoreCase("BEGIN") &&
|
||||
strArray[1].trim().equalsIgnoreCase("VCARD")) {
|
||||
@@ -310,7 +309,7 @@ public class VCardParser_V21 extends VCardParser {
|
||||
/**
|
||||
* The arguments useCache and allowGarbase are usually true and false accordingly when
|
||||
* this function is called outside this function itself.
|
||||
*
|
||||
*
|
||||
* @param useCache When true, line is obtained from mPreviousline. Otherwise, getLine()
|
||||
* is used.
|
||||
* @param allowGarbage When true, ignore non "END:VCARD" line.
|
||||
@@ -353,7 +352,6 @@ public class VCardParser_V21 extends VCardParser {
|
||||
* / item
|
||||
*/
|
||||
protected void parseItems() throws IOException, VCardException {
|
||||
/* items *CRLF item / item */
|
||||
boolean ended = false;
|
||||
|
||||
if (mBuilder != null) {
|
||||
@@ -399,7 +397,7 @@ public class VCardParser_V21 extends VCardParser {
|
||||
protected boolean parseItem() throws IOException, VCardException {
|
||||
mEncoding = sDefaultEncoding;
|
||||
|
||||
String line = getNonEmptyLine();
|
||||
final String line = getNonEmptyLine();
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
String[] propertyNameAndValue = separateLineAndHandleGroup(line);
|
||||
@@ -441,23 +439,22 @@ public class VCardParser_V21 extends VCardParser {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new VCardException("Unknown property name: \"" +
|
||||
propertyName + "\"");
|
||||
throw new VCardException("Unknown property name: \"" + propertyName + "\"");
|
||||
}
|
||||
|
||||
static private final int STATE_GROUP_OR_PROPNAME = 0;
|
||||
static private final int STATE_PARAMS = 1;
|
||||
// vCard 3.1 specification allows double-quoted param-value, while vCard 2.1 does not.
|
||||
// vCard 3.0 specification allows double-quoted param-value, while vCard 2.1 does not.
|
||||
// This is just for safety.
|
||||
static private final int STATE_PARAMS_IN_DQUOTE = 2;
|
||||
|
||||
|
||||
protected String[] separateLineAndHandleGroup(String line) throws VCardException {
|
||||
int length = line.length();
|
||||
int state = STATE_GROUP_OR_PROPNAME;
|
||||
int nameIndex = 0;
|
||||
|
||||
String[] propertyNameAndValue = new String[2];
|
||||
final String[] propertyNameAndValue = new String[2];
|
||||
|
||||
final int length = line.length();
|
||||
if (length > 0 && line.charAt(0) == '#') {
|
||||
throw new VCardInvalidCommentLineException();
|
||||
}
|
||||
@@ -465,82 +462,84 @@ public class VCardParser_V21 extends VCardParser {
|
||||
for (int i = 0; i < length; i++) {
|
||||
char ch = line.charAt(i);
|
||||
switch (state) {
|
||||
case STATE_GROUP_OR_PROPNAME:
|
||||
if (ch == ':') {
|
||||
String propertyName = line.substring(nameIndex, i);
|
||||
if (propertyName.equalsIgnoreCase("END")) {
|
||||
mPreviousLine = line;
|
||||
return null;
|
||||
case STATE_GROUP_OR_PROPNAME: {
|
||||
if (ch == ':') {
|
||||
final String propertyName = line.substring(nameIndex, i);
|
||||
if (propertyName.equalsIgnoreCase("END")) {
|
||||
mPreviousLine = line;
|
||||
return null;
|
||||
}
|
||||
if (mBuilder != null) {
|
||||
mBuilder.propertyName(propertyName);
|
||||
}
|
||||
propertyNameAndValue[0] = propertyName;
|
||||
if (i < length - 1) {
|
||||
propertyNameAndValue[1] = line.substring(i + 1);
|
||||
} else {
|
||||
propertyNameAndValue[1] = "";
|
||||
}
|
||||
return propertyNameAndValue;
|
||||
} else if (ch == '.') {
|
||||
String groupName = line.substring(nameIndex, i);
|
||||
if (mBuilder != null) {
|
||||
mBuilder.propertyGroup(groupName);
|
||||
}
|
||||
nameIndex = i + 1;
|
||||
} else if (ch == ';') {
|
||||
String propertyName = line.substring(nameIndex, i);
|
||||
if (propertyName.equalsIgnoreCase("END")) {
|
||||
mPreviousLine = line;
|
||||
return null;
|
||||
}
|
||||
if (mBuilder != null) {
|
||||
mBuilder.propertyName(propertyName);
|
||||
}
|
||||
propertyNameAndValue[0] = propertyName;
|
||||
nameIndex = i + 1;
|
||||
state = STATE_PARAMS;
|
||||
}
|
||||
if (mBuilder != null) {
|
||||
mBuilder.propertyName(propertyName);
|
||||
}
|
||||
propertyNameAndValue[0] = propertyName;
|
||||
if (i < length - 1) {
|
||||
propertyNameAndValue[1] = line.substring(i + 1);
|
||||
} else {
|
||||
propertyNameAndValue[1] = "";
|
||||
}
|
||||
return propertyNameAndValue;
|
||||
} else if (ch == '.') {
|
||||
String groupName = line.substring(nameIndex, i);
|
||||
if (mBuilder != null) {
|
||||
mBuilder.propertyGroup(groupName);
|
||||
}
|
||||
nameIndex = i + 1;
|
||||
} else if (ch == ';') {
|
||||
String propertyName = line.substring(nameIndex, i);
|
||||
if (propertyName.equalsIgnoreCase("END")) {
|
||||
mPreviousLine = line;
|
||||
return null;
|
||||
}
|
||||
if (mBuilder != null) {
|
||||
mBuilder.propertyName(propertyName);
|
||||
}
|
||||
propertyNameAndValue[0] = propertyName;
|
||||
nameIndex = i + 1;
|
||||
state = STATE_PARAMS;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case STATE_PARAMS:
|
||||
if (ch == '"') {
|
||||
state = STATE_PARAMS_IN_DQUOTE;
|
||||
} else if (ch == ';') {
|
||||
handleParams(line.substring(nameIndex, i));
|
||||
nameIndex = i + 1;
|
||||
} else if (ch == ':') {
|
||||
handleParams(line.substring(nameIndex, i));
|
||||
if (i < length - 1) {
|
||||
propertyNameAndValue[1] = line.substring(i + 1);
|
||||
} else {
|
||||
propertyNameAndValue[1] = "";
|
||||
case STATE_PARAMS: {
|
||||
if (ch == '"') {
|
||||
state = STATE_PARAMS_IN_DQUOTE;
|
||||
} else if (ch == ';') {
|
||||
handleParams(line.substring(nameIndex, i));
|
||||
nameIndex = i + 1;
|
||||
} else if (ch == ':') {
|
||||
handleParams(line.substring(nameIndex, i));
|
||||
if (i < length - 1) {
|
||||
propertyNameAndValue[1] = line.substring(i + 1);
|
||||
} else {
|
||||
propertyNameAndValue[1] = "";
|
||||
}
|
||||
return propertyNameAndValue;
|
||||
}
|
||||
return propertyNameAndValue;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case STATE_PARAMS_IN_DQUOTE:
|
||||
if (ch == '"') {
|
||||
state = STATE_PARAMS;
|
||||
case STATE_PARAMS_IN_DQUOTE: {
|
||||
if (ch == '"') {
|
||||
state = STATE_PARAMS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new VCardInvalidLineException("Invalid line: \"" + line + "\"");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* params = ";" [ws] paramlist
|
||||
* paramlist = paramlist [ws] ";" [ws] param
|
||||
* / param
|
||||
* param = "TYPE" [ws] "=" [ws] ptypeval
|
||||
* / "VALUE" [ws] "=" [ws] pvalueval
|
||||
* / "ENCODING" [ws] "=" [ws] pencodingval
|
||||
* / "CHARSET" [ws] "=" [ws] charsetval
|
||||
* / "LANGUAGE" [ws] "=" [ws] langval
|
||||
* / "X-" word [ws] "=" [ws] word
|
||||
* / knowntype
|
||||
* params = ";" [ws] paramlist
|
||||
* paramlist = paramlist [ws] ";" [ws] param
|
||||
* / param
|
||||
* param = "TYPE" [ws] "=" [ws] ptypeval
|
||||
* / "VALUE" [ws] "=" [ws] pvalueval
|
||||
* / "ENCODING" [ws] "=" [ws] pencodingval
|
||||
* / "CHARSET" [ws] "=" [ws] charsetval
|
||||
* / "LANGUAGE" [ws] "=" [ws] langval
|
||||
* / "X-" word [ws] "=" [ws] word
|
||||
* / knowntype
|
||||
*/
|
||||
protected void handleParams(String params) throws VCardException {
|
||||
String[] strArray = params.split("=", 2);
|
||||
@@ -624,8 +623,8 @@ public class VCardParser_V21 extends VCardParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* vCard specification only allows us-ascii and iso-8859-xxx (See RFC 1521),
|
||||
* but some vCard contains other charset, so we allow them.
|
||||
* vCard 2.1 specification only allows us-ascii and iso-8859-xxx (See RFC 1521),
|
||||
* but today's vCard often contains other charset, so we allow them.
|
||||
*/
|
||||
protected void handleCharset(String charsetval) {
|
||||
if (mBuilder != null) {
|
||||
@@ -633,7 +632,7 @@ public class VCardParser_V21 extends VCardParser {
|
||||
mBuilder.propertyParamValue(charsetval);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See also Section 7.1 of RFC 1521
|
||||
*/
|
||||
@@ -671,12 +670,12 @@ public class VCardParser_V21 extends VCardParser {
|
||||
mBuilder.propertyParamValue(paramValue);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handlePropertyValue(String propertyName, String propertyValue) throws
|
||||
IOException, VCardException {
|
||||
|
||||
protected void handlePropertyValue(String propertyName, String propertyValue)
|
||||
throws IOException, VCardException {
|
||||
if (mEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
|
||||
long start = System.currentTimeMillis();
|
||||
String result = getQuotedPrintable(propertyValue);
|
||||
final long start = System.currentTimeMillis();
|
||||
final String result = getQuotedPrintable(propertyValue);
|
||||
if (mBuilder != null) {
|
||||
ArrayList<String> v = new ArrayList<String>();
|
||||
v.add(result);
|
||||
@@ -685,11 +684,11 @@ public class VCardParser_V21 extends VCardParser {
|
||||
mTimeHandleQuotedPrintable += System.currentTimeMillis() - start;
|
||||
} else if (mEncoding.equalsIgnoreCase("BASE64") ||
|
||||
mEncoding.equalsIgnoreCase("B")) {
|
||||
long start = System.currentTimeMillis();
|
||||
final long start = System.currentTimeMillis();
|
||||
// It is very rare, but some BASE64 data may be so big that
|
||||
// OutOfMemoryError occurs. To ignore such cases, use try-catch.
|
||||
try {
|
||||
String result = getBase64(propertyValue);
|
||||
final String result = getBase64(propertyValue);
|
||||
if (mBuilder != null) {
|
||||
ArrayList<String> v = new ArrayList<String>();
|
||||
v.add(result);
|
||||
@@ -709,7 +708,7 @@ public class VCardParser_V21 extends VCardParser {
|
||||
Log.w(LOG_TAG, "The encoding unsupported by vCard spec: \"" + mEncoding + "\".");
|
||||
}
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
final long start = System.currentTimeMillis();
|
||||
if (mBuilder != null) {
|
||||
ArrayList<String> v = new ArrayList<String>();
|
||||
v.add(maybeUnescapeText(propertyValue));
|
||||
@@ -820,16 +819,15 @@ public class VCardParser_V21 extends VCardParser {
|
||||
|
||||
/**
|
||||
* vCard 2.1 specifies AGENT allows one vcard entry. It is not encoded at all.
|
||||
*
|
||||
* item = ...
|
||||
* / [groups "."] "AGENT"
|
||||
* [params] ":" vcard CRLF
|
||||
* vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF
|
||||
* items *CRLF "END" [ws] ":" [ws] "VCARD"
|
||||
*
|
||||
*
|
||||
* item = ...
|
||||
* / [groups "."] "AGENT"
|
||||
* [params] ":" vcard CRLF
|
||||
* vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF
|
||||
* items *CRLF "END" [ws] ":" [ws] "VCARD"
|
||||
*/
|
||||
protected void handleAgent(final String propertyValue) throws VCardException {
|
||||
if (mIgnoreAgentLine) {
|
||||
if (mIgnoreInvalidAgentLine && !propertyValue.toUpperCase().contains("BEGIN:VCARD")) {
|
||||
return;
|
||||
} else {
|
||||
throw new VCardAgentNotSupportedException("AGENT Property is not supported now.");
|
||||
|
||||
@@ -23,12 +23,12 @@ import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* This class is used to parse vcard3.0. <br>
|
||||
* Please refer to vCard Specification 3.0 (http://tools.ietf.org/html/rfc2426)
|
||||
* The class used to parse vCard 3.0.
|
||||
* Please refer to vCard Specification 3.0 (http://tools.ietf.org/html/rfc2426).
|
||||
*/
|
||||
public class VCardParser_V30 extends VCardParser_V21 {
|
||||
private static final String LOG_TAG = "vcard.VCardParser_V30";
|
||||
|
||||
private static final String LOG_TAG = "VCardParser_V30";
|
||||
|
||||
private static final HashSet<String> sAcceptablePropsWithParam = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"BEGIN", "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND",
|
||||
@@ -185,17 +185,17 @@ public class VCardParser_V30 extends VCardParser_V21 {
|
||||
|
||||
|
||||
/**
|
||||
* vcard = [group "."] "BEGIN" ":" "VCARD" 1*CRLF
|
||||
* 1*(contentline)
|
||||
* vcard = [group "."] "BEGIN" ":" "VCARD" 1 * CRLF
|
||||
* 1 * (contentline)
|
||||
* ;A vCard object MUST include the VERSION, FN and N types.
|
||||
* [group "."] "END" ":" "VCARD" 1*CRLF
|
||||
* [group "."] "END" ":" "VCARD" 1 * CRLF
|
||||
*/
|
||||
@Override
|
||||
protected boolean readBeginVCard(boolean allowGarbage) throws IOException, VCardException {
|
||||
// TODO: vCard 3.0 supports group.
|
||||
return super.readBeginVCard(allowGarbage);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void readEndVCard(boolean useCache, boolean allowGarbage)
|
||||
throws IOException, VCardException {
|
||||
@@ -222,14 +222,9 @@ public class VCardParser_V30 extends VCardParser_V21 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void handleAnyParam(String paramName, String paramValue) {
|
||||
// vCard 3.0 accept comma-separated multiple values, but
|
||||
// current PropertyNode does not accept it.
|
||||
// For now, we do not split the values.
|
||||
//
|
||||
// TODO: fix this.
|
||||
super.handleAnyParam(paramName, paramValue);
|
||||
}
|
||||
|
||||
@@ -266,7 +261,7 @@ public class VCardParser_V30 extends VCardParser_V21 {
|
||||
|
||||
@Override
|
||||
protected void handleAgent(String propertyValue) {
|
||||
// The way how vCard 3.0 supports "AGENT" is completely different from vCard 2.0.
|
||||
// The way how vCard 3.0 supports "AGENT" is completely different from vCard 2.1.
|
||||
//
|
||||
// e.g.
|
||||
// AGENT:BEGIN:VCARD\nFN:Joe Friday\nTEL:+1-919-555-7878\n
|
||||
@@ -281,13 +276,13 @@ public class VCardParser_V30 extends VCardParser_V21 {
|
||||
// AGENT;VALUE=uri:
|
||||
// CID:JQPUBLIC.part3.960129T083020.xyzMail@host3.com
|
||||
//
|
||||
// This is not VCARD. Should we support this?
|
||||
// throw new VCardException("AGENT in vCard 3.0 is not supported yet.");
|
||||
// This is not vCard. Should we support this?
|
||||
//
|
||||
// Just ignore the line for now, since we cannot know how to handle it...
|
||||
if (!mEmittedAgentWarning) {
|
||||
Log.w(LOG_TAG, "AGENT in vCard 3.0 is not supported yet. Ignore it");
|
||||
mEmittedAgentWarning = true;
|
||||
}
|
||||
// Just ignore the line for now, since we cannot know how to handle it...
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,7 +293,7 @@ public class VCardParser_V30 extends VCardParser_V21 {
|
||||
protected String getBase64(String firstString) throws IOException, VCardException {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(firstString);
|
||||
|
||||
|
||||
while (true) {
|
||||
String line = getLine();
|
||||
if (line == null) {
|
||||
@@ -322,8 +317,8 @@ public class VCardParser_V30 extends VCardParser_V21 {
|
||||
* ; \\ encodes \, \n or \N encodes newline
|
||||
* ; \; encodes ;, \, encodes ,
|
||||
*
|
||||
* Note: Apple escape ':' into '\:' while does not escape '\'
|
||||
*/
|
||||
* Note: Apple escapes ':' into '\:' while does not escape '\'
|
||||
*/
|
||||
@Override
|
||||
protected String maybeUnescapeText(String text) {
|
||||
return unescapeText(text);
|
||||
@@ -347,7 +342,7 @@ public class VCardParser_V30 extends VCardParser_V21 {
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String maybeUnescapeCharacter(char ch) {
|
||||
return unescapeCharacter(ch);
|
||||
|
||||
@@ -62,7 +62,7 @@ public class VCardSourceDetector implements VCardInterpreter {
|
||||
public void end() {
|
||||
}
|
||||
|
||||
public void startRecord(String type) {
|
||||
public void startEntry() {
|
||||
}
|
||||
|
||||
public void startProperty() {
|
||||
@@ -72,7 +72,7 @@ public class VCardSourceDetector implements VCardInterpreter {
|
||||
public void endProperty() {
|
||||
}
|
||||
|
||||
public void endRecord() {
|
||||
public void endEntry() {
|
||||
}
|
||||
|
||||
public void propertyGroup(String group) {
|
||||
|
||||
@@ -64,7 +64,7 @@ public class PropertyNodesVerifier extends VNodeBuilder {
|
||||
public void verify(InputStream is, int vCardType) throws IOException, VCardException {
|
||||
final VCardParser vCardParser;
|
||||
if (VCardConfig.isV30(vCardType)) {
|
||||
vCardParser = new VCardParser_V30(true); // use StrictParsing
|
||||
vCardParser = new VCardParser_V30(true); // Use StrictParsing.
|
||||
} else {
|
||||
vCardParser = new VCardParser_V21();
|
||||
}
|
||||
@@ -86,8 +86,8 @@ public class PropertyNodesVerifier extends VNodeBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endRecord() {
|
||||
super.endRecord();
|
||||
public void endEntry() {
|
||||
super.endEntry();
|
||||
mAndroidTestCase.assertTrue(mIndex < mPropertyNodesVerifierElemList.size());
|
||||
mAndroidTestCase.assertTrue(mIndex < vNodeList.size());
|
||||
mPropertyNodesVerifierElemList.get(mIndex).verify(vNodeList.get(mIndex));
|
||||
|
||||
@@ -37,7 +37,7 @@ import android.pim.vcard.VCardEntry;
|
||||
import android.pim.vcard.VCardEntryCommitter;
|
||||
import android.pim.vcard.VCardEntryHandler;
|
||||
import android.pim.vcard.VCardInterpreter;
|
||||
import android.pim.vcard.VCardInterPreterCollection;
|
||||
import android.pim.vcard.VCardInterpreterCollection;
|
||||
import android.pim.vcard.VCardComposer;
|
||||
import android.pim.vcard.VCardConfig;
|
||||
import android.pim.vcard.VCardEntryConstructor;
|
||||
@@ -863,7 +863,7 @@ class CustomMockContext extends MockContext {
|
||||
new VCardEntryConstructor(mVCardType);
|
||||
vcardDataBuilder.addEntryHandler(mImportVerifier);
|
||||
if (mPropertyNodesVerifier != null) {
|
||||
builder = new VCardInterPreterCollection(Arrays.asList(
|
||||
builder = new VCardInterpreterCollection(Arrays.asList(
|
||||
mPropertyNodesVerifier, vcardDataBuilder));
|
||||
} else {
|
||||
builder = vnodeBuilder;
|
||||
|
||||
@@ -115,11 +115,10 @@ public class VNodeBuilder implements VCardInterpreter {
|
||||
// I leave this code as is since I'm not familiar with vcalendar specification.
|
||||
// But I believe we should refactor this code in the future.
|
||||
// Until this, the last entry has to be removed when some error occurs.
|
||||
public void startRecord(String type) {
|
||||
|
||||
public void startEntry() {
|
||||
VNode vnode = new VNode();
|
||||
vnode.parseStatus = 1;
|
||||
vnode.VName = type;
|
||||
vnode.VName = "VCARD";
|
||||
// I feel this should be done in endRecord(), but it cannot be done because of
|
||||
// the reason above.
|
||||
vNodeList.add(vnode);
|
||||
@@ -127,7 +126,7 @@ public class VNodeBuilder implements VCardInterpreter {
|
||||
mCurrentVNode = vNodeList.get(mNodeListPos);
|
||||
}
|
||||
|
||||
public void endRecord() {
|
||||
public void endEntry() {
|
||||
VNode endNode = vNodeList.get(mNodeListPos);
|
||||
endNode.parseStatus = 0;
|
||||
while(mNodeListPos > 0){
|
||||
|
||||
Reference in New Issue
Block a user