diff --git a/core/java/android/pim/vcard/JapaneseUtils.java b/core/java/android/pim/vcard/JapaneseUtils.java index b37b07dbadce3..dcfe980bfcaf3 100644 --- a/core/java/android/pim/vcard/JapaneseUtils.java +++ b/core/java/android/pim/vcard/JapaneseUtils.java @@ -27,7 +27,6 @@ import java.util.Map; new HashMap(); static { - // There's no logical mapping rule in Unicode. Sigh. sHalfWidthMap.put('\u3001', "\uFF64"); sHalfWidthMap.put('\u3002', "\uFF61"); sHalfWidthMap.put('\u300C', "\uFF62"); diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java index 8c007fe1e0d00..170d6fafdccd0 100644 --- a/core/java/android/pim/vcard/VCardComposer.java +++ b/core/java/android/pim/vcard/VCardComposer.java @@ -90,14 +90,14 @@ import java.util.Map; * if (composer != null) { * composer.terminate(); * } - * } - *

+ * } + *

* Users have to manually take care of memory efficiency. Even one vCard may contain * image of non-trivial size for mobile devices. - *

- *

- * In default, Default {@link VCardBuilder} class is used to build each vCard. - *

+ *

+ *

+ * {@link VCardBuilder} is used to build each vCard. + *

