am ddd017f8: Merge change I8daabf26 into eclair-mr2

Merge commit 'ddd017f872bee40450c0e73dcf6608a9fdc49a05' into eclair-mr2-plus-aosp

* commit 'ddd017f872bee40450c0e73dcf6608a9fdc49a05':
  Modify vCard exporter code so that it does not emit non-Ascii type.
This commit is contained in:
Daisuke Miyakawa
2009-11-18 16:16:33 -08:00
committed by Android Git Automerger
7 changed files with 264 additions and 170 deletions

View File

@@ -370,7 +370,7 @@ import java.util.Map;
* @param ch input character * @param ch input character
* @return CharSequence object if the mapping for ch exists. Return null otherwise. * @return CharSequence object if the mapping for ch exists. Return null otherwise.
*/ */
public static CharSequence tryGetHalfWidthText(char ch) { public static String tryGetHalfWidthText(char ch) {
if (sHalfWidthMap.containsKey(ch)) { if (sHalfWidthMap.containsKey(ch)) {
return sHalfWidthMap.get(ch); return sHalfWidthMap.get(ch);
} else { } else {

View File

@@ -835,66 +835,90 @@ public class VCardBuilder {
* @return null when there's no information available to construct the data. * @return null when there's no information available to construct the data.
*/ */
private PostalStruct tryConstructPostalStruct(ContentValues contentValues) { private PostalStruct tryConstructPostalStruct(ContentValues contentValues) {
boolean reallyUseQuotedPrintable = false; // adr-value = 0*6(text-value ";") text-value
boolean appendCharset = false; // ; PO Box, Extended Address, Street, Locality, Region, Postal
// ; Code, Country Name
boolean dataArrayExists = false; final String rawPoBox = contentValues.getAsString(StructuredPostal.POBOX);
String[] dataArray = VCardUtils.getVCardPostalElements(contentValues); final String rawExtendedAddress = contentValues.getAsString(StructuredPostal.NEIGHBORHOOD);
for (String data : dataArray) { final String rawStreet = contentValues.getAsString(StructuredPostal.STREET);
if (!TextUtils.isEmpty(data)) { final String rawLocality = contentValues.getAsString(StructuredPostal.CITY);
dataArrayExists = true; final String rawRegion = contentValues.getAsString(StructuredPostal.REGION);
if (!appendCharset && !VCardUtils.containsOnlyPrintableAscii(data)) { final String rawPostalCode = contentValues.getAsString(StructuredPostal.POSTCODE);
appendCharset = true; final String rawCountry = contentValues.getAsString(StructuredPostal.COUNTRY);
} final String[] rawAddressArray = new String[]{
if (mShouldUseQuotedPrintable && rawPoBox, rawExtendedAddress, rawStreet, rawLocality,
!VCardUtils.containsOnlyNonCrLfPrintableAscii(data)) { rawRegion, rawPostalCode, rawCountry};
reallyUseQuotedPrintable = true; if (!VCardUtils.areAllEmpty(rawAddressArray)) {
break; final boolean reallyUseQuotedPrintable =
} (mShouldUseQuotedPrintable &&
} !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawAddressArray));
} final boolean appendCharset =
!VCardUtils.containsOnlyPrintableAscii(rawAddressArray);
if (dataArrayExists) { final String encodedPoBox;
StringBuffer addressBuffer = new StringBuffer(); final String encodedExtendedAddress;
boolean first = true; final String encodedStreet;
for (String data : dataArray) { final String encodedLocality;
if (first) { final String encodedRegion;
first = false; final String encodedPostalCode;
} else { final String encodedCountry;
addressBuffer.append(VCARD_ITEM_SEPARATOR);
}
if (!TextUtils.isEmpty(data)) {
if (reallyUseQuotedPrintable) {
addressBuffer.append(encodeQuotedPrintable(data));
} else {
addressBuffer.append(escapeCharacters(data));
}
}
}
return new PostalStruct(reallyUseQuotedPrintable, appendCharset,
addressBuffer.toString());
}
String formattedAddress =
contentValues.getAsString(StructuredPostal.FORMATTED_ADDRESS);
if (!TextUtils.isEmpty(formattedAddress)) {
reallyUseQuotedPrintable =
!VCardUtils.containsOnlyPrintableAscii(formattedAddress);
appendCharset =
!VCardUtils.containsOnlyNonCrLfPrintableAscii(formattedAddress);
if (reallyUseQuotedPrintable) { if (reallyUseQuotedPrintable) {
formattedAddress = encodeQuotedPrintable(formattedAddress); encodedPoBox = encodeQuotedPrintable(rawPoBox);
encodedExtendedAddress = encodeQuotedPrintable(rawExtendedAddress);
encodedStreet = encodeQuotedPrintable(rawStreet);
encodedLocality = encodeQuotedPrintable(rawLocality);
encodedRegion = encodeQuotedPrintable(rawRegion);
encodedPostalCode = encodeQuotedPrintable(rawPostalCode);
encodedCountry = encodeQuotedPrintable(rawCountry);
} else { } else {
formattedAddress = escapeCharacters(formattedAddress); encodedPoBox = escapeCharacters(rawPoBox);
encodedExtendedAddress = escapeCharacters(rawExtendedAddress);
encodedStreet = escapeCharacters(rawStreet);
encodedLocality = escapeCharacters(rawLocality);
encodedRegion = escapeCharacters(rawRegion);
encodedPostalCode = escapeCharacters(rawPostalCode);
encodedCountry = escapeCharacters(rawCountry);
} }
// We use the second value ("Extended Address"). final StringBuffer addressBuffer = new StringBuffer();
// addressBuffer.append(encodedPoBox);
// adr-value = 0*6(text-value ";") text-value
// ; PO Box, Extended Address, Street, Locality, Region, Postal
// ; Code, Country Name
StringBuffer addressBuffer = new StringBuffer();
addressBuffer.append(VCARD_ITEM_SEPARATOR); addressBuffer.append(VCARD_ITEM_SEPARATOR);
addressBuffer.append(formattedAddress); addressBuffer.append(encodedExtendedAddress);
addressBuffer.append(VCARD_ITEM_SEPARATOR);
addressBuffer.append(encodedStreet);
addressBuffer.append(VCARD_ITEM_SEPARATOR);
addressBuffer.append(encodedLocality);
addressBuffer.append(VCARD_ITEM_SEPARATOR);
addressBuffer.append(encodedRegion);
addressBuffer.append(VCARD_ITEM_SEPARATOR);
addressBuffer.append(encodedPostalCode);
addressBuffer.append(VCARD_ITEM_SEPARATOR);
addressBuffer.append(encodedCountry);
return new PostalStruct(
reallyUseQuotedPrintable, appendCharset, addressBuffer.toString());
} else { // VCardUtils.areAllEmpty(rawAddressArray) == true
// Try to use FORMATTED_ADDRESS instead.
final String rawFormattedAddress =
contentValues.getAsString(StructuredPostal.FORMATTED_ADDRESS);
if (TextUtils.isEmpty(rawFormattedAddress)) {
return null;
}
final boolean reallyUseQuotedPrintable =
(mShouldUseQuotedPrintable &&
!VCardUtils.containsOnlyNonCrLfPrintableAscii(rawFormattedAddress));
final boolean appendCharset =
!VCardUtils.containsOnlyPrintableAscii(rawFormattedAddress);
final String encodedFormattedAddress;
if (reallyUseQuotedPrintable) {
encodedFormattedAddress = encodeQuotedPrintable(rawFormattedAddress);
} else {
encodedFormattedAddress = escapeCharacters(rawFormattedAddress);
}
// We use the second value ("Extended Address") just because Japanese mobile phones
// do so. If the other importer expects the value be in the other field, some flag may
// be needed.
final StringBuffer addressBuffer = new StringBuffer();
addressBuffer.append(VCARD_ITEM_SEPARATOR);
addressBuffer.append(encodedFormattedAddress);
addressBuffer.append(VCARD_ITEM_SEPARATOR); addressBuffer.append(VCARD_ITEM_SEPARATOR);
addressBuffer.append(VCARD_ITEM_SEPARATOR); addressBuffer.append(VCARD_ITEM_SEPARATOR);
addressBuffer.append(VCARD_ITEM_SEPARATOR); addressBuffer.append(VCARD_ITEM_SEPARATOR);
@@ -903,7 +927,6 @@ public class VCardBuilder {
return new PostalStruct( return new PostalStruct(
reallyUseQuotedPrintable, appendCharset, addressBuffer.toString()); reallyUseQuotedPrintable, appendCharset, addressBuffer.toString());
} }
return null; // There's no data available.
} }
public VCardBuilder appendIms(final List<ContentValues> contentValuesList) { public VCardBuilder appendIms(final List<ContentValues> contentValuesList) {
@@ -1653,13 +1676,22 @@ public class VCardBuilder {
// We may have to make this comma separated form like "TYPE=DOM,WORK" in the future, // We may have to make this comma separated form like "TYPE=DOM,WORK" in the future,
// which would be recommended way in vcard 3.0 though not valid in vCard 2.1. // which would be recommended way in vcard 3.0 though not valid in vCard 2.1.
boolean first = true; boolean first = true;
for (String type : types) { for (final String typeValue : types) {
// Note: vCard 3.0 specifies the different type of acceptable type Strings, but
// we don't emit that kind of vCard 3.0 specific type since there should be
// high probabilyty in which external importers cannot understand them.
//
// e.g. TYPE="\u578B\u306B\u3087" (vCard 3.0 allows non-Ascii characters if they
// are quoted.)
if (!VCardUtils.isV21Word(typeValue)) {
continue;
}
if (first) { if (first) {
first = false; first = false;
} else { } else {
mBuilder.append(VCARD_PARAM_SEPARATOR); mBuilder.append(VCARD_PARAM_SEPARATOR);
} }
appendTypeParameter(type); appendTypeParameter(typeValue);
} }
} }

View File

@@ -16,14 +16,12 @@
package android.pim.vcard; package android.pim.vcard;
import android.content.ContentProviderOperation; import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.provider.ContactsContract.Data; import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.CommonDataKinds.Im; import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.telephony.PhoneNumberUtils; import android.telephony.PhoneNumberUtils;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -245,8 +243,7 @@ public class VCardUtils {
* Inserts postal data into the builder object. * Inserts postal data into the builder object.
* *
* Note that the data structure of ContactsContract is different from that defined in vCard. * Note that the data structure of ContactsContract is different from that defined in vCard.
* So some conversion may be performed in this method. See also * So some conversion may be performed in this method.
* {{@link #getVCardPostalElements(ContentValues)}
*/ */
public static void insertStructuredPostalDataUsingContactsStruct(int vcardType, public static void insertStructuredPostalDataUsingContactsStruct(int vcardType,
final ContentProviderOperation.Builder builder, final ContentProviderOperation.Builder builder,
@@ -260,9 +257,6 @@ public class VCardUtils {
} }
builder.withValue(StructuredPostal.POBOX, postalData.pobox); builder.withValue(StructuredPostal.POBOX, postalData.pobox);
// TODO: Japanese phone seems to use this field for expressing all the address including
// region, city, etc. Not sure we're ok to store them into NEIGHBORHOOD, while it would be
// better than dropping them all.
builder.withValue(StructuredPostal.NEIGHBORHOOD, postalData.extendedAddress); builder.withValue(StructuredPostal.NEIGHBORHOOD, postalData.extendedAddress);
builder.withValue(StructuredPostal.STREET, postalData.street); builder.withValue(StructuredPostal.STREET, postalData.street);
builder.withValue(StructuredPostal.CITY, postalData.localty); builder.withValue(StructuredPostal.CITY, postalData.localty);
@@ -277,59 +271,6 @@ public class VCardUtils {
} }
} }
/**
* Returns String[] containing address information based on vCard spec
* (PO Box, Extended Address, Street, Locality, Region, Postal Code, Country Name).
* All String objects are non-null ("" is used when the relevant data is empty).
*
* Note that the data structure of ContactsContract is different from that defined in vCard.
* So some conversion may be performed in this method. See also
* {{@link #insertStructuredPostalDataUsingContactsStruct(int,
* android.content.ContentProviderOperation.Builder,
* android.pim.vcard.VCardEntry.PostalData)}
*/
public static String[] getVCardPostalElements(ContentValues contentValues) {
// adr-value = 0*6(text-value ";") text-value
// ; PO Box, Extended Address, Street, Locality, Region, Postal
// ; Code, Country Name
String[] dataArray = new String[7];
dataArray[0] = contentValues.getAsString(StructuredPostal.POBOX);
if (dataArray[0] == null) {
dataArray[0] = "";
}
// We keep all the data in StructuredPostal, presuming NEIGHBORHOOD is
// similar to "Extended Address".
dataArray[1] = contentValues.getAsString(StructuredPostal.NEIGHBORHOOD);
if (dataArray[1] == null) {
dataArray[1] = "";
}
dataArray[2] = contentValues.getAsString(StructuredPostal.STREET);
if (dataArray[2] == null) {
dataArray[2] = "";
}
// Assume that localty == city
dataArray[3] = contentValues.getAsString(StructuredPostal.CITY);
if (dataArray[3] == null) {
dataArray[3] = "";
}
String region = contentValues.getAsString(StructuredPostal.REGION);
if (!TextUtils.isEmpty(region)) {
dataArray[4] = region;
} else {
dataArray[4] = "";
}
dataArray[5] = contentValues.getAsString(StructuredPostal.POSTCODE);
if (dataArray[5] == null) {
dataArray[5] = "";
}
dataArray[6] = contentValues.getAsString(StructuredPostal.COUNTRY);
if (dataArray[6] == null) {
dataArray[6] = "";
}
return dataArray;
}
public static String constructNameFromElements(final int vcardType, public static String constructNameFromElements(final int vcardType,
final String familyName, final String middleName, final String givenName) { final String familyName, final String middleName, final String givenName) {
return constructNameFromElements(vcardType, familyName, middleName, givenName, return constructNameFromElements(vcardType, familyName, middleName, givenName,
@@ -394,18 +335,22 @@ public class VCardUtils {
return list; return list;
} }
public static boolean containsOnlyPrintableAscii(String str) { public static boolean containsOnlyPrintableAscii(final String...values) {
if (TextUtils.isEmpty(str)) { if (values == null) {
return true; return true;
} }
final int length = str.length();
final int asciiFirst = 0x20; final int asciiFirst = 0x20;
final int asciiLast = 0x7E; // included final int asciiLast = 0x7E; // included
for (int i = 0; i < length; i = str.offsetByCodePoints(i, 1)) { for (final String value : values) {
final int c = str.codePointAt(i); if (TextUtils.isEmpty(value)) {
if (!((asciiFirst <= c && c <= asciiLast) || c == '\r' || c == '\n')) { continue;
return false; }
final int length = value.length();
for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) {
final int c = value.codePointAt(i);
if (!((asciiFirst <= c && c <= asciiLast) || c == '\r' || c == '\n')) {
return false;
}
} }
} }
return true; return true;
@@ -416,17 +361,50 @@ public class VCardUtils {
* or not, which is required by vCard 2.1. * or not, which is required by vCard 2.1.
* See the definition of "7bit" in vCard 2.1 spec for more information. * See the definition of "7bit" in vCard 2.1 spec for more information.
*/ */
public static boolean containsOnlyNonCrLfPrintableAscii(String str) { public static boolean containsOnlyNonCrLfPrintableAscii(final String...values) {
if (TextUtils.isEmpty(str)) { if (values == null) {
return true; return true;
} }
final int length = str.length();
final int asciiFirst = 0x20; final int asciiFirst = 0x20;
final int asciiLast = 0x7E; // included final int asciiLast = 0x7E; // included
for (int i = 0; i < length; i = str.offsetByCodePoints(i, 1)) { for (final String value : values) {
final int c = str.codePointAt(i); if (TextUtils.isEmpty(value)) {
if (!(asciiFirst <= c && c <= asciiLast)) { continue;
}
final int length = value.length();
for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) {
final int c = value.codePointAt(i);
if (!(asciiFirst <= c && c <= asciiLast)) {
return false;
}
}
}
return true;
}
private static final Set<Character> sUnAcceptableAsciiInV21WordSet =
new HashSet<Character>(Arrays.asList('[', ']', '=', ':', '.', ',', ' '));
/**
* <P>
* Returns true when the given String is categorized as "word" specified in vCard spec 2.1.
* </P>
* <P>
* vCard 2.1 specifies:<BR />
* word = &lt;any printable 7bit us-ascii except []=:., &gt;
* </P>
*/
public static boolean isV21Word(final String value) {
if (TextUtils.isEmpty(value)) {
return true;
}
final int asciiFirst = 0x20;
final int asciiLast = 0x7E; // included
final int length = value.length();
for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) {
final int c = value.codePointAt(i);
if (!(asciiFirst <= c && c <= asciiLast) ||
sUnAcceptableAsciiInV21WordSet.contains((char)c)) {
return false; return false;
} }
} }
@@ -442,11 +420,10 @@ public class VCardUtils {
* such kind of input but must never output it unless the target is very specific * such kind of input but must never output it unless the target is very specific
* to the device which is able to parse the malformed input. * to the device which is able to parse the malformed input.
*/ */
public static boolean containsOnlyAlphaDigitHyphen(String str) { public static boolean containsOnlyAlphaDigitHyphen(final String...values) {
if (TextUtils.isEmpty(str)) { if (values == null) {
return true; return true;
} }
final int upperAlphabetFirst = 0x41; // A final int upperAlphabetFirst = 0x41; // A
final int upperAlphabetAfterLast = 0x5b; // [ final int upperAlphabetAfterLast = 0x5b; // [
final int lowerAlphabetFirst = 0x61; // a final int lowerAlphabetFirst = 0x61; // a
@@ -454,30 +431,35 @@ public class VCardUtils {
final int digitFirst = 0x30; // 0 final int digitFirst = 0x30; // 0
final int digitAfterLast = 0x3A; // : final int digitAfterLast = 0x3A; // :
final int hyphen = '-'; final int hyphen = '-';
final int length = str.length(); for (final String str : values) {
for (int i = 0; i < length; i = str.offsetByCodePoints(i, 1)) { if (TextUtils.isEmpty(str)) {
int codepoint = str.codePointAt(i); continue;
if (!((lowerAlphabetFirst <= codepoint && codepoint < lowerAlphabetAfterLast) || }
final int length = str.length();
for (int i = 0; i < length; i = str.offsetByCodePoints(i, 1)) {
int codepoint = str.codePointAt(i);
if (!((lowerAlphabetFirst <= codepoint && codepoint < lowerAlphabetAfterLast) ||
(upperAlphabetFirst <= codepoint && codepoint < upperAlphabetAfterLast) || (upperAlphabetFirst <= codepoint && codepoint < upperAlphabetAfterLast) ||
(digitFirst <= codepoint && codepoint < digitAfterLast) || (digitFirst <= codepoint && codepoint < digitAfterLast) ||
(codepoint == hyphen))) { (codepoint == hyphen))) {
return false; return false;
}
} }
} }
return true; return true;
} }
public static String toHalfWidthString(String orgString) { public static String toHalfWidthString(final String orgString) {
if (TextUtils.isEmpty(orgString)) { if (TextUtils.isEmpty(orgString)) {
return null; return null;
} }
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
final int length = orgString.length(); final int length = orgString.length();
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i = orgString.offsetByCodePoints(i, 1)) {
// All Japanese character is able to be expressed by char. // All Japanese character is able to be expressed by char.
// Do not need to use String#codepPointAt(). // Do not need to use String#codepPointAt().
final char ch = orgString.charAt(i); final char ch = orgString.charAt(i);
CharSequence halfWidthText = JapaneseUtils.tryGetHalfWidthText(ch); final String halfWidthText = JapaneseUtils.tryGetHalfWidthText(ch);
if (halfWidthText != null) { if (halfWidthText != null) {
builder.append(halfWidthText); builder.append(halfWidthText);
} else { } else {
@@ -495,6 +477,9 @@ public class VCardUtils {
* @return The image type or null when the type cannot be determined. * @return The image type or null when the type cannot be determined.
*/ */
public static String guessImageType(final byte[] input) { public static String guessImageType(final byte[] input) {
if (input == null) {
return null;
}
if (input.length >= 3 && input[0] == 'G' && input[1] == 'I' && input[2] == 'F') { if (input.length >= 3 && input[0] == 'G' && input[1] == 'I' && input[2] == 'F') {
return "GIF"; return "GIF";
} else if (input.length >= 4 && input[0] == (byte) 0x89 } else if (input.length >= 4 && input[0] == (byte) 0x89
@@ -511,6 +496,22 @@ public class VCardUtils {
} }
} }
/**
* @return True when all the given values are null or empty Strings.
*/
public static boolean areAllEmpty(final String...values) {
if (values == null) {
return true;
}
for (final String value : values) {
if (!TextUtils.isEmpty(value)) {
return false;
}
}
return true;
}
private VCardUtils() { private VCardUtils() {
} }
} }

View File

@@ -139,6 +139,12 @@ class PropertyNodesVerifierElem {
return addNodeWithOrder(propName, propValue, null, null, contentValues, null, null); return addNodeWithOrder(propName, propValue, null, null, contentValues, null, null);
} }
public PropertyNodesVerifierElem addNodeWithOrder(String propName,
List<String> propValueList, ContentValues contentValues) {
return addNodeWithOrder(propName, null, propValueList,
null, contentValues, null, null);
}
public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue, public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue,
List<String> propValueList) { List<String> propValueList) {
return addNodeWithOrder(propName, propValue, propValueList, null, null, null, null); return addNodeWithOrder(propName, propValue, propValueList, null, null, null, null);
@@ -157,8 +163,7 @@ class PropertyNodesVerifierElem {
public PropertyNodesVerifierElem addNodeWithOrder(String propName, public PropertyNodesVerifierElem addNodeWithOrder(String propName,
List<String> propValueList, TypeSet paramMap_TYPE) { List<String> propValueList, TypeSet paramMap_TYPE) {
final String propValue = concatinateListWithSemiColon(propValueList); return addNodeWithOrder(propName, null, propValueList, null, null,
return addNodeWithOrder(propName, propValue, propValueList, null, null,
paramMap_TYPE, null); paramMap_TYPE, null);
} }
@@ -177,6 +182,9 @@ class PropertyNodesVerifierElem {
public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue, public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue,
List<String> propValueList, byte[] propValue_bytes, List<String> propValueList, byte[] propValue_bytes,
ContentValues paramMap, TypeSet paramMap_TYPE, GroupSet propGroupSet) { ContentValues paramMap, TypeSet paramMap_TYPE, GroupSet propGroupSet) {
if (propValue == null && propValueList != null) {
propValue = concatinateListWithSemiColon(propValueList);
}
PropertyNode propertyNode = new PropertyNode(propName, PropertyNode propertyNode = new PropertyNode(propName,
propValue, propValueList, propValue_bytes, propValue, propValueList, propValue_bytes,
paramMap, paramMap_TYPE, propGroupSet); paramMap, paramMap_TYPE, propGroupSet);
@@ -200,14 +208,20 @@ class PropertyNodesVerifierElem {
return addNodeWithoutOrder(propName, propValue, null, null, contentValues, null, null); return addNodeWithoutOrder(propName, propValue, null, null, contentValues, null, null);
} }
public PropertyNodesVerifierElem addNodeWithoutOrder(String propName,
List<String> propValueList, ContentValues contentValues) {
return addNodeWithoutOrder(propName, null,
propValueList, null, contentValues, null, null);
}
public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue, public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue,
List<String> propValueList) { List<String> propValueList) {
return addNodeWithoutOrder(propName, propValue, propValueList, null, null, null, null); return addNodeWithoutOrder(propName, propValue, propValueList, null, null, null, null);
} }
public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, List<String> propValueList) { public PropertyNodesVerifierElem addNodeWithoutOrder(String propName,
final String propValue = concatinateListWithSemiColon(propValueList); List<String> propValueList) {
return addNodeWithoutOrder(propName, propValue, propValueList, return addNodeWithoutOrder(propName, null, propValueList,
null, null, null, null); null, null, null, null);
} }
@@ -238,6 +252,9 @@ class PropertyNodesVerifierElem {
public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue, public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue,
List<String> propValueList, byte[] propValue_bytes, List<String> propValueList, byte[] propValue_bytes,
ContentValues paramMap, TypeSet paramMap_TYPE, GroupSet propGroupSet) { ContentValues paramMap, TypeSet paramMap_TYPE, GroupSet propGroupSet) {
if (propValue == null && propValueList != null) {
propValue = concatinateListWithSemiColon(propValueList);
}
mUnorderedNodeList.add(new PropertyNode(propName, propValue, mUnorderedNodeList.add(new PropertyNode(propName, propValue,
propValueList, propValue_bytes, paramMap, paramMap_TYPE, propGroupSet)); propValueList, propValue_bytes, paramMap, paramMap_TYPE, propGroupSet));
return this; return this;

View File

@@ -546,12 +546,9 @@ public class VCardExporterTests extends VCardTestsBase {
testEmailPrefHandlingCommon(V30); testEmailPrefHandlingCommon(V30);
} }
private void testPostalOnlyWithStructuredDataCommon(int vcardType) { private void testPostalAddressCommon(int vcardType) {
VCardVerifier verifier = new VCardVerifier(vcardType); VCardVerifier verifier = new VCardVerifier(vcardType);
ContactEntry entry = verifier.addInputEntry(); ContactEntry entry = verifier.addInputEntry();
// adr-value = 0*6(text-value ";") text-value
// ; PO Box, Extended Address, Street, Locality, Region, Postal Code,
// ; Country Name
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE) entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.POBOX, "Pobox") .put(StructuredPostal.POBOX, "Pobox")
.put(StructuredPostal.NEIGHBORHOOD, "Neighborhood") .put(StructuredPostal.NEIGHBORHOOD, "Neighborhood")
@@ -559,27 +556,33 @@ public class VCardExporterTests extends VCardTestsBase {
.put(StructuredPostal.CITY, "City") .put(StructuredPostal.CITY, "City")
.put(StructuredPostal.REGION, "Region") .put(StructuredPostal.REGION, "Region")
.put(StructuredPostal.POSTCODE, "100") .put(StructuredPostal.POSTCODE, "100")
.put(StructuredPostal.COUNTRY, "Country"); .put(StructuredPostal.COUNTRY, "Country")
.put(StructuredPostal.FORMATTED_ADDRESS, "Formatted Address")
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK);
// adr-value = 0*6(text-value ";") text-value
// ; PO Box, Extended Address, Street, Locality, Region, Postal Code,
// ; Country Name
verifier.addPropertyNodesVerifierElemWithEmptyName() verifier.addPropertyNodesVerifierElemWithEmptyName()
.addNodeWithoutOrder("ADR", "Pobox;Neighborhood;Street;City;Region;100;Country", .addNodeWithoutOrder("ADR",
Arrays.asList("Pobox", "Neighborhood", "Street", "City", Arrays.asList("Pobox", "Neighborhood", "Street", "City",
"Region", "100", "Country"), new TypeSet("HOME")); "Region", "100", "Country"), new TypeSet("WORK"));
verifier.verify(); verifier.verify();
} }
public void testPostalOnlyWithStructuredDataV21() { public void testPostalAddressV21() {
testPostalOnlyWithStructuredDataCommon(V21); testPostalAddressCommon(V21);
} }
public void testPostalOnlyWithStructuredDataV30() { public void testPostalAddressV30() {
testPostalOnlyWithStructuredDataCommon(V30); testPostalAddressCommon(V30);
} }
private void testPostalOnlyWithFormattedAddressCommon(int vcardType) { private void testPostalOnlyWithFormattedAddressCommon(int vcardType) {
VCardVerifier verifier = new VCardVerifier(vcardType); VCardVerifier verifier = new VCardVerifier(vcardType);
ContactEntry entry = verifier.addInputEntry(); ContactEntry entry = verifier.addInputEntry();
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE) entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.REGION, "") // Must be ignored.
.put(StructuredPostal.FORMATTED_ADDRESS, .put(StructuredPostal.FORMATTED_ADDRESS,
"Formatted address CA 123-334 United Statue"); "Formatted address CA 123-334 United Statue");
@@ -587,7 +590,6 @@ public class VCardExporterTests extends VCardTestsBase {
.addNodeWithOrder("ADR", ";Formatted address CA 123-334 United Statue;;;;;", .addNodeWithOrder("ADR", ";Formatted address CA 123-334 United Statue;;;;;",
Arrays.asList("", "Formatted address CA 123-334 United Statue", Arrays.asList("", "Formatted address CA 123-334 United Statue",
"", "", "", "", ""), new TypeSet("HOME")); "", "", "", "", ""), new TypeSet("HOME"));
verifier.verify(); verifier.verify();
} }

View File

@@ -205,11 +205,50 @@ public class VCardJapanizationTests extends VCardTestsBase {
verifier.verify(); verifier.verify();
} }
private void testPostalAddressWithJapaneseCommon(int vcardType) {
VCardVerifier verifier = new VCardVerifier(vcardType);
ContactEntry entry = verifier.addInputEntry();
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.POBOX, "\u79C1\u66F8\u7BB107")
.put(StructuredPostal.NEIGHBORHOOD,
"\u30A2\u30D1\u30FC\u30C8\u0020\u0033\u0034\u53F7\u5BA4")
.put(StructuredPostal.STREET, "\u96DB\u898B\u6CA2\u6751")
.put(StructuredPostal.CITY, "\u9E7F\u9AA8\u5E02")
.put(StructuredPostal.REGION, "\u00D7\u00D7\u770C")
.put(StructuredPostal.POSTCODE, "494-1313")
.put(StructuredPostal.COUNTRY, "\u65E5\u672C")
.put(StructuredPostal.FORMATTED_ADDRESS,
"\u3053\u3093\u306A\u3068\u3053\u308D\u3092\u898B"
+ "\u308B\u306A\u3093\u3066\u6687\u4EBA\u3067\u3059\u304B\uFF1F")
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM)
.put(StructuredPostal.LABEL, "\u304A\u3082\u3061\u304B\u3048\u308A");
ContentValues contentValues = (VCardConfig.usesShiftJis(vcardType) ?
(VCardConfig.isV30(vcardType) ? mContentValuesForSJis :
mContentValuesForQPAndSJis) :
(VCardConfig.isV30(vcardType) ? mContentValuesForUtf8 :
mContentValuesForQPAndUtf8));
PropertyNodesVerifierElem elem = verifier.addPropertyNodesVerifierElemWithEmptyName();
// LABEL must be ignored in vCard 2.1. As for vCard 3.0, the current behavior is
// same as that in vCard 3.0, which can be changed in the future.
elem.addNodeWithoutOrder("ADR", Arrays.asList("\u79C1\u66F8\u7BB107",
"\u30A2\u30D1\u30FC\u30C8\u0020\u0033\u0034\u53F7\u5BA4",
"\u96DB\u898B\u6CA2\u6751", "\u9E7F\u9AA8\u5E02", "\u00D7\u00D7\u770C",
"494-1313", "\u65E5\u672C"),
contentValues);
verifier.verify();
}
public void testPostalAddresswithJapaneseV21() {
testPostalAddressWithJapaneseCommon(VCardConfig.VCARD_TYPE_V21_JAPANESE_SJIS);
}
/** /**
* Verifies that only one address field is emitted toward DoCoMo phones. * Verifies that only one address field is emitted toward DoCoMo phones.
* Prefered type must (should?) be: HOME > WORK > OTHER > CUSTOM * Prefered type must (should?) be: HOME > WORK > OTHER > CUSTOM
*/ */
public void testAdrressFieldEmittionForDoCoMo_1() { public void testPostalAdrressForDoCoMo_1() {
VCardVerifier verifier = new VCardVerifier(VCardConfig.VCARD_TYPE_DOCOMO); VCardVerifier verifier = new VCardVerifier(VCardConfig.VCARD_TYPE_DOCOMO);
ContactEntry entry = verifier.addInputEntry(); ContactEntry entry = verifier.addInputEntry();
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE) entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
@@ -238,7 +277,7 @@ public class VCardJapanizationTests extends VCardTestsBase {
verifier.verify(); verifier.verify();
} }
public void testAdrressFieldEmittionForDoCoMo_2() { public void testPostalAdrressForDoCoMo_2() {
VCardVerifier verifier = new VCardVerifier(VCardConfig.VCARD_TYPE_DOCOMO); VCardVerifier verifier = new VCardVerifier(VCardConfig.VCARD_TYPE_DOCOMO);
ContactEntry entry = verifier.addInputEntry(); ContactEntry entry = verifier.addInputEntry();
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE) entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
@@ -264,7 +303,7 @@ public class VCardJapanizationTests extends VCardTestsBase {
verifier.verify(); verifier.verify();
} }
public void testAdrressFieldEmittionForDoCoMo_3() { public void testPostalAdrressForDoCoMo_3() {
VCardVerifier verifier = new VCardVerifier(VCardConfig.VCARD_TYPE_DOCOMO); VCardVerifier verifier = new VCardVerifier(VCardConfig.VCARD_TYPE_DOCOMO);
ContactEntry entry = verifier.addInputEntry(); ContactEntry entry = verifier.addInputEntry();
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE) entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
@@ -293,7 +332,7 @@ public class VCardJapanizationTests extends VCardTestsBase {
/** /**
* Verifies the vCard exporter tolerates null TYPE. * Verifies the vCard exporter tolerates null TYPE.
*/ */
public void testAdrressFieldEmittionForDoCoMo_4() { public void testPostalAdrressForDoCoMo_4() {
VCardVerifier verifier = new VCardVerifier(VCardConfig.VCARD_TYPE_DOCOMO); VCardVerifier verifier = new VCardVerifier(VCardConfig.VCARD_TYPE_DOCOMO);
ContactEntry entry = verifier.addInputEntry(); ContactEntry entry = verifier.addInputEntry();
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE) entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)

View File

@@ -22,7 +22,8 @@ import junit.framework.TestCase;
public class VCardUtilsTests extends TestCase { public class VCardUtilsTests extends TestCase {
public void testContainsOnlyPrintableAscii() { public void testContainsOnlyPrintableAscii() {
assertTrue(VCardUtils.containsOnlyPrintableAscii(null)); assertTrue(VCardUtils.containsOnlyPrintableAscii((String)null));
assertTrue(VCardUtils.containsOnlyPrintableAscii((String[])null));
assertTrue(VCardUtils.containsOnlyPrintableAscii("")); assertTrue(VCardUtils.containsOnlyPrintableAscii(""));
assertTrue(VCardUtils.containsOnlyPrintableAscii("abcdefghijklmnopqrstuvwxyz")); assertTrue(VCardUtils.containsOnlyPrintableAscii("abcdefghijklmnopqrstuvwxyz"));
assertTrue(VCardUtils.containsOnlyPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); assertTrue(VCardUtils.containsOnlyPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
@@ -37,7 +38,8 @@ public class VCardUtilsTests extends TestCase {
} }
public void testContainsOnlyNonCrLfPrintableAscii() { public void testContainsOnlyNonCrLfPrintableAscii() {
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii(null)); assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii((String)null));
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii((String[])null));
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("")); assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii(""));
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("abcdefghijklmnopqrstuvwxyz")); assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("abcdefghijklmnopqrstuvwxyz"));
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
@@ -53,7 +55,8 @@ public class VCardUtilsTests extends TestCase {
} }
public void testContainsOnlyAlphaDigitHyphen() { public void testContainsOnlyAlphaDigitHyphen() {
assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen(null)); assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen((String)null));
assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen((String[])null));
assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen("")); assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen(""));
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("abcdefghijklmnopqrstuvwxyz")); assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("abcdefghijklmnopqrstuvwxyz"));
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));