*/ public class VCardComposer { private static final String LOG_TAG = "VCardComposer"; @@ -161,14 +161,14 @@ public class VCardComposer { * Must not close the stream outside this class. *

*/ - public class HandlerForOutputStream implements OneEntryHandler { + public final class HandlerForOutputStream implements OneEntryHandler { @SuppressWarnings("hiding") - private static final String LOG_TAG = "vcard.VCardComposer.HandlerForOutputStream"; + private static final String LOG_TAG = "VCardComposer.HandlerForOutputStream"; private boolean mOnTerminateIsCalled = false; - final private OutputStream mOutputStream; // mWriter will close this. - protected Writer mWriter; + private final OutputStream mOutputStream; // mWriter will close this. + private Writer mWriter; /** * Input stream will be closed on the detruction of this object. @@ -177,7 +177,7 @@ public class VCardComposer { mOutputStream = outputStream; } - public final boolean onInit(final Context context) { + public boolean onInit(final Context context) { try { mWriter = new BufferedWriter(new OutputStreamWriter( mOutputStream, mCharset)); @@ -207,7 +207,7 @@ public class VCardComposer { return true; } - public final boolean onEntryCreated(String vcard) { + public boolean onEntryCreated(String vcard) { try { mWriter.write(vcard); } catch (IOException e) { @@ -220,7 +220,7 @@ public class VCardComposer { return true; } - public final void onTerminate() { + public void onTerminate() { mOnTerminateIsCalled = true; if (mWriter != null) { try { @@ -242,8 +242,6 @@ public class VCardComposer { } } - // Users can override this if they want to (e.g. if they don't want to close the stream). - // TODO: Should expose bare OutputStream instead? public void closeOutputStream() { try { mWriter.close(); @@ -312,8 +310,7 @@ public class VCardComposer { * a Handler object given via {{@link #addHandler(OneEntryHandler)} returns false. * If false, this ignores those errors. */ - public VCardComposer(final Context context, final int vcardType, - String charset, + public VCardComposer(final Context context, final int vcardType, String charset, final boolean careHandlerErrors) { mContext = context; mVCardType = vcardType; @@ -380,6 +377,7 @@ public class VCardComposer { mCharset = charset; } } + Log.d(LOG_TAG, "Use the charset \"" + mCharset + "\""); } @@ -602,7 +600,6 @@ public class VCardComposer { return ""; } else { final VCardBuilder builder = new VCardBuilder(mVCardType, mCharset); - // TODO: Android-specific X attributes? builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE)) .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE)) .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE)) diff --git a/core/java/android/pim/vcard/VCardConfig.java b/core/java/android/pim/vcard/VCardConfig.java index 657672c634921..6c25216766220 100644 --- a/core/java/android/pim/vcard/VCardConfig.java +++ b/core/java/android/pim/vcard/VCardConfig.java @@ -153,6 +153,7 @@ public class VCardConfig { * In vCard 3.0, Quoted-Printable is explicitly "prohibitted", so we don't need to care this * kind of problem (hopefully). *

+ * @hide */ public static final int FLAG_REFRAIN_QP_TO_NAME_PROPERTIES = 0x10000000; @@ -171,7 +172,7 @@ public class VCardConfig { * able to parse them as we expect. *

*/ - public static final int FLAG_CONVERT_PHONETIC_NAME_STRINGS = 0x0800000; + public static final int FLAG_CONVERT_PHONETIC_NAME_STRINGS = 0x08000000; /** *

@@ -184,21 +185,20 @@ public class VCardConfig { * How more than one TYPE fields are expressed is different between vCard 2.1 and vCard 3.0. *

*

- * e.g.
- * 1) Probably valid in both vCard 2.1 and vCard 3.0: "ADR;TYPE=DOM;TYPE=HOME:..."
- * 2) Valid in vCard 2.1 but not in vCard 3.0: "ADR;DOM;HOME:..."
- * 3) Valid in vCard 3.0 but not in vCard 2.1: "ADR;TYPE=DOM,HOME:..."
- *

- *

- * 2) had been the default of VCard exporter/importer in Android, but it is found that - * some external exporter is not able to parse the type format like 2) but only 3). + * e.g. *

+ *
    + *
  1. Probably valid in both vCard 2.1 and vCard 3.0: "ADR;TYPE=DOM;TYPE=HOME:..."
  2. + *
  3. Valid in vCard 2.1 but not in vCard 3.0: "ADR;DOM;HOME:..."
  4. + *
  5. Valid in vCard 3.0 but not in vCard 2.1: "ADR;TYPE=DOM,HOME:..."
  6. + *
*

* If you are targeting to the importer which cannot accept TYPE params without "TYPE=" * strings (which should be rare though), please use this flag. *

*

- * Example usage: int vcardType = (VCARD_TYPE_V21_GENERIC | FLAG_APPEND_TYPE_PARAM); + * Example usage: + *

int type = (VCARD_TYPE_V21_GENERIC | FLAG_APPEND_TYPE_PARAM);
*

*/ public static final int FLAG_APPEND_TYPE_PARAM = 0x04000000; @@ -261,7 +261,6 @@ public class VCardConfig { */ public static final int VCARD_TYPE_UNKNOWN = 0; - /** *

* Generic vCard format with the vCard 2.1. When composing a vCard entry, diff --git a/core/java/android/pim/vcard/VCardEntry.java b/core/java/android/pim/vcard/VCardEntry.java index 5b8422f332c98..ec03cf4846379 100644 --- a/core/java/android/pim/vcard/VCardEntry.java +++ b/core/java/android/pim/vcard/VCardEntry.java @@ -78,12 +78,12 @@ public class VCardEntry { Im.PROTOCOL_GOOGLE_TALK); } - static public class PhoneData { + public static class PhoneData { public final int type; public final String data; public final String label; - // isPrimary is changable only when there's no appropriate one existing in - // the original VCard. + // isPrimary is (not final but) changable, only when there's no appropriate one existing + // in the original VCard. public boolean isPrimary; public PhoneData(int type, String data, String label, boolean isPrimary) { this.type = type; @@ -109,13 +109,11 @@ public class VCardEntry { } } - static public class EmailData { + public static class EmailData { public final int type; public final String data; // Used only when TYPE 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 EmailData(int type, String data, String label, boolean isPrimary) { this.type = type; @@ -141,9 +139,9 @@ public class VCardEntry { } } - static public class PostalData { - // Determined by vCard spec. - // PO Box, Extended Addr, Street, Locality, Region, Postal Code, Country Name + public static class PostalData { + // Determined by vCard specification. + // - PO Box, Extended Addr, Street, Locality, Region, Postal Code, Country Name public static final int ADDR_MAX_DATA_SIZE = 7; private final String[] dataArray; public final String pobox; @@ -248,10 +246,11 @@ public class VCardEntry { } } - static public class OrganizationData { + public static class OrganizationData { public final int type; // non-final is Intentional: we may change the values since this info is separated into - // two parts in vCard: "ORG" + "TITLE". + // two parts in vCard: "ORG" + "TITLE", and we have to cope with each field in + // different timing. public String companyName; public String departmentName; public String titleName; @@ -313,7 +312,7 @@ public class VCardEntry { } } - static public class ImData { + public static class ImData { public final int protocol; public final String customProtocol; public final int type; @@ -441,7 +440,7 @@ public class VCardEntry { private String mSuffix; // Used only when no family nor given name is found. - private String mFullName; + private String mFormattedName; private String mPhoneticFamilyName; private String mPhoneticGivenName; @@ -499,7 +498,6 @@ public class VCardEntry { } } - // Use NANP in default when there's no information about locale. final int formattingType = VCardUtils.getPhoneNumberFormat(mVCardType); formattedNumber = PhoneNumberUtils.formatNumber(builder.toString(), formattingType); } @@ -754,11 +752,11 @@ public class VCardEntry { if (propName.equals(VCardConstants.PROPERTY_VERSION)) { // vCard version. Ignore this. } else if (propName.equals(VCardConstants.PROPERTY_FN)) { - mFullName = propValue; - } else if (propName.equals(VCardConstants.PROPERTY_NAME) && mFullName == null) { + mFormattedName = propValue; + } else if (propName.equals(VCardConstants.PROPERTY_NAME) && mFormattedName == null) { // Only in vCard 3.0. Use this if FN, which must exist in vCard 3.0 but may not // actually exist in the real vCard data, does not exist. - mFullName = propValue; + mFormattedName = propValue; } else if (propName.equals(VCardConstants.PROPERTY_N)) { handleNProperty(propValueList); } else if (propName.equals(VCardConstants.PROPERTY_SORT_STRING)) { @@ -1016,8 +1014,8 @@ public class VCardEntry { */ private void constructDisplayName() { // FullName (created via "FN" or "NAME" field) is prefered. - if (!TextUtils.isEmpty(mFullName)) { - mDisplayName = mFullName; + if (!TextUtils.isEmpty(mFormattedName)) { + mDisplayName = mFormattedName; } else if (!(TextUtils.isEmpty(mFamilyName) && TextUtils.isEmpty(mGivenName))) { mDisplayName = VCardUtils.constructNameFromElements(mVCardType, mFamilyName, mMiddleName, mGivenName, mPrefix, mSuffix); @@ -1320,7 +1318,7 @@ public class VCardEntry { && TextUtils.isEmpty(mGivenName) && TextUtils.isEmpty(mPrefix) && TextUtils.isEmpty(mSuffix) - && TextUtils.isEmpty(mFullName) + && TextUtils.isEmpty(mFormattedName) && TextUtils.isEmpty(mPhoneticFamilyName) && TextUtils.isEmpty(mPhoneticMiddleName) && TextUtils.isEmpty(mPhoneticGivenName) @@ -1379,7 +1377,7 @@ public class VCardEntry { } public String getFullName() { - return mFullName; + return mFormattedName; } public String getPhoneticFamilyName() { diff --git a/core/java/android/pim/vcard/VCardEntryConstructor.java b/core/java/android/pim/vcard/VCardEntryConstructor.java index e3c691ac140fe..a0abae8c641d8 100644 --- a/core/java/android/pim/vcard/VCardEntryConstructor.java +++ b/core/java/android/pim/vcard/VCardEntryConstructor.java @@ -20,9 +20,7 @@ import android.text.TextUtils; import android.util.CharsetUtils; import android.util.Log; -import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Base64; -import org.apache.commons.codec.net.QuotedPrintableCodec; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; @@ -31,6 +29,23 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +/** + *

+ * The {@link VCardInterpreter} implementation which enables {@link VCardEntryHandler} objects + * to easily handle each vCard entry. + *

+ *

+ * This class understand details inside vCard and translates it to {@link VCardEntry}. + * Then the class throw it to {@link VCardEntryHandler} registered via + * {@link #addEntryHandler(VCardEntryHandler)}, so that all those registered objects + * are able to handle the {@link VCardEntry} object. + *

+ *

+ * If you want to know the detail inside vCard, it would be better to implement + * {@link VCardInterpreter} directly, instead of relying on this class and + * {@link VCardEntry} created by the object. + *

+ */ public class VCardEntryConstructor implements VCardInterpreter { private static String LOG_TAG = "VCardEntryConstructor"; @@ -48,27 +63,33 @@ public class VCardEntryConstructor implements VCardInterpreter { private final int mVCardType; private final Account mAccount; - /** For measuring performance. */ + // For measuring performance. private long mTimePushIntoContentResolver; - final private List mEntryHandlers = new ArrayList(); + private final List mEntryHandlers = new ArrayList(); public VCardEntryConstructor() { - this(null, false, VCardConfig.VCARD_TYPE_V21_GENERIC, null); + this(VCardConfig.VCARD_TYPE_V21_GENERIC, null, null, false); } public VCardEntryConstructor(final int vcardType) { - this(null, false, vcardType, null); + this(vcardType, null, null, false); } - public VCardEntryConstructor(final String inputCharset, - final int vcardType, final Account account) { - this(inputCharset, false, vcardType, account); + public VCardEntryConstructor(final int vcardType, final Account account) { + this(vcardType, account, null, false); } - public VCardEntryConstructor(final String inputCharset, - final boolean strictLineBreakParsing, final int vcardType, - final Account account) { + public VCardEntryConstructor(final int vcardType, final Account account, + final String inputCharset) { + this(vcardType, account, inputCharset, false); + } + + /** + * @hide + */ + public VCardEntryConstructor(final int vcardType, final Account account, + final String inputCharset, final boolean strictLineBreakParsing) { if (inputCharset != null) { mSourceCharset = inputCharset; } else { @@ -95,17 +116,11 @@ public class VCardEntryConstructor implements VCardInterpreter { } } - /** - * Called when the parse failed between {@link #startEntry()} and {@link #endEntry()}. - */ public void clear() { mCurrentVCardEntry = null; mCurrentProperty = new VCardEntry.Property(); } - /** - * Assume that VCard is not nested. In other words, this code does not accept - */ public void startEntry() { if (mCurrentVCardEntry != null) { Log.e(LOG_TAG, "Nested VCard code is not supported now."); @@ -211,6 +226,9 @@ public class VCardEntryConstructor implements VCardInterpreter { } } + /** + * @hide + */ public void showPerformanceInfo() { Log.d(LOG_TAG, "time for insert ContactStruct to database: " + mTimePushIntoContentResolver + " ms"); diff --git a/core/java/android/pim/vcard/VCardEntryHandler.java b/core/java/android/pim/vcard/VCardEntryHandler.java index 83a67fe2c6f87..56bf69d5d3717 100644 --- a/core/java/android/pim/vcard/VCardEntryHandler.java +++ b/core/java/android/pim/vcard/VCardEntryHandler.java @@ -16,8 +16,13 @@ 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}. + *

+ * The interface called by {@link VCardEntryConstructor}. + *

+ *

+ * This class is useful when you don't want to know vCard data in detail. If you want to know + * it, it would be better to consider using {@link VCardInterpreter}. + *

*/ public interface VCardEntryHandler { /** diff --git a/core/java/android/pim/vcard/VCardInterpreter.java b/core/java/android/pim/vcard/VCardInterpreter.java index b5237c066bf03..03704a22a962a 100644 --- a/core/java/android/pim/vcard/VCardInterpreter.java +++ b/core/java/android/pim/vcard/VCardInterpreter.java @@ -20,7 +20,7 @@ import java.util.List; /** *

* The interface which should be implemented by the classes which have to analyze each - * vCard entry more minutely than {@link VCardEntry} class analysis. + * vCard entry minutely. *

*

* Here, there are several terms specific to vCard (and this library). diff --git a/core/java/android/pim/vcard/VCardInterpreterCollection.java b/core/java/android/pim/vcard/VCardInterpreterCollection.java index 99f81f704d779..4952dc71c48ad 100644 --- a/core/java/android/pim/vcard/VCardInterpreterCollection.java +++ b/core/java/android/pim/vcard/VCardInterpreterCollection.java @@ -23,7 +23,7 @@ import java.util.List; * {@link VCardInterpreter} objects and make a user object treat them as one * {@link VCardInterpreter} object. */ -public class VCardInterpreterCollection implements VCardInterpreter { +public final class VCardInterpreterCollection implements VCardInterpreter { private final Collection mInterpreterCollection; public VCardInterpreterCollection(Collection interpreterCollection) { diff --git a/core/java/android/pim/vcard/VCardUtils.java b/core/java/android/pim/vcard/VCardUtils.java index 426d3b46e37d1..680ef6fa0f067 100644 --- a/core/java/android/pim/vcard/VCardUtils.java +++ b/core/java/android/pim/vcard/VCardUtils.java @@ -39,6 +39,7 @@ import java.util.Set; /** * Utilities for VCard handling codes. + * @hide */ public class VCardUtils { private static final String LOG_TAG = "VCardUtils"; @@ -247,10 +248,13 @@ public class VCardUtils { } /** + *

* Inserts postal data into the builder object. - * + *

+ *

* Note that the data structure of ContactsContract is different from that defined in vCard. * So some conversion may be performed in this method. + *

*/ public static void insertStructuredPostalDataUsingContactsStruct(int vcardType, final ContentProviderOperation.Builder builder, @@ -378,9 +382,13 @@ public class VCardUtils { } /** + *

* This is useful when checking the string should be encoded into quoted-printable * or not, which is required by vCard 2.1. + *

+ *

* See the definition of "7bit" in vCard 2.1 spec for more information. + *

*/ public static boolean containsOnlyNonCrLfPrintableAscii(final String...values) { if (values == null) { @@ -414,13 +422,16 @@ public class VCardUtils { new HashSet(Arrays.asList('[', ']', '=', ':', '.', ',', ' ')); /** + *

* This is useful since vCard 3.0 often requires the ("X-") properties and groups * should contain only alphabets, digits, and hyphen. - * + *

+ *

* Note: It is already known some devices (wrongly) outputs properties with characters * which should not be in the field. One example is "X-GOOGLE TALK". We accept * 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(final String...values) { if (values == null) { @@ -459,13 +470,13 @@ public class VCardUtils { } /** - *

+ *

* Returns true when the given String is categorized as "word" specified in vCard spec 2.1. - *

- *

- * vCard 2.1 specifies:
+ *

+ *

+ * vCard 2.1 specifies:
* word = <any printable 7bit us-ascii except []=:., > - *

+ *

*/ public static boolean isV21Word(final String value) { if (TextUtils.isEmpty(value)) { @@ -550,7 +561,7 @@ public class VCardUtils { //// The methods bellow may be used by unit test. /** - * @hide + * @hide */ public static String parseQuotedPrintable(String value, boolean strictLineBreaking, String sourceCharset, String targetCharset) { diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifier.java b/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifier.java index afaeafcf2fcf2..f2516edcf87f1 100644 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifier.java +++ b/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifier.java @@ -66,7 +66,7 @@ public class ContentValuesVerifier implements VCardEntryHandler { public void verify(InputStream is, int vCardType, final VCardParser vCardParser) throws IOException, VCardException { VCardEntryConstructor builder = - new VCardEntryConstructor(null, false, vCardType, null); + new VCardEntryConstructor(vCardType, null, null, false); builder.addEntryHandler(this); try { vCardParser.parse(is, builder); diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifierElem.java b/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifierElem.java index a25de03effc83..66d69b330d4cb 100644 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifierElem.java +++ b/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifierElem.java @@ -62,7 +62,7 @@ public class ContentValuesVerifierElem { vCardParser = new VCardParser_V21(); } VCardEntryConstructor builder = - new VCardEntryConstructor(null, false, vCardType, null); + new VCardEntryConstructor(vCardType, null, null, false); builder.addEntryHandler(mHandler); try { vCardParser.parse(is, builder); diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/VCardVerifier.java b/core/tests/coretests/src/android/pim/vcard/test_utils/VCardVerifier.java index 8c248cc47ec8d..5fb29426895c7 100644 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/VCardVerifier.java +++ b/core/tests/coretests/src/android/pim/vcard/test_utils/VCardVerifier.java @@ -106,7 +106,7 @@ public class VCardVerifier { mVerified = false; } - // Called by each import test. + // Should be called at the beginning of each import test. public void initForImportTest(int vcardType, int resId) { if (mInitialized) { mTestCase.fail("Already initialized"); @@ -118,7 +118,7 @@ public class VCardVerifier { mInitialized = true; } - // Called by each export test. + // Should be called at the beginning of each export test. public void initForExportTest(int vcardType) { initForExportTest(vcardType, "UTF-8"); }