Use vcard lib

Now the vcard code is available with LOCAL_SDK_VERSION=9.

Change-Id: I8aad414263a2971c3052b231e20c6e1ff129d5ca
diff --git a/Android.mk b/Android.mk
index 7fa60a0..d054c0c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_STATIC_JAVA_LIBRARIES := guava
+LOCAL_STATIC_JAVA_LIBRARIES := guava com.android.vcard
 
 # Only compile source java files in this apk.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/src/com/android/vcard/CharsetUtils.java b/src/com/android/vcard/CharsetUtils.java
deleted file mode 100644
index 4c85b29..0000000
--- a/src/com/android/vcard/CharsetUtils.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.vcard;
-
-import android.os.Build;
-import android.text.TextUtils;
-
-import java.nio.charset.Charset;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * <p>
- * A class containing utility methods related to character sets. This
- * class is primarily useful for code that wishes to be vendor-aware
- * in its interpretation of Japanese charset names (used in DoCoMo,
- * KDDI, and SoftBank).
- * </p>
- *
- * <p>
- * <b>Note:</b> Developers will need to add an appropriate mapping for
- * each vendor-specific charset. You may need to modify the C libraries
- * like icu4c in order to let Android support an additional charset.
- * </p>
- *
- * @hide
- */
-public final class CharsetUtils {
-    /**
-     * name of the vendor "DoCoMo". <b>Note:</b> This isn't a public
-     * constant, in order to keep this class from becoming a de facto
-     * reference list of vendor names.
-     */
-    private static final String VENDOR_DOCOMO = "docomo";
-    /**
-     * Name of the vendor "KDDI".
-     */
-    private static final String VENDOR_KDDI = "kddi";
-    /**
-     * Name of the vendor "SoftBank".
-     */
-    private static final String VENDOR_SOFTBANK = "softbank";
-
-    /**
-     * Represents one-to-one mapping from a vendor name to a charset specific to the vendor.
-     */
-    private static final Map<String, String> sVendorShiftJisMap = new HashMap<String, String>();
-
-    static {
-        // These variants of Shift_JIS come from icu's mapping data (convrtrs.txt)
-        sVendorShiftJisMap.put(VENDOR_DOCOMO, "docomo-shift_jis-2007");
-        sVendorShiftJisMap.put(VENDOR_KDDI, "kddi-shift_jis-2007");
-        sVendorShiftJisMap.put(VENDOR_SOFTBANK, "softbank-shift_jis-2007");
-    }
-
-    /**
-     * This class is uninstantiable.
-     */
-    private CharsetUtils() {
-        // This space intentionally left blank.
-    }
-
-    /**
-     * Returns the name of the vendor-specific character set
-     * corresponding to the given original character set name and
-     * vendor. If there is no vendor-specific character set for the
-     * given name/vendor pair, this returns the original character set name.
-     *
-     * @param charsetName the base character set name
-     * @param vendor the vendor to specialize for. All characters should be lower-cased.
-     * @return the specialized character set name, or {@code charsetName} if
-     * there is no specialized name
-     */
-    public static String nameForVendor(String charsetName, String vendor) {
-        if (!TextUtils.isEmpty(charsetName) && !TextUtils.isEmpty(vendor)) {
-            // You can add your own mapping here.
-            if (isShiftJis(charsetName)) {
-                final String vendorShiftJis = sVendorShiftJisMap.get(vendor);
-                if (vendorShiftJis != null) {
-                    return vendorShiftJis;
-                }
-            }
-        }
-
-        return charsetName;
-    }
-
-    /**
-     * Returns the name of the vendor-specific character set
-     * corresponding to the given original character set name and the
-     * default vendor (that is, the targeted vendor of the device this
-     * code is running on). This method merely calls through to
-     * {@link #nameForVendor(String,String)}, passing the default vendor
-     * as the second argument.
-     *
-     * @param charsetName the base character set name
-     * @return the specialized character set name, or {@code charsetName} if
-     * there is no specialized name
-     */
-    public static String nameForDefaultVendor(String charsetName) {
-        return nameForVendor(charsetName, getDefaultVendor());
-    }
-
-    /**
-     * Returns the vendor-specific character set corresponding to the
-     * given original character set name and vendor. If there is no
-     * vendor-specific character set for the given name/vendor pair,
-     * this returns the character set corresponding to the original
-     * name. The vendor name is matched case-insensitively. This
-     * method merely calls {@code Charset.forName()} on a name
-     * transformed by a call to {@link #nameForVendor(String,String)}.
-     *
-     * @param charsetName the base character set name
-     * @param vendor the vendor to specialize for
-     * @return the specialized character set, or the one corresponding
-     * directly to {@code charsetName} if there is no specialized
-     * variant
-     * @throws UnsupportedCharsetException thrown if the named character
-     * set is not supported by the system
-     * @throws IllegalCharsetNameException thrown if {@code charsetName}
-     * has invalid syntax
-     */
-    public static Charset charsetForVendor(String charsetName, String vendor)
-            throws UnsupportedCharsetException, IllegalCharsetNameException {
-        charsetName = nameForVendor(charsetName, vendor);
-        return Charset.forName(charsetName);
-    }
-
-    /**
-     * Returns the vendor-specific character set corresponding to the
-     * given original character set name and default vendor (that is,
-     * the targeted vendor of the device this code is running on).
-     * This method merely calls through to {@link
-     * #charsetForVendor(String,String)}, passing the default vendor
-     * as the second argument.
-     *
-     * @param charsetName the base character set name
-     * @return the specialized character set, or the one corresponding
-     * directly to {@code charsetName} if there is no specialized
-     * variant
-     * @throws UnsupportedCharsetException thrown if the named character
-     * set is not supported by the system
-     * @throws IllegalCharsetNameException thrown if {@code charsetName}
-     * has invalid syntax
-     */
-    public static Charset charsetForVendor(String charsetName)
-            throws UnsupportedCharsetException, IllegalCharsetNameException {
-        return charsetForVendor(charsetName, getDefaultVendor());
-    }
-
-    /**
-     * Returns whether the given character set name indicates the Shift-JIS
-     * encoding. Returns false if the name is null.
-     *
-     * @param charsetName the character set name
-     * @return {@code true} if the name corresponds to Shift-JIS or
-     * {@code false} if not
-     */
-    private static boolean isShiftJis(String charsetName) {
-        // Bail quickly if the length doesn't match.
-        if (charsetName == null) {
-            return false;
-        }
-        int length = charsetName.length();
-        if (length != 4 && length != 9) {
-            return false;
-        }
-
-        return charsetName.equalsIgnoreCase("shift_jis")
-            || charsetName.equalsIgnoreCase("shift-jis")
-            || charsetName.equalsIgnoreCase("sjis");
-    }
-
-    /**
-     * Gets the default vendor for this build.
-     *
-     * @return the default vendor name
-     */
-    private static String getDefaultVendor() {
-        return Build.BRAND;
-    }
-}
diff --git a/src/com/android/vcard/JapaneseUtils.java b/src/com/android/vcard/JapaneseUtils.java
deleted file mode 100644
index 5b44944..0000000
--- a/src/com/android/vcard/JapaneseUtils.java
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.vcard;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * TextUtils especially for Japanese.
- */
-/* package */ class JapaneseUtils {
-    static private final Map<Character, String> sHalfWidthMap =
-        new HashMap<Character, String>();
-
-    static {
-        sHalfWidthMap.put('\u3001', "\uFF64");
-        sHalfWidthMap.put('\u3002', "\uFF61");
-        sHalfWidthMap.put('\u300C', "\uFF62");
-        sHalfWidthMap.put('\u300D', "\uFF63");
-        sHalfWidthMap.put('\u301C', "~");
-        sHalfWidthMap.put('\u3041', "\uFF67");
-        sHalfWidthMap.put('\u3042', "\uFF71");
-        sHalfWidthMap.put('\u3043', "\uFF68");
-        sHalfWidthMap.put('\u3044', "\uFF72");
-        sHalfWidthMap.put('\u3045', "\uFF69");
-        sHalfWidthMap.put('\u3046', "\uFF73");
-        sHalfWidthMap.put('\u3047', "\uFF6A");
-        sHalfWidthMap.put('\u3048', "\uFF74");
-        sHalfWidthMap.put('\u3049', "\uFF6B");
-        sHalfWidthMap.put('\u304A', "\uFF75");
-        sHalfWidthMap.put('\u304B', "\uFF76");
-        sHalfWidthMap.put('\u304C', "\uFF76\uFF9E");
-        sHalfWidthMap.put('\u304D', "\uFF77");
-        sHalfWidthMap.put('\u304E', "\uFF77\uFF9E");
-        sHalfWidthMap.put('\u304F', "\uFF78");
-        sHalfWidthMap.put('\u3050', "\uFF78\uFF9E");
-        sHalfWidthMap.put('\u3051', "\uFF79");
-        sHalfWidthMap.put('\u3052', "\uFF79\uFF9E");
-        sHalfWidthMap.put('\u3053', "\uFF7A");
-        sHalfWidthMap.put('\u3054', "\uFF7A\uFF9E");
-        sHalfWidthMap.put('\u3055', "\uFF7B");
-        sHalfWidthMap.put('\u3056', "\uFF7B\uFF9E");
-        sHalfWidthMap.put('\u3057', "\uFF7C");
-        sHalfWidthMap.put('\u3058', "\uFF7C\uFF9E");
-        sHalfWidthMap.put('\u3059', "\uFF7D");
-        sHalfWidthMap.put('\u305A', "\uFF7D\uFF9E");
-        sHalfWidthMap.put('\u305B', "\uFF7E");
-        sHalfWidthMap.put('\u305C', "\uFF7E\uFF9E");
-        sHalfWidthMap.put('\u305D', "\uFF7F");
-        sHalfWidthMap.put('\u305E', "\uFF7F\uFF9E");
-        sHalfWidthMap.put('\u305F', "\uFF80");
-        sHalfWidthMap.put('\u3060', "\uFF80\uFF9E");
-        sHalfWidthMap.put('\u3061', "\uFF81");
-        sHalfWidthMap.put('\u3062', "\uFF81\uFF9E");
-        sHalfWidthMap.put('\u3063', "\uFF6F");
-        sHalfWidthMap.put('\u3064', "\uFF82");
-        sHalfWidthMap.put('\u3065', "\uFF82\uFF9E");
-        sHalfWidthMap.put('\u3066', "\uFF83");
-        sHalfWidthMap.put('\u3067', "\uFF83\uFF9E");
-        sHalfWidthMap.put('\u3068', "\uFF84");
-        sHalfWidthMap.put('\u3069', "\uFF84\uFF9E");
-        sHalfWidthMap.put('\u306A', "\uFF85");
-        sHalfWidthMap.put('\u306B', "\uFF86");
-        sHalfWidthMap.put('\u306C', "\uFF87");
-        sHalfWidthMap.put('\u306D', "\uFF88");
-        sHalfWidthMap.put('\u306E', "\uFF89");
-        sHalfWidthMap.put('\u306F', "\uFF8A");
-        sHalfWidthMap.put('\u3070', "\uFF8A\uFF9E");
-        sHalfWidthMap.put('\u3071', "\uFF8A\uFF9F");
-        sHalfWidthMap.put('\u3072', "\uFF8B");
-        sHalfWidthMap.put('\u3073', "\uFF8B\uFF9E");
-        sHalfWidthMap.put('\u3074', "\uFF8B\uFF9F");
-        sHalfWidthMap.put('\u3075', "\uFF8C");
-        sHalfWidthMap.put('\u3076', "\uFF8C\uFF9E");
-        sHalfWidthMap.put('\u3077', "\uFF8C\uFF9F");
-        sHalfWidthMap.put('\u3078', "\uFF8D");
-        sHalfWidthMap.put('\u3079', "\uFF8D\uFF9E");
-        sHalfWidthMap.put('\u307A', "\uFF8D\uFF9F");
-        sHalfWidthMap.put('\u307B', "\uFF8E");
-        sHalfWidthMap.put('\u307C', "\uFF8E\uFF9E");
-        sHalfWidthMap.put('\u307D', "\uFF8E\uFF9F");
-        sHalfWidthMap.put('\u307E', "\uFF8F");
-        sHalfWidthMap.put('\u307F', "\uFF90");
-        sHalfWidthMap.put('\u3080', "\uFF91");
-        sHalfWidthMap.put('\u3081', "\uFF92");
-        sHalfWidthMap.put('\u3082', "\uFF93");
-        sHalfWidthMap.put('\u3083', "\uFF6C");
-        sHalfWidthMap.put('\u3084', "\uFF94");
-        sHalfWidthMap.put('\u3085', "\uFF6D");
-        sHalfWidthMap.put('\u3086', "\uFF95");
-        sHalfWidthMap.put('\u3087', "\uFF6E");
-        sHalfWidthMap.put('\u3088', "\uFF96");
-        sHalfWidthMap.put('\u3089', "\uFF97");
-        sHalfWidthMap.put('\u308A', "\uFF98");
-        sHalfWidthMap.put('\u308B', "\uFF99");
-        sHalfWidthMap.put('\u308C', "\uFF9A");
-        sHalfWidthMap.put('\u308D', "\uFF9B");
-        sHalfWidthMap.put('\u308E', "\uFF9C");
-        sHalfWidthMap.put('\u308F', "\uFF9C");
-        sHalfWidthMap.put('\u3090', "\uFF72");
-        sHalfWidthMap.put('\u3091', "\uFF74");
-        sHalfWidthMap.put('\u3092', "\uFF66");
-        sHalfWidthMap.put('\u3093', "\uFF9D");
-        sHalfWidthMap.put('\u309B', "\uFF9E");
-        sHalfWidthMap.put('\u309C', "\uFF9F");
-        sHalfWidthMap.put('\u30A1', "\uFF67");
-        sHalfWidthMap.put('\u30A2', "\uFF71");
-        sHalfWidthMap.put('\u30A3', "\uFF68");
-        sHalfWidthMap.put('\u30A4', "\uFF72");
-        sHalfWidthMap.put('\u30A5', "\uFF69");
-        sHalfWidthMap.put('\u30A6', "\uFF73");
-        sHalfWidthMap.put('\u30A7', "\uFF6A");
-        sHalfWidthMap.put('\u30A8', "\uFF74");
-        sHalfWidthMap.put('\u30A9', "\uFF6B");
-        sHalfWidthMap.put('\u30AA', "\uFF75");
-        sHalfWidthMap.put('\u30AB', "\uFF76");
-        sHalfWidthMap.put('\u30AC', "\uFF76\uFF9E");
-        sHalfWidthMap.put('\u30AD', "\uFF77");
-        sHalfWidthMap.put('\u30AE', "\uFF77\uFF9E");
-        sHalfWidthMap.put('\u30AF', "\uFF78");
-        sHalfWidthMap.put('\u30B0', "\uFF78\uFF9E");
-        sHalfWidthMap.put('\u30B1', "\uFF79");
-        sHalfWidthMap.put('\u30B2', "\uFF79\uFF9E");
-        sHalfWidthMap.put('\u30B3', "\uFF7A");
-        sHalfWidthMap.put('\u30B4', "\uFF7A\uFF9E");
-        sHalfWidthMap.put('\u30B5', "\uFF7B");
-        sHalfWidthMap.put('\u30B6', "\uFF7B\uFF9E");
-        sHalfWidthMap.put('\u30B7', "\uFF7C");
-        sHalfWidthMap.put('\u30B8', "\uFF7C\uFF9E");
-        sHalfWidthMap.put('\u30B9', "\uFF7D");
-        sHalfWidthMap.put('\u30BA', "\uFF7D\uFF9E");
-        sHalfWidthMap.put('\u30BB', "\uFF7E");
-        sHalfWidthMap.put('\u30BC', "\uFF7E\uFF9E");
-        sHalfWidthMap.put('\u30BD', "\uFF7F");
-        sHalfWidthMap.put('\u30BE', "\uFF7F\uFF9E");
-        sHalfWidthMap.put('\u30BF', "\uFF80");
-        sHalfWidthMap.put('\u30C0', "\uFF80\uFF9E");
-        sHalfWidthMap.put('\u30C1', "\uFF81");
-        sHalfWidthMap.put('\u30C2', "\uFF81\uFF9E");
-        sHalfWidthMap.put('\u30C3', "\uFF6F");
-        sHalfWidthMap.put('\u30C4', "\uFF82");
-        sHalfWidthMap.put('\u30C5', "\uFF82\uFF9E");
-        sHalfWidthMap.put('\u30C6', "\uFF83");
-        sHalfWidthMap.put('\u30C7', "\uFF83\uFF9E");
-        sHalfWidthMap.put('\u30C8', "\uFF84");
-        sHalfWidthMap.put('\u30C9', "\uFF84\uFF9E");
-        sHalfWidthMap.put('\u30CA', "\uFF85");
-        sHalfWidthMap.put('\u30CB', "\uFF86");
-        sHalfWidthMap.put('\u30CC', "\uFF87");
-        sHalfWidthMap.put('\u30CD', "\uFF88");
-        sHalfWidthMap.put('\u30CE', "\uFF89");
-        sHalfWidthMap.put('\u30CF', "\uFF8A");
-        sHalfWidthMap.put('\u30D0', "\uFF8A\uFF9E");
-        sHalfWidthMap.put('\u30D1', "\uFF8A\uFF9F");
-        sHalfWidthMap.put('\u30D2', "\uFF8B");
-        sHalfWidthMap.put('\u30D3', "\uFF8B\uFF9E");
-        sHalfWidthMap.put('\u30D4', "\uFF8B\uFF9F");
-        sHalfWidthMap.put('\u30D5', "\uFF8C");
-        sHalfWidthMap.put('\u30D6', "\uFF8C\uFF9E");
-        sHalfWidthMap.put('\u30D7', "\uFF8C\uFF9F");
-        sHalfWidthMap.put('\u30D8', "\uFF8D");
-        sHalfWidthMap.put('\u30D9', "\uFF8D\uFF9E");
-        sHalfWidthMap.put('\u30DA', "\uFF8D\uFF9F");
-        sHalfWidthMap.put('\u30DB', "\uFF8E");
-        sHalfWidthMap.put('\u30DC', "\uFF8E\uFF9E");
-        sHalfWidthMap.put('\u30DD', "\uFF8E\uFF9F");
-        sHalfWidthMap.put('\u30DE', "\uFF8F");
-        sHalfWidthMap.put('\u30DF', "\uFF90");
-        sHalfWidthMap.put('\u30E0', "\uFF91");
-        sHalfWidthMap.put('\u30E1', "\uFF92");
-        sHalfWidthMap.put('\u30E2', "\uFF93");
-        sHalfWidthMap.put('\u30E3', "\uFF6C");
-        sHalfWidthMap.put('\u30E4', "\uFF94");
-        sHalfWidthMap.put('\u30E5', "\uFF6D");
-        sHalfWidthMap.put('\u30E6', "\uFF95");
-        sHalfWidthMap.put('\u30E7', "\uFF6E");
-        sHalfWidthMap.put('\u30E8', "\uFF96");
-        sHalfWidthMap.put('\u30E9', "\uFF97");
-        sHalfWidthMap.put('\u30EA', "\uFF98");
-        sHalfWidthMap.put('\u30EB', "\uFF99");
-        sHalfWidthMap.put('\u30EC', "\uFF9A");
-        sHalfWidthMap.put('\u30ED', "\uFF9B");
-        sHalfWidthMap.put('\u30EE', "\uFF9C");
-        sHalfWidthMap.put('\u30EF', "\uFF9C");
-        sHalfWidthMap.put('\u30F0', "\uFF72");
-        sHalfWidthMap.put('\u30F1', "\uFF74");
-        sHalfWidthMap.put('\u30F2', "\uFF66");
-        sHalfWidthMap.put('\u30F3', "\uFF9D");
-        sHalfWidthMap.put('\u30F4', "\uFF73\uFF9E");
-        sHalfWidthMap.put('\u30F5', "\uFF76");
-        sHalfWidthMap.put('\u30F6', "\uFF79");
-        sHalfWidthMap.put('\u30FB', "\uFF65");
-        sHalfWidthMap.put('\u30FC', "\uFF70");
-        sHalfWidthMap.put('\uFF01', "!");
-        sHalfWidthMap.put('\uFF02', "\"");
-        sHalfWidthMap.put('\uFF03', "#");
-        sHalfWidthMap.put('\uFF04', "$");
-        sHalfWidthMap.put('\uFF05', "%");
-        sHalfWidthMap.put('\uFF06', "&");
-        sHalfWidthMap.put('\uFF07', "'");
-        sHalfWidthMap.put('\uFF08', "(");
-        sHalfWidthMap.put('\uFF09', ")");
-        sHalfWidthMap.put('\uFF0A', "*");
-        sHalfWidthMap.put('\uFF0B', "+");
-        sHalfWidthMap.put('\uFF0C', ",");
-        sHalfWidthMap.put('\uFF0D', "-");
-        sHalfWidthMap.put('\uFF0E', ".");
-        sHalfWidthMap.put('\uFF0F', "/");
-        sHalfWidthMap.put('\uFF10', "0");
-        sHalfWidthMap.put('\uFF11', "1");
-        sHalfWidthMap.put('\uFF12', "2");
-        sHalfWidthMap.put('\uFF13', "3");
-        sHalfWidthMap.put('\uFF14', "4");
-        sHalfWidthMap.put('\uFF15', "5");
-        sHalfWidthMap.put('\uFF16', "6");
-        sHalfWidthMap.put('\uFF17', "7");
-        sHalfWidthMap.put('\uFF18', "8");
-        sHalfWidthMap.put('\uFF19', "9");
-        sHalfWidthMap.put('\uFF1A', ":");
-        sHalfWidthMap.put('\uFF1B', ";");
-        sHalfWidthMap.put('\uFF1C', "<");
-        sHalfWidthMap.put('\uFF1D', "=");
-        sHalfWidthMap.put('\uFF1E', ">");
-        sHalfWidthMap.put('\uFF1F', "?");
-        sHalfWidthMap.put('\uFF20', "@");
-        sHalfWidthMap.put('\uFF21', "A");
-        sHalfWidthMap.put('\uFF22', "B");
-        sHalfWidthMap.put('\uFF23', "C");
-        sHalfWidthMap.put('\uFF24', "D");
-        sHalfWidthMap.put('\uFF25', "E");
-        sHalfWidthMap.put('\uFF26', "F");
-        sHalfWidthMap.put('\uFF27', "G");
-        sHalfWidthMap.put('\uFF28', "H");
-        sHalfWidthMap.put('\uFF29', "I");
-        sHalfWidthMap.put('\uFF2A', "J");
-        sHalfWidthMap.put('\uFF2B', "K");
-        sHalfWidthMap.put('\uFF2C', "L");
-        sHalfWidthMap.put('\uFF2D', "M");
-        sHalfWidthMap.put('\uFF2E', "N");
-        sHalfWidthMap.put('\uFF2F', "O");
-        sHalfWidthMap.put('\uFF30', "P");
-        sHalfWidthMap.put('\uFF31', "Q");
-        sHalfWidthMap.put('\uFF32', "R");
-        sHalfWidthMap.put('\uFF33', "S");
-        sHalfWidthMap.put('\uFF34', "T");
-        sHalfWidthMap.put('\uFF35', "U");
-        sHalfWidthMap.put('\uFF36', "V");
-        sHalfWidthMap.put('\uFF37', "W");
-        sHalfWidthMap.put('\uFF38', "X");
-        sHalfWidthMap.put('\uFF39', "Y");
-        sHalfWidthMap.put('\uFF3A', "Z");
-        sHalfWidthMap.put('\uFF3B', "[");
-        sHalfWidthMap.put('\uFF3C', "\\");
-        sHalfWidthMap.put('\uFF3D', "]");
-        sHalfWidthMap.put('\uFF3E', "^");
-        sHalfWidthMap.put('\uFF3F', "_");
-        sHalfWidthMap.put('\uFF41', "a");
-        sHalfWidthMap.put('\uFF42', "b");
-        sHalfWidthMap.put('\uFF43', "c");
-        sHalfWidthMap.put('\uFF44', "d");
-        sHalfWidthMap.put('\uFF45', "e");
-        sHalfWidthMap.put('\uFF46', "f");
-        sHalfWidthMap.put('\uFF47', "g");
-        sHalfWidthMap.put('\uFF48', "h");
-        sHalfWidthMap.put('\uFF49', "i");
-        sHalfWidthMap.put('\uFF4A', "j");
-        sHalfWidthMap.put('\uFF4B', "k");
-        sHalfWidthMap.put('\uFF4C', "l");
-        sHalfWidthMap.put('\uFF4D', "m");
-        sHalfWidthMap.put('\uFF4E', "n");
-        sHalfWidthMap.put('\uFF4F', "o");
-        sHalfWidthMap.put('\uFF50', "p");
-        sHalfWidthMap.put('\uFF51', "q");
-        sHalfWidthMap.put('\uFF52', "r");
-        sHalfWidthMap.put('\uFF53', "s");
-        sHalfWidthMap.put('\uFF54', "t");
-        sHalfWidthMap.put('\uFF55', "u");
-        sHalfWidthMap.put('\uFF56', "v");
-        sHalfWidthMap.put('\uFF57', "w");
-        sHalfWidthMap.put('\uFF58', "x");
-        sHalfWidthMap.put('\uFF59', "y");
-        sHalfWidthMap.put('\uFF5A', "z");
-        sHalfWidthMap.put('\uFF5B', "{");
-        sHalfWidthMap.put('\uFF5C', "|");
-        sHalfWidthMap.put('\uFF5D', "}");
-        sHalfWidthMap.put('\uFF5E', "~");
-        sHalfWidthMap.put('\uFF61', "\uFF61");
-        sHalfWidthMap.put('\uFF62', "\uFF62");
-        sHalfWidthMap.put('\uFF63', "\uFF63");
-        sHalfWidthMap.put('\uFF64', "\uFF64");
-        sHalfWidthMap.put('\uFF65', "\uFF65");
-        sHalfWidthMap.put('\uFF66', "\uFF66");
-        sHalfWidthMap.put('\uFF67', "\uFF67");
-        sHalfWidthMap.put('\uFF68', "\uFF68");
-        sHalfWidthMap.put('\uFF69', "\uFF69");
-        sHalfWidthMap.put('\uFF6A', "\uFF6A");
-        sHalfWidthMap.put('\uFF6B', "\uFF6B");
-        sHalfWidthMap.put('\uFF6C', "\uFF6C");
-        sHalfWidthMap.put('\uFF6D', "\uFF6D");
-        sHalfWidthMap.put('\uFF6E', "\uFF6E");
-        sHalfWidthMap.put('\uFF6F', "\uFF6F");
-        sHalfWidthMap.put('\uFF70', "\uFF70");
-        sHalfWidthMap.put('\uFF71', "\uFF71");
-        sHalfWidthMap.put('\uFF72', "\uFF72");
-        sHalfWidthMap.put('\uFF73', "\uFF73");
-        sHalfWidthMap.put('\uFF74', "\uFF74");
-        sHalfWidthMap.put('\uFF75', "\uFF75");
-        sHalfWidthMap.put('\uFF76', "\uFF76");
-        sHalfWidthMap.put('\uFF77', "\uFF77");
-        sHalfWidthMap.put('\uFF78', "\uFF78");
-        sHalfWidthMap.put('\uFF79', "\uFF79");
-        sHalfWidthMap.put('\uFF7A', "\uFF7A");
-        sHalfWidthMap.put('\uFF7B', "\uFF7B");
-        sHalfWidthMap.put('\uFF7C', "\uFF7C");
-        sHalfWidthMap.put('\uFF7D', "\uFF7D");
-        sHalfWidthMap.put('\uFF7E', "\uFF7E");
-        sHalfWidthMap.put('\uFF7F', "\uFF7F");
-        sHalfWidthMap.put('\uFF80', "\uFF80");
-        sHalfWidthMap.put('\uFF81', "\uFF81");
-        sHalfWidthMap.put('\uFF82', "\uFF82");
-        sHalfWidthMap.put('\uFF83', "\uFF83");
-        sHalfWidthMap.put('\uFF84', "\uFF84");
-        sHalfWidthMap.put('\uFF85', "\uFF85");
-        sHalfWidthMap.put('\uFF86', "\uFF86");
-        sHalfWidthMap.put('\uFF87', "\uFF87");
-        sHalfWidthMap.put('\uFF88', "\uFF88");
-        sHalfWidthMap.put('\uFF89', "\uFF89");
-        sHalfWidthMap.put('\uFF8A', "\uFF8A");
-        sHalfWidthMap.put('\uFF8B', "\uFF8B");
-        sHalfWidthMap.put('\uFF8C', "\uFF8C");
-        sHalfWidthMap.put('\uFF8D', "\uFF8D");
-        sHalfWidthMap.put('\uFF8E', "\uFF8E");
-        sHalfWidthMap.put('\uFF8F', "\uFF8F");
-        sHalfWidthMap.put('\uFF90', "\uFF90");
-        sHalfWidthMap.put('\uFF91', "\uFF91");
-        sHalfWidthMap.put('\uFF92', "\uFF92");
-        sHalfWidthMap.put('\uFF93', "\uFF93");
-        sHalfWidthMap.put('\uFF94', "\uFF94");
-        sHalfWidthMap.put('\uFF95', "\uFF95");
-        sHalfWidthMap.put('\uFF96', "\uFF96");
-        sHalfWidthMap.put('\uFF97', "\uFF97");
-        sHalfWidthMap.put('\uFF98', "\uFF98");
-        sHalfWidthMap.put('\uFF99', "\uFF99");
-        sHalfWidthMap.put('\uFF9A', "\uFF9A");
-        sHalfWidthMap.put('\uFF9B', "\uFF9B");
-        sHalfWidthMap.put('\uFF9C', "\uFF9C");
-        sHalfWidthMap.put('\uFF9D', "\uFF9D");
-        sHalfWidthMap.put('\uFF9E', "\uFF9E");
-        sHalfWidthMap.put('\uFF9F', "\uFF9F");
-        sHalfWidthMap.put('\uFFE5', "\u005C\u005C");
-    }
-
-    /**
-     * Returns half-width version of that character if possible. Returns null if not possible
-     * @param ch input character
-     * @return CharSequence object if the mapping for ch exists. Return null otherwise.
-     */
-    public static String tryGetHalfWidthText(final char ch) {
-        if (sHalfWidthMap.containsKey(ch)) {
-            return sHalfWidthMap.get(ch);
-        } else {
-            return null;
-        }
-    }
-}
diff --git a/src/com/android/vcard/VCardBuilder.java b/src/com/android/vcard/VCardBuilder.java
deleted file mode 100644
index c16aad7..0000000
--- a/src/com/android/vcard/VCardBuilder.java
+++ /dev/null
@@ -1,2208 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.android.vcard;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Event;
-import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Nickname;
-import android.provider.ContactsContract.CommonDataKinds.Note;
-import android.provider.ContactsContract.CommonDataKinds.Organization;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.CommonDataKinds.Relation;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.provider.ContactsContract.CommonDataKinds.Website;
-import android.telephony.PhoneNumberUtils;
-import android.text.TextUtils;
-import android.util.Base64;
-//import android.util.CharsetUtils;
-import android.util.Log;
-
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.UnsupportedCharsetException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * <p>
- * The class which lets users create their own vCard String. Typical usage is as follows:
- * </p>
- * <pre class="prettyprint">final VCardBuilder builder = new VCardBuilder(vcardType);
- * builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE))
- *     .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE))
- *     .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE))
- *     .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE))
- *     .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE))
- *     .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE))
- *     .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE))
- *     .appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE))
- *     .appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE))
- *     .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE))
- *     .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE))
- *     .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE));
- * return builder.toString();</pre>
- */
-public class VCardBuilder {
-    private static final String LOG_TAG = "VCardBuilder";
-
-    // If you add the other element, please check all the columns are able to be
-    // converted to String.
-    //
-    // e.g. BLOB is not what we can handle here now.
-    private static final Set<String> sAllowedAndroidPropertySet =
-            Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
-                    Nickname.CONTENT_ITEM_TYPE, Event.CONTENT_ITEM_TYPE,
-                    Relation.CONTENT_ITEM_TYPE)));
-
-    public static final int DEFAULT_PHONE_TYPE = Phone.TYPE_HOME;
-    public static final int DEFAULT_POSTAL_TYPE = StructuredPostal.TYPE_HOME;
-    public static final int DEFAULT_EMAIL_TYPE = Email.TYPE_OTHER;
-
-    private static final String VCARD_DATA_VCARD = "VCARD";
-    private static final String VCARD_DATA_PUBLIC = "PUBLIC";
-
-    private static final String VCARD_PARAM_SEPARATOR = ";";
-    private static final String VCARD_END_OF_LINE = "\r\n";
-    private static final String VCARD_DATA_SEPARATOR = ":";
-    private static final String VCARD_ITEM_SEPARATOR = ";";
-    private static final String VCARD_WS = " ";
-    private static final String VCARD_PARAM_EQUAL = "=";
-
-    private static final String VCARD_PARAM_ENCODING_QP =
-            "ENCODING=" + VCardConstants.PARAM_ENCODING_QP;
-    private static final String VCARD_PARAM_ENCODING_BASE64_V21 =
-            "ENCODING=" + VCardConstants.PARAM_ENCODING_BASE64;
-    private static final String VCARD_PARAM_ENCODING_BASE64_AS_B =
-            "ENCODING=" + VCardConstants.PARAM_ENCODING_B;
-
-    private static final String SHIFT_JIS = "SHIFT_JIS";
-
-    private final int mVCardType;
-
-    private final boolean mIsV30OrV40;
-    private final boolean mIsJapaneseMobilePhone;
-    private final boolean mOnlyOneNoteFieldIsAvailable;
-    private final boolean mIsDoCoMo;
-    private final boolean mShouldUseQuotedPrintable;
-    private final boolean mUsesAndroidProperty;
-    private final boolean mUsesDefactProperty;
-    private final boolean mAppendTypeParamName;
-    private final boolean mRefrainsQPToNameProperties;
-    private final boolean mNeedsToConvertPhoneticString;
-
-    private final boolean mShouldAppendCharsetParam;
-
-    private final String mCharset;
-    private final String mVCardCharsetParameter;
-
-    private StringBuilder mBuilder;
-    private boolean mEndAppended;
-
-    public VCardBuilder(final int vcardType) {
-        // Default charset should be used
-        this(vcardType, null);
-    }
-
-    /**
-     * @param vcardType
-     * @param charset If null, we use default charset for export.
-     * @hide
-     */
-    public VCardBuilder(final int vcardType, String charset) {
-        mVCardType = vcardType;
-
-        if (VCardConfig.isVersion40(vcardType)) {
-            Log.w(LOG_TAG, "Should not use vCard 4.0 when building vCard. " +
-                    "It is not officially published yet.");
-        }
-
-        mIsV30OrV40 = VCardConfig.isVersion30(vcardType) || VCardConfig.isVersion40(vcardType);
-        mShouldUseQuotedPrintable = VCardConfig.shouldUseQuotedPrintable(vcardType);
-        mIsDoCoMo = VCardConfig.isDoCoMo(vcardType);
-        mIsJapaneseMobilePhone = VCardConfig.needsToConvertPhoneticString(vcardType);
-        mOnlyOneNoteFieldIsAvailable = VCardConfig.onlyOneNoteFieldIsAvailable(vcardType);
-        mUsesAndroidProperty = VCardConfig.usesAndroidSpecificProperty(vcardType);
-        mUsesDefactProperty = VCardConfig.usesDefactProperty(vcardType);
-        mRefrainsQPToNameProperties = VCardConfig.shouldRefrainQPToNameProperties(vcardType);
-        mAppendTypeParamName = VCardConfig.appendTypeParamName(vcardType);
-        mNeedsToConvertPhoneticString = VCardConfig.needsToConvertPhoneticString(vcardType);
-
-        // vCard 2.1 requires charset.
-        // vCard 3.0 does not allow it but we found some devices use it to determine
-        // the exact charset.
-        // We currently append it only when charset other than UTF_8 is used.
-        mShouldAppendCharsetParam =
-                !(VCardConfig.isVersion30(vcardType) && "UTF-8".equalsIgnoreCase(charset));
-
-        if (VCardConfig.isDoCoMo(vcardType)) {
-            if (!SHIFT_JIS.equalsIgnoreCase(charset)) {
-                /* Log.w(LOG_TAG,
-                        "The charset \"" + charset + "\" is used while "
-                        + SHIFT_JIS + " is needed to be used."); */
-                if (TextUtils.isEmpty(charset)) {
-                    mCharset = SHIFT_JIS;
-                } else {
-                    try {
-                        charset = CharsetUtils.charsetForVendor(charset).name();
-                    } catch (UnsupportedCharsetException e) {
-                        Log.i(LOG_TAG,
-                                "Career-specific \"" + charset + "\" was not found (as usual). "
-                                + "Use it as is.");
-                    }
-                    mCharset = charset;
-                }
-            } else {
-                if (mIsDoCoMo) {
-                    try {
-                        charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name();
-                    } catch (UnsupportedCharsetException e) {
-                        Log.e(LOG_TAG,
-                                "DoCoMo-specific SHIFT_JIS was not found. "
-                                + "Use SHIFT_JIS as is.");
-                        charset = SHIFT_JIS;
-                    }
-                } else {
-                    try {
-                        charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name();
-                    } catch (UnsupportedCharsetException e) {
-                        Log.e(LOG_TAG,
-                                "Career-specific SHIFT_JIS was not found. "
-                                + "Use SHIFT_JIS as is.");
-                        charset = SHIFT_JIS;
-                    }
-                }
-                mCharset = charset;
-            }
-            mVCardCharsetParameter = "CHARSET=" + SHIFT_JIS;
-        } else {
-            if (TextUtils.isEmpty(charset)) {
-                Log.i(LOG_TAG,
-                        "Use the charset \"" + VCardConfig.DEFAULT_EXPORT_CHARSET
-                        + "\" for export.");
-                mCharset = VCardConfig.DEFAULT_EXPORT_CHARSET;
-                mVCardCharsetParameter = "CHARSET=" + VCardConfig.DEFAULT_EXPORT_CHARSET;
-            } else {
-                try {
-                    charset = CharsetUtils.charsetForVendor(charset).name();
-                } catch (UnsupportedCharsetException e) {
-                    Log.i(LOG_TAG,
-                            "Career-specific \"" + charset + "\" was not found (as usual). "
-                            + "Use it as is.");
-                }
-                mCharset = charset;
-                mVCardCharsetParameter = "CHARSET=" + charset;
-            }
-        }
-        clear();
-    }
-
-    public void clear() {
-        mBuilder = new StringBuilder();
-        mEndAppended = false;
-        appendLine(VCardConstants.PROPERTY_BEGIN, VCARD_DATA_VCARD);
-        if (VCardConfig.isVersion40(mVCardType)) {
-            appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V40);
-        } else if (VCardConfig.isVersion30(mVCardType)) {
-            appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V30);
-        } else {
-            if (!VCardConfig.isVersion21(mVCardType)) {
-                Log.w(LOG_TAG, "Unknown vCard version detected.");
-            }
-            appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V21);
-        }
-    }
-
-    private boolean containsNonEmptyName(final ContentValues contentValues) {
-        final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME);
-        final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME);
-        final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME);
-        final String prefix = contentValues.getAsString(StructuredName.PREFIX);
-        final String suffix = contentValues.getAsString(StructuredName.SUFFIX);
-        final String phoneticFamilyName =
-                contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
-        final String phoneticMiddleName =
-                contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
-        final String phoneticGivenName =
-                contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
-        final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME);
-        return !(TextUtils.isEmpty(familyName) && TextUtils.isEmpty(middleName) &&
-                TextUtils.isEmpty(givenName) && TextUtils.isEmpty(prefix) &&
-                TextUtils.isEmpty(suffix) && TextUtils.isEmpty(phoneticFamilyName) &&
-                TextUtils.isEmpty(phoneticMiddleName) && TextUtils.isEmpty(phoneticGivenName) &&
-                TextUtils.isEmpty(displayName));
-    }
-
-    private ContentValues getPrimaryContentValue(final List<ContentValues> contentValuesList) {
-        ContentValues primaryContentValues = null;
-        ContentValues subprimaryContentValues = null;
-        for (ContentValues contentValues : contentValuesList) {
-            if (contentValues == null){
-                continue;
-            }
-            Integer isSuperPrimary = contentValues.getAsInteger(StructuredName.IS_SUPER_PRIMARY);
-            if (isSuperPrimary != null && isSuperPrimary > 0) {
-                // We choose "super primary" ContentValues.
-                primaryContentValues = contentValues;
-                break;
-            } else if (primaryContentValues == null) {
-                // We choose the first "primary" ContentValues
-                // if "super primary" ContentValues does not exist.
-                final Integer isPrimary = contentValues.getAsInteger(StructuredName.IS_PRIMARY);
-                if (isPrimary != null && isPrimary > 0 &&
-                        containsNonEmptyName(contentValues)) {
-                    primaryContentValues = contentValues;
-                    // Do not break, since there may be ContentValues with "super primary"
-                    // afterword.
-                } else if (subprimaryContentValues == null &&
-                        containsNonEmptyName(contentValues)) {
-                    subprimaryContentValues = contentValues;
-                }
-            }
-        }
-
-        if (primaryContentValues == null) {
-            if (subprimaryContentValues != null) {
-                // We choose the first ContentValues if any "primary" ContentValues does not exist.
-                primaryContentValues = subprimaryContentValues;
-            } else {
-                Log.e(LOG_TAG, "All ContentValues given from database is empty.");
-                primaryContentValues = new ContentValues();
-            }
-        }
-
-        return primaryContentValues;
-    }
-
-    /**
-     * To avoid unnecessary complication in logic, we use this method to construct N, FN
-     * properties for vCard 4.0.
-     */
-    private VCardBuilder appendNamePropertiesV40(final List<ContentValues> contentValuesList) {
-        if (mIsDoCoMo || mNeedsToConvertPhoneticString) {
-            // Ignore all flags that look stale from the view of vCard 4.0 to
-            // simplify construction algorithm. Actually we don't have any vCard file
-            // available from real world yet, so we may need to re-enable some of these
-            // in the future.
-            Log.w(LOG_TAG, "Invalid flag is used in vCard 4.0 construction. Ignored.");
-        }
-
-        if (contentValuesList == null || contentValuesList.isEmpty()) {
-            appendLine(VCardConstants.PROPERTY_FN, "");
-            return this;
-        }
-
-        // We have difficulty here. How can we appropriately handle StructuredName with
-        // missing parts necessary for displaying while it has suppremental information.
-        //
-        // e.g. How to handle non-empty phonetic names with empty structured names?
-
-        final ContentValues contentValues = getPrimaryContentValue(contentValuesList);
-        String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME);
-        final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME);
-        final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME);
-        final String prefix = contentValues.getAsString(StructuredName.PREFIX);
-        final String suffix = contentValues.getAsString(StructuredName.SUFFIX);
-        final String formattedName = contentValues.getAsString(StructuredName.DISPLAY_NAME);
-        if (TextUtils.isEmpty(familyName)
-                && TextUtils.isEmpty(givenName)
-                && TextUtils.isEmpty(middleName)
-                && TextUtils.isEmpty(prefix)
-                && TextUtils.isEmpty(suffix)) {
-            if (TextUtils.isEmpty(formattedName)) {
-                appendLine(VCardConstants.PROPERTY_FN, "");
-                return this;
-            }
-            familyName = formattedName;
-        }
-
-        final String phoneticFamilyName =
-                contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
-        final String phoneticMiddleName =
-                contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
-        final String phoneticGivenName =
-                contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
-        final String escapedFamily = escapeCharacters(familyName);
-        final String escapedGiven = escapeCharacters(givenName);
-        final String escapedMiddle = escapeCharacters(middleName);
-        final String escapedPrefix = escapeCharacters(prefix);
-        final String escapedSuffix = escapeCharacters(suffix);
-
-        mBuilder.append(VCardConstants.PROPERTY_N);
-
-        if (!(TextUtils.isEmpty(phoneticFamilyName) &&
-                        TextUtils.isEmpty(phoneticMiddleName) &&
-                        TextUtils.isEmpty(phoneticGivenName))) {
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            final String sortAs = escapeCharacters(phoneticFamilyName)
-                    + ';' + escapeCharacters(phoneticGivenName)
-                    + ';' + escapeCharacters(phoneticMiddleName);
-            mBuilder.append("SORT-AS=").append(
-                    VCardUtils.toStringAsV40ParamValue(sortAs));
-        }
-
-        mBuilder.append(VCARD_DATA_SEPARATOR);
-        mBuilder.append(escapedFamily);
-        mBuilder.append(VCARD_ITEM_SEPARATOR);
-        mBuilder.append(escapedGiven);
-        mBuilder.append(VCARD_ITEM_SEPARATOR);
-        mBuilder.append(escapedMiddle);
-        mBuilder.append(VCARD_ITEM_SEPARATOR);
-        mBuilder.append(escapedPrefix);
-        mBuilder.append(VCARD_ITEM_SEPARATOR);
-        mBuilder.append(escapedSuffix);
-        mBuilder.append(VCARD_END_OF_LINE);
-
-        if (TextUtils.isEmpty(formattedName)) {
-            // Note:
-            // DISPLAY_NAME doesn't exist while some other elements do, which is usually
-            // weird in Android, as DISPLAY_NAME should (usually) be constructed
-            // from the others using locale information and its code points.
-            Log.w(LOG_TAG, "DISPLAY_NAME is empty.");
-
-            final String escaped = escapeCharacters(VCardUtils.constructNameFromElements(
-                    VCardConfig.getNameOrderType(mVCardType),
-                    familyName, middleName, givenName, prefix, suffix));
-            appendLine(VCardConstants.PROPERTY_FN, escaped);
-        } else {
-            final String escapedFormatted = escapeCharacters(formattedName);
-            mBuilder.append(VCardConstants.PROPERTY_FN);
-            mBuilder.append(VCARD_DATA_SEPARATOR);
-            mBuilder.append(escapedFormatted);
-            mBuilder.append(VCARD_END_OF_LINE);
-        }
-
-        // We may need X- properties for phonetic names.
-        appendPhoneticNameFields(contentValues);
-        return this;
-    }
-
-    /**
-     * For safety, we'll emit just one value around StructuredName, as external importers
-     * may get confused with multiple "N", "FN", etc. properties, though it is valid in
-     * vCard spec.
-     */
-    public VCardBuilder appendNameProperties(final List<ContentValues> contentValuesList) {
-        if (VCardConfig.isVersion40(mVCardType)) {
-            return appendNamePropertiesV40(contentValuesList);
-        }
-
-        if (contentValuesList == null || contentValuesList.isEmpty()) {
-            if (VCardConfig.isVersion30(mVCardType)) {
-                // vCard 3.0 requires "N" and "FN" properties.
-                // vCard 4.0 does NOT require N, but we take care of possible backward
-                // compatibility issues.
-                appendLine(VCardConstants.PROPERTY_N, "");
-                appendLine(VCardConstants.PROPERTY_FN, "");
-            } else if (mIsDoCoMo) {
-                appendLine(VCardConstants.PROPERTY_N, "");
-            }
-            return this;
-        }
-
-        final ContentValues contentValues = getPrimaryContentValue(contentValuesList);
-        final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME);
-        final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME);
-        final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME);
-        final String prefix = contentValues.getAsString(StructuredName.PREFIX);
-        final String suffix = contentValues.getAsString(StructuredName.SUFFIX);
-        final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME);
-
-        if (!TextUtils.isEmpty(familyName) || !TextUtils.isEmpty(givenName)) {
-            final boolean reallyAppendCharsetParameterToName =
-                    shouldAppendCharsetParam(familyName, givenName, middleName, prefix, suffix);
-            final boolean reallyUseQuotedPrintableToName =
-                    (!mRefrainsQPToNameProperties &&
-                            !(VCardUtils.containsOnlyNonCrLfPrintableAscii(familyName) &&
-                                    VCardUtils.containsOnlyNonCrLfPrintableAscii(givenName) &&
-                                    VCardUtils.containsOnlyNonCrLfPrintableAscii(middleName) &&
-                                    VCardUtils.containsOnlyNonCrLfPrintableAscii(prefix) &&
-                                    VCardUtils.containsOnlyNonCrLfPrintableAscii(suffix)));
-
-            final String formattedName;
-            if (!TextUtils.isEmpty(displayName)) {
-                formattedName = displayName;
-            } else {
-                formattedName = VCardUtils.constructNameFromElements(
-                        VCardConfig.getNameOrderType(mVCardType),
-                        familyName, middleName, givenName, prefix, suffix);
-            }
-            final boolean reallyAppendCharsetParameterToFN =
-                    shouldAppendCharsetParam(formattedName);
-            final boolean reallyUseQuotedPrintableToFN =
-                    !mRefrainsQPToNameProperties &&
-                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(formattedName);
-
-            final String encodedFamily;
-            final String encodedGiven;
-            final String encodedMiddle;
-            final String encodedPrefix;
-            final String encodedSuffix;
-            if (reallyUseQuotedPrintableToName) {
-                encodedFamily = encodeQuotedPrintable(familyName);
-                encodedGiven = encodeQuotedPrintable(givenName);
-                encodedMiddle = encodeQuotedPrintable(middleName);
-                encodedPrefix = encodeQuotedPrintable(prefix);
-                encodedSuffix = encodeQuotedPrintable(suffix);
-            } else {
-                encodedFamily = escapeCharacters(familyName);
-                encodedGiven = escapeCharacters(givenName);
-                encodedMiddle = escapeCharacters(middleName);
-                encodedPrefix = escapeCharacters(prefix);
-                encodedSuffix = escapeCharacters(suffix);
-            }
-
-            final String encodedFormattedname =
-                    (reallyUseQuotedPrintableToFN ?
-                            encodeQuotedPrintable(formattedName) : escapeCharacters(formattedName));
-
-            mBuilder.append(VCardConstants.PROPERTY_N);
-            if (mIsDoCoMo) {
-                if (reallyAppendCharsetParameterToName) {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                    mBuilder.append(mVCardCharsetParameter);
-                }
-                if (reallyUseQuotedPrintableToName) {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                    mBuilder.append(VCARD_PARAM_ENCODING_QP);
-                }
-                mBuilder.append(VCARD_DATA_SEPARATOR);
-                // DoCoMo phones require that all the elements in the "family name" field.
-                mBuilder.append(formattedName);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-            } else {
-                if (reallyAppendCharsetParameterToName) {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                    mBuilder.append(mVCardCharsetParameter);
-                }
-                if (reallyUseQuotedPrintableToName) {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                    mBuilder.append(VCARD_PARAM_ENCODING_QP);
-                }
-                mBuilder.append(VCARD_DATA_SEPARATOR);
-                mBuilder.append(encodedFamily);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-                mBuilder.append(encodedGiven);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-                mBuilder.append(encodedMiddle);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-                mBuilder.append(encodedPrefix);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-                mBuilder.append(encodedSuffix);
-            }
-            mBuilder.append(VCARD_END_OF_LINE);
-
-            // FN property
-            mBuilder.append(VCardConstants.PROPERTY_FN);
-            if (reallyAppendCharsetParameterToFN) {
-                mBuilder.append(VCARD_PARAM_SEPARATOR);
-                mBuilder.append(mVCardCharsetParameter);
-            }
-            if (reallyUseQuotedPrintableToFN) {
-                mBuilder.append(VCARD_PARAM_SEPARATOR);
-                mBuilder.append(VCARD_PARAM_ENCODING_QP);
-            }
-            mBuilder.append(VCARD_DATA_SEPARATOR);
-            mBuilder.append(encodedFormattedname);
-            mBuilder.append(VCARD_END_OF_LINE);
-        } else if (!TextUtils.isEmpty(displayName)) {
-            final boolean reallyUseQuotedPrintableToDisplayName =
-                (!mRefrainsQPToNameProperties &&
-                        !VCardUtils.containsOnlyNonCrLfPrintableAscii(displayName));
-            final String encodedDisplayName =
-                    reallyUseQuotedPrintableToDisplayName ?
-                            encodeQuotedPrintable(displayName) :
-                                escapeCharacters(displayName);
-
-            // N
-            mBuilder.append(VCardConstants.PROPERTY_N);
-            if (shouldAppendCharsetParam(displayName)) {
-                mBuilder.append(VCARD_PARAM_SEPARATOR);
-                mBuilder.append(mVCardCharsetParameter);
-            }
-            if (reallyUseQuotedPrintableToDisplayName) {
-                mBuilder.append(VCARD_PARAM_SEPARATOR);
-                mBuilder.append(VCARD_PARAM_ENCODING_QP);
-            }
-            mBuilder.append(VCARD_DATA_SEPARATOR);
-            mBuilder.append(encodedDisplayName);
-            mBuilder.append(VCARD_ITEM_SEPARATOR);
-            mBuilder.append(VCARD_ITEM_SEPARATOR);
-            mBuilder.append(VCARD_ITEM_SEPARATOR);
-            mBuilder.append(VCARD_ITEM_SEPARATOR);
-            mBuilder.append(VCARD_END_OF_LINE);
-
-            // FN
-            mBuilder.append(VCardConstants.PROPERTY_FN);
-
-            // Note: "CHARSET" param is not allowed in vCard 3.0, but we may add it
-            //       when it would be useful or necessary for external importers,
-            //       assuming the external importer allows this vioration of the spec.
-            if (shouldAppendCharsetParam(displayName)) {
-                mBuilder.append(VCARD_PARAM_SEPARATOR);
-                mBuilder.append(mVCardCharsetParameter);
-            }
-            mBuilder.append(VCARD_DATA_SEPARATOR);
-            mBuilder.append(encodedDisplayName);
-            mBuilder.append(VCARD_END_OF_LINE);
-        } else if (VCardConfig.isVersion30(mVCardType)) {
-            appendLine(VCardConstants.PROPERTY_N, "");
-            appendLine(VCardConstants.PROPERTY_FN, "");
-        } else if (mIsDoCoMo) {
-            appendLine(VCardConstants.PROPERTY_N, "");
-        }
-
-        appendPhoneticNameFields(contentValues);
-        return this;
-    }
-
-    /**
-     * Emits SOUND;IRMC, SORT-STRING, and de-fact values for phonetic names like X-PHONETIC-FAMILY.
-     */
-    private void appendPhoneticNameFields(final ContentValues contentValues) {
-        final String phoneticFamilyName;
-        final String phoneticMiddleName;
-        final String phoneticGivenName;
-        {
-            final String tmpPhoneticFamilyName =
-                contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
-            final String tmpPhoneticMiddleName =
-                contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
-            final String tmpPhoneticGivenName =
-                contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
-            if (mNeedsToConvertPhoneticString) {
-                phoneticFamilyName = VCardUtils.toHalfWidthString(tmpPhoneticFamilyName);
-                phoneticMiddleName = VCardUtils.toHalfWidthString(tmpPhoneticMiddleName);
-                phoneticGivenName = VCardUtils.toHalfWidthString(tmpPhoneticGivenName);
-            } else {
-                phoneticFamilyName = tmpPhoneticFamilyName;
-                phoneticMiddleName = tmpPhoneticMiddleName;
-                phoneticGivenName = tmpPhoneticGivenName;
-            }
-        }
-
-        if (TextUtils.isEmpty(phoneticFamilyName)
-                && TextUtils.isEmpty(phoneticMiddleName)
-                && TextUtils.isEmpty(phoneticGivenName)) {
-            if (mIsDoCoMo) {
-                mBuilder.append(VCardConstants.PROPERTY_SOUND);
-                mBuilder.append(VCARD_PARAM_SEPARATOR);
-                mBuilder.append(VCardConstants.PARAM_TYPE_X_IRMC_N);
-                mBuilder.append(VCARD_DATA_SEPARATOR);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-                mBuilder.append(VCARD_END_OF_LINE);
-            }
-            return;
-        }
-
-        if (VCardConfig.isVersion40(mVCardType)) {
-            // We don't want SORT-STRING anyway.
-        } else if (VCardConfig.isVersion30(mVCardType)) {
-            final String sortString =
-                    VCardUtils.constructNameFromElements(mVCardType,
-                            phoneticFamilyName, phoneticMiddleName, phoneticGivenName);
-            mBuilder.append(VCardConstants.PROPERTY_SORT_STRING);
-            if (VCardConfig.isVersion30(mVCardType) && shouldAppendCharsetParam(sortString)) {
-                // vCard 3.0 does not force us to use UTF-8 and actually we see some
-                // programs which emit this value. It is incorrect from the view of
-                // specification, but actually necessary for parsing vCard with non-UTF-8
-                // charsets, expecting other parsers not get confused with this value.
-                mBuilder.append(VCARD_PARAM_SEPARATOR);
-                mBuilder.append(mVCardCharsetParameter);
-            }
-            mBuilder.append(VCARD_DATA_SEPARATOR);
-            mBuilder.append(escapeCharacters(sortString));
-            mBuilder.append(VCARD_END_OF_LINE);
-        } else if (mIsJapaneseMobilePhone) {
-            // Note: There is no appropriate property for expressing
-            //       phonetic name (Yomigana in Japanese) in vCard 2.1, while there is in
-            //       vCard 3.0 (SORT-STRING).
-            //       We use DoCoMo's way when the device is Japanese one since it is already
-            //       supported by a lot of Japanese mobile phones.
-            //       This is "X-" property, so any parser hopefully would not get
-            //       confused with this.
-            //
-            //       Also, DoCoMo's specification requires vCard composer to use just the first
-            //       column.
-            //       i.e.
-            //       good:  SOUND;X-IRMC-N:Miyakawa Daisuke;;;;
-            //       bad :  SOUND;X-IRMC-N:Miyakawa;Daisuke;;;
-            mBuilder.append(VCardConstants.PROPERTY_SOUND);
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            mBuilder.append(VCardConstants.PARAM_TYPE_X_IRMC_N);
-
-            boolean reallyUseQuotedPrintable =
-                (!mRefrainsQPToNameProperties
-                        && !(VCardUtils.containsOnlyNonCrLfPrintableAscii(
-                                phoneticFamilyName)
-                                && VCardUtils.containsOnlyNonCrLfPrintableAscii(
-                                        phoneticMiddleName)
-                                && VCardUtils.containsOnlyNonCrLfPrintableAscii(
-                                        phoneticGivenName)));
-
-            final String encodedPhoneticFamilyName;
-            final String encodedPhoneticMiddleName;
-            final String encodedPhoneticGivenName;
-            if (reallyUseQuotedPrintable) {
-                encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName);
-                encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName);
-                encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName);
-            } else {
-                encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName);
-                encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName);
-                encodedPhoneticGivenName = escapeCharacters(phoneticGivenName);
-            }
-
-            if (shouldAppendCharsetParam(encodedPhoneticFamilyName,
-                    encodedPhoneticMiddleName, encodedPhoneticGivenName)) {
-                mBuilder.append(VCARD_PARAM_SEPARATOR);
-                mBuilder.append(mVCardCharsetParameter);
-            }
-            mBuilder.append(VCARD_DATA_SEPARATOR);
-            {
-                boolean first = true;
-                if (!TextUtils.isEmpty(encodedPhoneticFamilyName)) {
-                    mBuilder.append(encodedPhoneticFamilyName);
-                    first = false;
-                }
-                if (!TextUtils.isEmpty(encodedPhoneticMiddleName)) {
-                    if (first) {
-                        first = false;
-                    } else {
-                        mBuilder.append(' ');
-                    }
-                    mBuilder.append(encodedPhoneticMiddleName);
-                }
-                if (!TextUtils.isEmpty(encodedPhoneticGivenName)) {
-                    if (!first) {
-                        mBuilder.append(' ');
-                    }
-                    mBuilder.append(encodedPhoneticGivenName);
-                }
-            }
-            mBuilder.append(VCARD_ITEM_SEPARATOR);  // family;given
-            mBuilder.append(VCARD_ITEM_SEPARATOR);  // given;middle
-            mBuilder.append(VCARD_ITEM_SEPARATOR);  // middle;prefix
-            mBuilder.append(VCARD_ITEM_SEPARATOR);  // prefix;suffix
-            mBuilder.append(VCARD_END_OF_LINE);
-        }
-
-        if (mUsesDefactProperty) {
-            if (!TextUtils.isEmpty(phoneticGivenName)) {
-                final boolean reallyUseQuotedPrintable =
-                    (mShouldUseQuotedPrintable &&
-                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName));
-                final String encodedPhoneticGivenName;
-                if (reallyUseQuotedPrintable) {
-                    encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName);
-                } else {
-                    encodedPhoneticGivenName = escapeCharacters(phoneticGivenName);
-                }
-                mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_FIRST_NAME);
-                if (shouldAppendCharsetParam(phoneticGivenName)) {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                    mBuilder.append(mVCardCharsetParameter);
-                }
-                if (reallyUseQuotedPrintable) {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                    mBuilder.append(VCARD_PARAM_ENCODING_QP);
-                }
-                mBuilder.append(VCARD_DATA_SEPARATOR);
-                mBuilder.append(encodedPhoneticGivenName);
-                mBuilder.append(VCARD_END_OF_LINE);
-            }  // if (!TextUtils.isEmpty(phoneticGivenName))
-            if (!TextUtils.isEmpty(phoneticMiddleName)) {
-                final boolean reallyUseQuotedPrintable =
-                    (mShouldUseQuotedPrintable &&
-                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName));
-                final String encodedPhoneticMiddleName;
-                if (reallyUseQuotedPrintable) {
-                    encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName);
-                } else {
-                    encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName);
-                }
-                mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_MIDDLE_NAME);
-                if (shouldAppendCharsetParam(phoneticMiddleName)) {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                    mBuilder.append(mVCardCharsetParameter);
-                }
-                if (reallyUseQuotedPrintable) {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                    mBuilder.append(VCARD_PARAM_ENCODING_QP);
-                }
-                mBuilder.append(VCARD_DATA_SEPARATOR);
-                mBuilder.append(encodedPhoneticMiddleName);
-                mBuilder.append(VCARD_END_OF_LINE);
-            }  // if (!TextUtils.isEmpty(phoneticGivenName))
-            if (!TextUtils.isEmpty(phoneticFamilyName)) {
-                final boolean reallyUseQuotedPrintable =
-                    (mShouldUseQuotedPrintable &&
-                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName));
-                final String encodedPhoneticFamilyName;
-                if (reallyUseQuotedPrintable) {
-                    encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName);
-                } else {
-                    encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName);
-                }
-                mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_LAST_NAME);
-                if (shouldAppendCharsetParam(phoneticFamilyName)) {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                    mBuilder.append(mVCardCharsetParameter);
-                }
-                if (reallyUseQuotedPrintable) {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                    mBuilder.append(VCARD_PARAM_ENCODING_QP);
-                }
-                mBuilder.append(VCARD_DATA_SEPARATOR);
-                mBuilder.append(encodedPhoneticFamilyName);
-                mBuilder.append(VCARD_END_OF_LINE);
-            }  // if (!TextUtils.isEmpty(phoneticFamilyName))
-        }
-    }
-
-    public VCardBuilder appendNickNames(final List<ContentValues> contentValuesList) {
-        final boolean useAndroidProperty;
-        if (mIsV30OrV40) {   // These specifications have NICKNAME property.
-            useAndroidProperty = false;
-        } else if (mUsesAndroidProperty) {
-            useAndroidProperty = true;
-        } else {
-            // There's no way to add this field.
-            return this;
-        }
-        if (contentValuesList != null) {
-            for (ContentValues contentValues : contentValuesList) {
-                final String nickname = contentValues.getAsString(Nickname.NAME);
-                if (TextUtils.isEmpty(nickname)) {
-                    continue;
-                }
-                if (useAndroidProperty) {
-                    appendAndroidSpecificProperty(Nickname.CONTENT_ITEM_TYPE, contentValues);
-                } else {
-                    appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_NICKNAME, nickname);
-                }
-            }
-        }
-        return this;
-    }
-
-    public VCardBuilder appendPhones(final List<ContentValues> contentValuesList) {
-        boolean phoneLineExists = false;
-        if (contentValuesList != null) {
-            Set<String> phoneSet = new HashSet<String>();
-            for (ContentValues contentValues : contentValuesList) {
-                final Integer typeAsObject = contentValues.getAsInteger(Phone.TYPE);
-                final String label = contentValues.getAsString(Phone.LABEL);
-                final Integer isPrimaryAsInteger = contentValues.getAsInteger(Phone.IS_PRIMARY);
-                final boolean isPrimary = (isPrimaryAsInteger != null ?
-                        (isPrimaryAsInteger > 0) : false);
-                String phoneNumber = contentValues.getAsString(Phone.NUMBER);
-                if (phoneNumber != null) {
-                    phoneNumber = phoneNumber.trim();
-                }
-                if (TextUtils.isEmpty(phoneNumber)) {
-                    continue;
-                }
-
-                // PAGER number needs unformatted "phone number".
-                // TODO: It would be better to have this logic as optional. 
-                final int type = (typeAsObject != null ? typeAsObject : DEFAULT_PHONE_TYPE);
-                if (type == Phone.TYPE_PAGER ||
-                        VCardConfig.refrainPhoneNumberFormatting(mVCardType)) {
-                    phoneLineExists = true;
-                    if (!phoneSet.contains(phoneNumber)) {
-                        phoneSet.add(phoneNumber);
-                        appendTelLine(type, label, phoneNumber, isPrimary);
-                    }
-                } else {
-                    final List<String> phoneNumberList = splitAndTrimPhoneNumbers(phoneNumber);
-                    if (phoneNumberList.isEmpty()) {
-                        continue;
-                    }
-                    phoneLineExists = true;
-                    for (String actualPhoneNumber : phoneNumberList) {
-                        if (!phoneSet.contains(actualPhoneNumber)) {
-                            final int phoneFormat = VCardUtils.getPhoneNumberFormat(mVCardType);
-                            String formatted = 
-                                    PhoneNumberUtils.formatNumber(actualPhoneNumber);
-
-                            // In vCard 4.0, value type must be "a single URI value",
-                            // not just a phone number. (Based on vCard 4.0 rev.13)
-                            if (VCardConfig.isVersion40(mVCardType)
-                                    && !TextUtils.isEmpty(formatted)
-                                    && !formatted.startsWith("tel:")) {
-                                formatted = "tel:" + formatted;
-                            }
-
-                            // Pre-formatted string should be stored.
-                            phoneSet.add(actualPhoneNumber);
-                            appendTelLine(type, label, formatted, isPrimary);
-                        }
-                    }  // for (String actualPhoneNumber : phoneNumberList) {
-
-                    // TODO: TEL with SIP URI?
-                }
-            }
-        }
-
-        if (!phoneLineExists && mIsDoCoMo) {
-            appendTelLine(Phone.TYPE_HOME, "", "", false);
-        }
-
-        return this;
-    }
-
-    /**
-     * <p>
-     * Splits a given string expressing phone numbers into several strings, and remove
-     * unnecessary characters inside them. The size of a returned list becomes 1 when
-     * no split is needed.
-     * </p>
-     * <p>
-     * The given number "may" have several phone numbers when the contact entry is corrupted
-     * because of its original source.
-     * e.g. "111-222-3333 (Miami)\n444-555-6666 (Broward; 305-653-6796 (Miami)"
-     * </p>
-     * <p>
-     * This kind of "phone numbers" will not be created with Android vCard implementation,
-     * but we may encounter them if the source of the input data has already corrupted
-     * implementation.
-     * </p>
-     * <p>
-     * To handle this case, this method first splits its input into multiple parts
-     * (e.g. "111-222-3333 (Miami)", "444-555-6666 (Broward", and 305653-6796 (Miami)") and
-     * removes unnecessary strings like "(Miami)".
-     * </p>
-     * <p>
-     * Do not call this method when trimming is inappropriate for its receivers.
-     * </p>
-     */
-    private List<String> splitAndTrimPhoneNumbers(final String phoneNumber) {
-        final List<String> phoneList = new ArrayList<String>();
-
-        StringBuilder builder = new StringBuilder();
-        final int length = phoneNumber.length();
-        for (int i = 0; i < length; i++) {
-            final char ch = phoneNumber.charAt(i);
-            if (Character.isDigit(ch) || ch == '+') {
-                builder.append(ch);
-            } else if ((ch == ';' || ch == '\n') && builder.length() > 0) {
-                phoneList.add(builder.toString());
-                builder = new StringBuilder();
-            }
-        }
-        if (builder.length() > 0) {
-            phoneList.add(builder.toString());
-        }
-
-        return phoneList;
-    }
-
-    public VCardBuilder appendEmails(final List<ContentValues> contentValuesList) {
-        boolean emailAddressExists = false;
-        if (contentValuesList != null) {
-            final Set<String> addressSet = new HashSet<String>();
-            for (ContentValues contentValues : contentValuesList) {
-                String emailAddress = contentValues.getAsString(Email.DATA);
-                if (emailAddress != null) {
-                    emailAddress = emailAddress.trim();
-                }
-                if (TextUtils.isEmpty(emailAddress)) {
-                    continue;
-                }
-                Integer typeAsObject = contentValues.getAsInteger(Email.TYPE);
-                final int type = (typeAsObject != null ?
-                        typeAsObject : DEFAULT_EMAIL_TYPE);
-                final String label = contentValues.getAsString(Email.LABEL);
-                Integer isPrimaryAsInteger = contentValues.getAsInteger(Email.IS_PRIMARY);
-                final boolean isPrimary = (isPrimaryAsInteger != null ?
-                        (isPrimaryAsInteger > 0) : false);
-                emailAddressExists = true;
-                if (!addressSet.contains(emailAddress)) {
-                    addressSet.add(emailAddress);
-                    appendEmailLine(type, label, emailAddress, isPrimary);
-                }
-            }
-        }
-
-        if (!emailAddressExists && mIsDoCoMo) {
-            appendEmailLine(Email.TYPE_HOME, "", "", false);
-        }
-
-        return this;
-    }
-
-    public VCardBuilder appendPostals(final List<ContentValues> contentValuesList) {
-        if (contentValuesList == null || contentValuesList.isEmpty()) {
-            if (mIsDoCoMo) {
-                mBuilder.append(VCardConstants.PROPERTY_ADR);
-                mBuilder.append(VCARD_PARAM_SEPARATOR);
-                mBuilder.append(VCardConstants.PARAM_TYPE_HOME);
-                mBuilder.append(VCARD_DATA_SEPARATOR);
-                mBuilder.append(VCARD_END_OF_LINE);
-            }
-        } else {
-            if (mIsDoCoMo) {
-                appendPostalsForDoCoMo(contentValuesList);
-            } else {
-                appendPostalsForGeneric(contentValuesList);
-            }
-        }
-
-        return this;
-    }
-
-    private static final Map<Integer, Integer> sPostalTypePriorityMap;
-
-    static {
-        sPostalTypePriorityMap = new HashMap<Integer, Integer>();
-        sPostalTypePriorityMap.put(StructuredPostal.TYPE_HOME, 0);
-        sPostalTypePriorityMap.put(StructuredPostal.TYPE_WORK, 1);
-        sPostalTypePriorityMap.put(StructuredPostal.TYPE_OTHER, 2);
-        sPostalTypePriorityMap.put(StructuredPostal.TYPE_CUSTOM, 3);
-    }
-
-    /**
-     * Tries to append just one line. If there's no appropriate address
-     * information, append an empty line.
-     */
-    private void appendPostalsForDoCoMo(final List<ContentValues> contentValuesList) {
-        int currentPriority = Integer.MAX_VALUE;
-        int currentType = Integer.MAX_VALUE;
-        ContentValues currentContentValues = null;
-        for (final ContentValues contentValues : contentValuesList) {
-            if (contentValues == null) {
-                continue;
-            }
-            final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE);
-            final Integer priorityAsInteger = sPostalTypePriorityMap.get(typeAsInteger);
-            final int priority =
-                    (priorityAsInteger != null ? priorityAsInteger : Integer.MAX_VALUE);
-            if (priority < currentPriority) {
-                currentPriority = priority;
-                currentType = typeAsInteger;
-                currentContentValues = contentValues;
-                if (priority == 0) {
-                    break;
-                }
-            }
-        }
-
-        if (currentContentValues == null) {
-            Log.w(LOG_TAG, "Should not come here. Must have at least one postal data.");
-            return;
-        }
-
-        final String label = currentContentValues.getAsString(StructuredPostal.LABEL);
-        appendPostalLine(currentType, label, currentContentValues, false, true);
-    }
-
-    private void appendPostalsForGeneric(final List<ContentValues> contentValuesList) {
-        for (final ContentValues contentValues : contentValuesList) {
-            if (contentValues == null) {
-                continue;
-            }
-            final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE);
-            final int type = (typeAsInteger != null ?
-                    typeAsInteger : DEFAULT_POSTAL_TYPE);
-            final String label = contentValues.getAsString(StructuredPostal.LABEL);
-            final Integer isPrimaryAsInteger =
-                contentValues.getAsInteger(StructuredPostal.IS_PRIMARY);
-            final boolean isPrimary = (isPrimaryAsInteger != null ?
-                    (isPrimaryAsInteger > 0) : false);
-            appendPostalLine(type, label, contentValues, isPrimary, false);
-        }
-    }
-
-    private static class PostalStruct {
-        final boolean reallyUseQuotedPrintable;
-        final boolean appendCharset;
-        final String addressData;
-        public PostalStruct(final boolean reallyUseQuotedPrintable,
-                final boolean appendCharset, final String addressData) {
-            this.reallyUseQuotedPrintable = reallyUseQuotedPrintable;
-            this.appendCharset = appendCharset;
-            this.addressData = addressData;
-        }
-    }
-
-    /**
-     * @return null when there's no information available to construct the data.
-     */
-    private PostalStruct tryConstructPostalStruct(ContentValues contentValues) {
-        // adr-value    = 0*6(text-value ";") text-value
-        //              ; PO Box, Extended Address, Street, Locality, Region, Postal
-        //              ; Code, Country Name
-        final String rawPoBox = contentValues.getAsString(StructuredPostal.POBOX);
-        final String rawNeighborhood = contentValues.getAsString(StructuredPostal.NEIGHBORHOOD);
-        final String rawStreet = contentValues.getAsString(StructuredPostal.STREET);
-        final String rawLocality = contentValues.getAsString(StructuredPostal.CITY);
-        final String rawRegion = contentValues.getAsString(StructuredPostal.REGION);
-        final String rawPostalCode = contentValues.getAsString(StructuredPostal.POSTCODE);
-        final String rawCountry = contentValues.getAsString(StructuredPostal.COUNTRY);
-        final String[] rawAddressArray = new String[]{
-                rawPoBox, rawNeighborhood, rawStreet, rawLocality,
-                rawRegion, rawPostalCode, rawCountry};
-        if (!VCardUtils.areAllEmpty(rawAddressArray)) {
-            final boolean reallyUseQuotedPrintable =
-                (mShouldUseQuotedPrintable &&
-                        !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawAddressArray));
-            final boolean appendCharset =
-                !VCardUtils.containsOnlyPrintableAscii(rawAddressArray);
-            final String encodedPoBox;
-            final String encodedStreet;
-            final String encodedLocality;
-            final String encodedRegion;
-            final String encodedPostalCode;
-            final String encodedCountry;
-            final String encodedNeighborhood;
-
-            final String rawLocality2;
-            // This looks inefficient since we encode rawLocality and rawNeighborhood twice,
-            // but this is intentional.
-            //
-            // QP encoding may add line feeds when needed and the result of
-            // - encodeQuotedPrintable(rawLocality + " " + rawNeighborhood)
-            // may be different from
-            // - encodedLocality + " " + encodedNeighborhood.
-            //
-            // We use safer way.
-            if (TextUtils.isEmpty(rawLocality)) {
-                if (TextUtils.isEmpty(rawNeighborhood)) {
-                    rawLocality2 = "";
-                } else {
-                    rawLocality2 = rawNeighborhood;
-                }
-            } else {
-                if (TextUtils.isEmpty(rawNeighborhood)) {
-                    rawLocality2 = rawLocality;
-                } else {
-                    rawLocality2 = rawLocality + " " + rawNeighborhood;
-                }
-            }
-            if (reallyUseQuotedPrintable) {
-                encodedPoBox = encodeQuotedPrintable(rawPoBox);
-                encodedStreet = encodeQuotedPrintable(rawStreet);
-                encodedLocality = encodeQuotedPrintable(rawLocality2);
-                encodedRegion = encodeQuotedPrintable(rawRegion);
-                encodedPostalCode = encodeQuotedPrintable(rawPostalCode);
-                encodedCountry = encodeQuotedPrintable(rawCountry);
-            } else {
-                encodedPoBox = escapeCharacters(rawPoBox);
-                encodedStreet = escapeCharacters(rawStreet);
-                encodedLocality = escapeCharacters(rawLocality2);
-                encodedRegion = escapeCharacters(rawRegion);
-                encodedPostalCode = escapeCharacters(rawPostalCode);
-                encodedCountry = escapeCharacters(rawCountry);
-                encodedNeighborhood = escapeCharacters(rawNeighborhood);
-            }
-            final StringBuilder addressBuilder = new StringBuilder();
-            addressBuilder.append(encodedPoBox);
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // PO BOX ; Extended Address
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Extended Address : Street
-            addressBuilder.append(encodedStreet);
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Street : Locality
-            addressBuilder.append(encodedLocality);
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Locality : Region
-            addressBuilder.append(encodedRegion);
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Region : Postal Code
-            addressBuilder.append(encodedPostalCode);
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Postal Code : Country
-            addressBuilder.append(encodedCountry);
-            return new PostalStruct(
-                    reallyUseQuotedPrintable, appendCharset, addressBuilder.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 StringBuilder addressBuilder = new StringBuilder();
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // PO BOX ; Extended Address
-            addressBuilder.append(encodedFormattedAddress);
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Extended Address : Street
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Street : Locality
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Locality : Region
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Region : Postal Code
-            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Postal Code : Country
-            return new PostalStruct(
-                    reallyUseQuotedPrintable, appendCharset, addressBuilder.toString());
-        }
-    }
-
-    public VCardBuilder appendIms(final List<ContentValues> contentValuesList) {
-        if (contentValuesList != null) {
-            for (ContentValues contentValues : contentValuesList) {
-                final Integer protocolAsObject = contentValues.getAsInteger(Im.PROTOCOL);
-                if (protocolAsObject == null) {
-                    continue;
-                }
-                final String propertyName = VCardUtils.getPropertyNameForIm(protocolAsObject);
-                if (propertyName == null) {
-                    continue;
-                }
-                String data = contentValues.getAsString(Im.DATA);
-                if (data != null) {
-                    data = data.trim();
-                }
-                if (TextUtils.isEmpty(data)) {
-                    continue;
-                }
-                final String typeAsString;
-                {
-                    final Integer typeAsInteger = contentValues.getAsInteger(Im.TYPE);
-                    switch (typeAsInteger != null ? typeAsInteger : Im.TYPE_OTHER) {
-                        case Im.TYPE_HOME: {
-                            typeAsString = VCardConstants.PARAM_TYPE_HOME;
-                            break;
-                        }
-                        case Im.TYPE_WORK: {
-                            typeAsString = VCardConstants.PARAM_TYPE_WORK;
-                            break;
-                        }
-                        case Im.TYPE_CUSTOM: {
-                            final String label = contentValues.getAsString(Im.LABEL);
-                            typeAsString = (label != null ? "X-" + label : null);
-                            break;
-                        }
-                        case Im.TYPE_OTHER:  // Ignore
-                        default: {
-                            typeAsString = null;
-                            break;
-                        }
-                    }
-                }
-
-                final List<String> parameterList = new ArrayList<String>();
-                if (!TextUtils.isEmpty(typeAsString)) {
-                    parameterList.add(typeAsString);
-                }
-                final Integer isPrimaryAsInteger = contentValues.getAsInteger(Im.IS_PRIMARY);
-                final boolean isPrimary = (isPrimaryAsInteger != null ?
-                        (isPrimaryAsInteger > 0) : false);
-                if (isPrimary) {
-                    parameterList.add(VCardConstants.PARAM_TYPE_PREF);
-                }
-
-                appendLineWithCharsetAndQPDetection(propertyName, parameterList, data);
-            }
-        }
-        return this;
-    }
-
-    public VCardBuilder appendWebsites(final List<ContentValues> contentValuesList) {
-        if (contentValuesList != null) {
-            for (ContentValues contentValues : contentValuesList) {
-                String website = contentValues.getAsString(Website.URL);
-                if (website != null) {
-                    website = website.trim();
-                }
-
-                // Note: vCard 3.0 does not allow any parameter addition toward "URL"
-                //       property, while there's no document in vCard 2.1.
-                if (!TextUtils.isEmpty(website)) {
-                    appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_URL, website);
-                }
-            }
-        }
-        return this;
-    }
-
-    public VCardBuilder appendOrganizations(final List<ContentValues> contentValuesList) {
-        if (contentValuesList != null) {
-            for (ContentValues contentValues : contentValuesList) {
-                String company = contentValues.getAsString(Organization.COMPANY);
-                if (company != null) {
-                    company = company.trim();
-                }
-                String department = contentValues.getAsString(Organization.DEPARTMENT);
-                if (department != null) {
-                    department = department.trim();
-                }
-                String title = contentValues.getAsString(Organization.TITLE);
-                if (title != null) {
-                    title = title.trim();
-                }
-
-                StringBuilder orgBuilder = new StringBuilder();
-                if (!TextUtils.isEmpty(company)) {
-                    orgBuilder.append(company);
-                }
-                if (!TextUtils.isEmpty(department)) {
-                    if (orgBuilder.length() > 0) {
-                        orgBuilder.append(';');
-                    }
-                    orgBuilder.append(department);
-                }
-                final String orgline = orgBuilder.toString();
-                appendLine(VCardConstants.PROPERTY_ORG, orgline,
-                        !VCardUtils.containsOnlyPrintableAscii(orgline),
-                        (mShouldUseQuotedPrintable &&
-                                !VCardUtils.containsOnlyNonCrLfPrintableAscii(orgline)));
-
-                if (!TextUtils.isEmpty(title)) {
-                    appendLine(VCardConstants.PROPERTY_TITLE, title,
-                            !VCardUtils.containsOnlyPrintableAscii(title),
-                            (mShouldUseQuotedPrintable &&
-                                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(title)));
-                }
-            }
-        }
-        return this;
-    }
-
-    public VCardBuilder appendPhotos(final List<ContentValues> contentValuesList) {
-        if (contentValuesList != null) {
-            for (ContentValues contentValues : contentValuesList) {
-                if (contentValues == null) {
-                    continue;
-                }
-                byte[] data = contentValues.getAsByteArray(Photo.PHOTO);
-                if (data == null) {
-                    continue;
-                }
-                final String photoType = VCardUtils.guessImageType(data);
-                if (photoType == null) {
-                    Log.d(LOG_TAG, "Unknown photo type. Ignored.");
-                    continue;
-                }
-                // TODO: check this works fine.
-                final String photoString = new String(Base64.encode(data, Base64.NO_WRAP));
-                if (!TextUtils.isEmpty(photoString)) {
-                    appendPhotoLine(photoString, photoType);
-                }
-            }
-        }
-        return this;
-    }
-
-    public VCardBuilder appendNotes(final List<ContentValues> contentValuesList) {
-        if (contentValuesList != null) {
-            if (mOnlyOneNoteFieldIsAvailable) {
-                final StringBuilder noteBuilder = new StringBuilder();
-                boolean first = true;
-                for (final ContentValues contentValues : contentValuesList) {
-                    String note = contentValues.getAsString(Note.NOTE);
-                    if (note == null) {
-                        note = "";
-                    }
-                    if (note.length() > 0) {
-                        if (first) {
-                            first = false;
-                        } else {
-                            noteBuilder.append('\n');
-                        }
-                        noteBuilder.append(note);
-                    }
-                }
-                final String noteStr = noteBuilder.toString();
-                // This means we scan noteStr completely twice, which is redundant.
-                // But for now, we assume this is not so time-consuming..
-                final boolean shouldAppendCharsetInfo =
-                    !VCardUtils.containsOnlyPrintableAscii(noteStr);
-                final boolean reallyUseQuotedPrintable =
-                        (mShouldUseQuotedPrintable &&
-                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr));
-                appendLine(VCardConstants.PROPERTY_NOTE, noteStr,
-                        shouldAppendCharsetInfo, reallyUseQuotedPrintable);
-            } else {
-                for (ContentValues contentValues : contentValuesList) {
-                    final String noteStr = contentValues.getAsString(Note.NOTE);
-                    if (!TextUtils.isEmpty(noteStr)) {
-                        final boolean shouldAppendCharsetInfo =
-                                !VCardUtils.containsOnlyPrintableAscii(noteStr);
-                        final boolean reallyUseQuotedPrintable =
-                                (mShouldUseQuotedPrintable &&
-                                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr));
-                        appendLine(VCardConstants.PROPERTY_NOTE, noteStr,
-                                shouldAppendCharsetInfo, reallyUseQuotedPrintable);
-                    }
-                }
-            }
-        }
-        return this;
-    }
-
-    public VCardBuilder appendEvents(final List<ContentValues> contentValuesList) {
-        // There's possibility where a given object may have more than one birthday, which
-        // is inappropriate. We just build one birthday.
-        if (contentValuesList != null) {
-            String primaryBirthday = null;
-            String secondaryBirthday = null;
-            for (final ContentValues contentValues : contentValuesList) {
-                if (contentValues == null) {
-                    continue;
-                }
-                final Integer eventTypeAsInteger = contentValues.getAsInteger(Event.TYPE);
-                final int eventType;
-                if (eventTypeAsInteger != null) {
-                    eventType = eventTypeAsInteger;
-                } else {
-                    eventType = Event.TYPE_OTHER;
-                }
-                if (eventType == Event.TYPE_BIRTHDAY) {
-                    final String birthdayCandidate = contentValues.getAsString(Event.START_DATE);
-                    if (birthdayCandidate == null) {
-                        continue;
-                    }
-                    final Integer isSuperPrimaryAsInteger =
-                        contentValues.getAsInteger(Event.IS_SUPER_PRIMARY);
-                    final boolean isSuperPrimary = (isSuperPrimaryAsInteger != null ?
-                            (isSuperPrimaryAsInteger > 0) : false);
-                    if (isSuperPrimary) {
-                        // "super primary" birthday should the prefered one.
-                        primaryBirthday = birthdayCandidate;
-                        break;
-                    }
-                    final Integer isPrimaryAsInteger =
-                        contentValues.getAsInteger(Event.IS_PRIMARY);
-                    final boolean isPrimary = (isPrimaryAsInteger != null ?
-                            (isPrimaryAsInteger > 0) : false);
-                    if (isPrimary) {
-                        // We don't break here since "super primary" birthday may exist later.
-                        primaryBirthday = birthdayCandidate;
-                    } else if (secondaryBirthday == null) {
-                        // First entry is set to the "secondary" candidate.
-                        secondaryBirthday = birthdayCandidate;
-                    }
-                } else if (mUsesAndroidProperty) {
-                    // Event types other than Birthday is not supported by vCard.
-                    appendAndroidSpecificProperty(Event.CONTENT_ITEM_TYPE, contentValues);
-                }
-            }
-            if (primaryBirthday != null) {
-                appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_BDAY,
-                        primaryBirthday.trim());
-            } else if (secondaryBirthday != null){
-                appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_BDAY,
-                        secondaryBirthday.trim());
-            }
-        }
-        return this;
-    }
-
-    public VCardBuilder appendRelation(final List<ContentValues> contentValuesList) {
-        if (mUsesAndroidProperty && contentValuesList != null) {
-            for (final ContentValues contentValues : contentValuesList) {
-                if (contentValues == null) {
-                    continue;
-                }
-                appendAndroidSpecificProperty(Relation.CONTENT_ITEM_TYPE, contentValues);
-            }
-        }
-        return this;
-    }
-
-    /**
-     * @param emitEveryTime If true, builder builds the line even when there's no entry.
-     */
-    public void appendPostalLine(final int type, final String label,
-            final ContentValues contentValues,
-            final boolean isPrimary, final boolean emitEveryTime) {
-        final boolean reallyUseQuotedPrintable;
-        final boolean appendCharset;
-        final String addressValue;
-        {
-            PostalStruct postalStruct = tryConstructPostalStruct(contentValues);
-            if (postalStruct == null) {
-                if (emitEveryTime) {
-                    reallyUseQuotedPrintable = false;
-                    appendCharset = false;
-                    addressValue = "";
-                } else {
-                    return;
-                }
-            } else {
-                reallyUseQuotedPrintable = postalStruct.reallyUseQuotedPrintable;
-                appendCharset = postalStruct.appendCharset;
-                addressValue = postalStruct.addressData;
-            }
-        }
-
-        List<String> parameterList = new ArrayList<String>();
-        if (isPrimary) {
-            parameterList.add(VCardConstants.PARAM_TYPE_PREF);
-        }
-        switch (type) {
-            case StructuredPostal.TYPE_HOME: {
-                parameterList.add(VCardConstants.PARAM_TYPE_HOME);
-                break;
-            }
-            case StructuredPostal.TYPE_WORK: {
-                parameterList.add(VCardConstants.PARAM_TYPE_WORK);
-                break;
-            }
-            case StructuredPostal.TYPE_CUSTOM: {
-                if (!TextUtils.isEmpty(label)
-                        && VCardUtils.containsOnlyAlphaDigitHyphen(label)) {
-                    // We're not sure whether the label is valid in the spec
-                    // ("IANA-token" in the vCard 3.0 is unclear...)
-                    // Just  for safety, we add "X-" at the beggining of each label.
-                    // Also checks the label obeys with vCard 3.0 spec.
-                    parameterList.add("X-" + label);
-                }
-                break;
-            }
-            case StructuredPostal.TYPE_OTHER: {
-                break;
-            }
-            default: {
-                Log.e(LOG_TAG, "Unknown StructuredPostal type: " + type);
-                break;
-            }
-        }
-
-        mBuilder.append(VCardConstants.PROPERTY_ADR);
-        if (!parameterList.isEmpty()) {
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            appendTypeParameters(parameterList);
-        }
-        if (appendCharset) {
-            // Strictly, vCard 3.0 does not allow exporters to emit charset information,
-            // but we will add it since the information should be useful for importers,
-            //
-            // Assume no parser does not emit error with this parameter in vCard 3.0.
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            mBuilder.append(mVCardCharsetParameter);
-        }
-        if (reallyUseQuotedPrintable) {
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            mBuilder.append(VCARD_PARAM_ENCODING_QP);
-        }
-        mBuilder.append(VCARD_DATA_SEPARATOR);
-        mBuilder.append(addressValue);
-        mBuilder.append(VCARD_END_OF_LINE);
-    }
-
-    public void appendEmailLine(final int type, final String label,
-            final String rawValue, final boolean isPrimary) {
-        final String typeAsString;
-        switch (type) {
-            case Email.TYPE_CUSTOM: {
-                if (VCardUtils.isMobilePhoneLabel(label)) {
-                    typeAsString = VCardConstants.PARAM_TYPE_CELL;
-                } else if (!TextUtils.isEmpty(label)
-                        && VCardUtils.containsOnlyAlphaDigitHyphen(label)) {
-                    typeAsString = "X-" + label;
-                } else {
-                    typeAsString = null;
-                }
-                break;
-            }
-            case Email.TYPE_HOME: {
-                typeAsString = VCardConstants.PARAM_TYPE_HOME;
-                break;
-            }
-            case Email.TYPE_WORK: {
-                typeAsString = VCardConstants.PARAM_TYPE_WORK;
-                break;
-            }
-            case Email.TYPE_OTHER: {
-                typeAsString = null;
-                break;
-            }
-            case Email.TYPE_MOBILE: {
-                typeAsString = VCardConstants.PARAM_TYPE_CELL;
-                break;
-            }
-            default: {
-                Log.e(LOG_TAG, "Unknown Email type: " + type);
-                typeAsString = null;
-                break;
-            }
-        }
-
-        final List<String> parameterList = new ArrayList<String>();
-        if (isPrimary) {
-            parameterList.add(VCardConstants.PARAM_TYPE_PREF);
-        }
-        if (!TextUtils.isEmpty(typeAsString)) {
-            parameterList.add(typeAsString);
-        }
-
-        appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_EMAIL, parameterList,
-                rawValue);
-    }
-
-    public void appendTelLine(final Integer typeAsInteger, final String label,
-            final String encodedValue, boolean isPrimary) {
-        mBuilder.append(VCardConstants.PROPERTY_TEL);
-        mBuilder.append(VCARD_PARAM_SEPARATOR);
-
-        final int type;
-        if (typeAsInteger == null) {
-            type = Phone.TYPE_OTHER;
-        } else {
-            type = typeAsInteger;
-        }
-
-        ArrayList<String> parameterList = new ArrayList<String>();
-        switch (type) {
-            case Phone.TYPE_HOME: {
-                parameterList.addAll(
-                        Arrays.asList(VCardConstants.PARAM_TYPE_HOME));
-                break;
-            }
-            case Phone.TYPE_WORK: {
-                parameterList.addAll(
-                        Arrays.asList(VCardConstants.PARAM_TYPE_WORK));
-                break;
-            }
-            case Phone.TYPE_FAX_HOME: {
-                parameterList.addAll(
-                        Arrays.asList(VCardConstants.PARAM_TYPE_HOME, VCardConstants.PARAM_TYPE_FAX));
-                break;
-            }
-            case Phone.TYPE_FAX_WORK: {
-                parameterList.addAll(
-                        Arrays.asList(VCardConstants.PARAM_TYPE_WORK, VCardConstants.PARAM_TYPE_FAX));
-                break;
-            }
-            case Phone.TYPE_MOBILE: {
-                parameterList.add(VCardConstants.PARAM_TYPE_CELL);
-                break;
-            }
-            case Phone.TYPE_PAGER: {
-                if (mIsDoCoMo) {
-                    // Not sure about the reason, but previous implementation had
-                    // used "VOICE" instead of "PAGER"
-                    parameterList.add(VCardConstants.PARAM_TYPE_VOICE);
-                } else {
-                    parameterList.add(VCardConstants.PARAM_TYPE_PAGER);
-                }
-                break;
-            }
-            case Phone.TYPE_OTHER: {
-                parameterList.add(VCardConstants.PARAM_TYPE_VOICE);
-                break;
-            }
-            case Phone.TYPE_CAR: {
-                parameterList.add(VCardConstants.PARAM_TYPE_CAR);
-                break;
-            }
-            case Phone.TYPE_COMPANY_MAIN: {
-                // There's no relevant field in vCard (at least 2.1).
-                parameterList.add(VCardConstants.PARAM_TYPE_WORK);
-                isPrimary = true;
-                break;
-            }
-            case Phone.TYPE_ISDN: {
-                parameterList.add(VCardConstants.PARAM_TYPE_ISDN);
-                break;
-            }
-            case Phone.TYPE_MAIN: {
-                isPrimary = true;
-                break;
-            }
-            case Phone.TYPE_OTHER_FAX: {
-                parameterList.add(VCardConstants.PARAM_TYPE_FAX);
-                break;
-            }
-            case Phone.TYPE_TELEX: {
-                parameterList.add(VCardConstants.PARAM_TYPE_TLX);
-                break;
-            }
-            case Phone.TYPE_WORK_MOBILE: {
-                parameterList.addAll(
-                        Arrays.asList(VCardConstants.PARAM_TYPE_WORK, VCardConstants.PARAM_TYPE_CELL));
-                break;
-            }
-            case Phone.TYPE_WORK_PAGER: {
-                parameterList.add(VCardConstants.PARAM_TYPE_WORK);
-                // See above.
-                if (mIsDoCoMo) {
-                    parameterList.add(VCardConstants.PARAM_TYPE_VOICE);
-                } else {
-                    parameterList.add(VCardConstants.PARAM_TYPE_PAGER);
-                }
-                break;
-            }
-            case Phone.TYPE_MMS: {
-                parameterList.add(VCardConstants.PARAM_TYPE_MSG);
-                break;
-            }
-            case Phone.TYPE_CUSTOM: {
-                if (TextUtils.isEmpty(label)) {
-                    // Just ignore the custom type.
-                    parameterList.add(VCardConstants.PARAM_TYPE_VOICE);
-                } else if (VCardUtils.isMobilePhoneLabel(label)) {
-                    parameterList.add(VCardConstants.PARAM_TYPE_CELL);
-                } else if (mIsV30OrV40) {
-                    // This label is appropriately encoded in appendTypeParameters.
-                    parameterList.add(label);
-                } else {
-                    final String upperLabel = label.toUpperCase();
-                    if (VCardUtils.isValidInV21ButUnknownToContactsPhoteType(upperLabel)) {
-                        parameterList.add(upperLabel);
-                    } else if (VCardUtils.containsOnlyAlphaDigitHyphen(label)) {
-                        // Note: Strictly, vCard 2.1 does not allow "X-" parameter without
-                        //       "TYPE=" string.
-                        parameterList.add("X-" + label);
-                    }
-                }
-                break;
-            }
-            case Phone.TYPE_RADIO:
-            case Phone.TYPE_TTY_TDD:
-            default: {
-                break;
-            }
-        }
-
-        if (isPrimary) {
-            parameterList.add(VCardConstants.PARAM_TYPE_PREF);
-        }
-
-        if (parameterList.isEmpty()) {
-            appendUncommonPhoneType(mBuilder, type);
-        } else {
-            appendTypeParameters(parameterList);
-        }
-
-        mBuilder.append(VCARD_DATA_SEPARATOR);
-        mBuilder.append(encodedValue);
-        mBuilder.append(VCARD_END_OF_LINE);
-    }
-
-    /**
-     * Appends phone type string which may not be available in some devices.
-     */
-    private void appendUncommonPhoneType(final StringBuilder builder, final Integer type) {
-        if (mIsDoCoMo) {
-            // The previous implementation for DoCoMo had been conservative
-            // about miscellaneous types.
-            builder.append(VCardConstants.PARAM_TYPE_VOICE);
-        } else {
-            String phoneType = VCardUtils.getPhoneTypeString(type);
-            if (phoneType != null) {
-                appendTypeParameter(phoneType);
-            } else {
-                Log.e(LOG_TAG, "Unknown or unsupported (by vCard) Phone type: " + type);
-            }
-        }
-    }
-
-    /**
-     * @param encodedValue Must be encoded by BASE64 
-     * @param photoType
-     */
-    public void appendPhotoLine(final String encodedValue, final String photoType) {
-        StringBuilder tmpBuilder = new StringBuilder();
-        tmpBuilder.append(VCardConstants.PROPERTY_PHOTO);
-        tmpBuilder.append(VCARD_PARAM_SEPARATOR);
-        if (mIsV30OrV40) {
-            tmpBuilder.append(VCARD_PARAM_ENCODING_BASE64_AS_B);
-        } else {
-            tmpBuilder.append(VCARD_PARAM_ENCODING_BASE64_V21);
-        }
-        tmpBuilder.append(VCARD_PARAM_SEPARATOR);
-        appendTypeParameter(tmpBuilder, photoType);
-        tmpBuilder.append(VCARD_DATA_SEPARATOR);
-        tmpBuilder.append(encodedValue);
-
-        final String tmpStr = tmpBuilder.toString();
-        tmpBuilder = new StringBuilder();
-        int lineCount = 0;
-        final int length = tmpStr.length();
-        final int maxNumForFirstLine = VCardConstants.MAX_CHARACTER_NUMS_BASE64_V30
-                - VCARD_END_OF_LINE.length();
-        final int maxNumInGeneral = maxNumForFirstLine - VCARD_WS.length();
-        int maxNum = maxNumForFirstLine;
-        for (int i = 0; i < length; i++) {
-            tmpBuilder.append(tmpStr.charAt(i));
-            lineCount++;
-            if (lineCount > maxNum) {
-                tmpBuilder.append(VCARD_END_OF_LINE);
-                tmpBuilder.append(VCARD_WS);
-                maxNum = maxNumInGeneral;
-                lineCount = 0;
-            }
-        }
-        mBuilder.append(tmpBuilder.toString());
-        mBuilder.append(VCARD_END_OF_LINE);
-        mBuilder.append(VCARD_END_OF_LINE);
-    }
-
-    /**
-     * SIP (Session Initiation Protocol) is first supported in RFC 4770 as part of IMPP
-     * support. vCard 2.1 and old vCard 3.0 may not able to parse it, or expect X-SIP
-     * instead of "IMPP;sip:...".
-     *
-     * We honor RFC 4770 and don't allow vCard 3.0 to emit X-SIP at all.
-     */
-    public VCardBuilder appendSipAddresses(final List<ContentValues> contentValuesList) {
-        final boolean useXProperty;
-        if (mIsV30OrV40) {
-            useXProperty = false;
-        } else if (mUsesDefactProperty){
-            useXProperty = true;
-        } else {
-            return this;
-        }
-
-        if (contentValuesList != null) {
-            for (ContentValues contentValues : contentValuesList) {
-                String sipAddress = contentValues.getAsString(SipAddress.SIP_ADDRESS);
-                if (TextUtils.isEmpty(sipAddress)) {
-                    continue;
-                }
-                if (useXProperty) {
-                    // X-SIP does not contain "sip:" prefix.
-                    if (sipAddress.startsWith("sip:")) {
-                        if (sipAddress.length() == 4) {
-                            continue;
-                        }
-                        sipAddress = sipAddress.substring(4);
-                    }
-                    // No type is available yet.
-                    appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_X_SIP, sipAddress);
-                } else {
-                    if (!sipAddress.startsWith("sip:")) {
-                        sipAddress = "sip:" + sipAddress;
-                    }
-                    final String propertyName;
-                    if (VCardConfig.isVersion40(mVCardType)) {
-                        // We have two ways to emit sip address: TEL and IMPP. Currently (rev.13)
-                        // TEL seems appropriate but may change in the future.
-                        propertyName = VCardConstants.PROPERTY_TEL;
-                    } else {
-                        // RFC 4770 (for vCard 3.0)
-                        propertyName = VCardConstants.PROPERTY_IMPP;
-                    }
-                    appendLineWithCharsetAndQPDetection(propertyName, sipAddress);
-                }
-            }
-        }
-        return this;
-    }
-
-    public void appendAndroidSpecificProperty(
-            final String mimeType, ContentValues contentValues) {
-        if (!sAllowedAndroidPropertySet.contains(mimeType)) {
-            return;
-        }
-        final List<String> rawValueList = new ArrayList<String>();
-        for (int i = 1; i <= VCardConstants.MAX_DATA_COLUMN; i++) {
-            String value = contentValues.getAsString("data" + i);
-            if (value == null) {
-                value = "";
-            }
-            rawValueList.add(value);
-        }
-
-        boolean needCharset =
-            (mShouldAppendCharsetParam &&
-                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
-        boolean reallyUseQuotedPrintable =
-            (mShouldUseQuotedPrintable &&
-                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
-        mBuilder.append(VCardConstants.PROPERTY_X_ANDROID_CUSTOM);
-        if (needCharset) {
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            mBuilder.append(mVCardCharsetParameter);
-        }
-        if (reallyUseQuotedPrintable) {
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            mBuilder.append(VCARD_PARAM_ENCODING_QP);
-        }
-        mBuilder.append(VCARD_DATA_SEPARATOR);
-        mBuilder.append(mimeType);  // Should not be encoded.
-        for (String rawValue : rawValueList) {
-            final String encodedValue;
-            if (reallyUseQuotedPrintable) {
-                encodedValue = encodeQuotedPrintable(rawValue);
-            } else {
-                // TODO: one line may be too huge, which may be invalid in vCard 3.0
-                //        (which says "When generating a content line, lines longer than
-                //        75 characters SHOULD be folded"), though several
-                //        (even well-known) applications do not care this.
-                encodedValue = escapeCharacters(rawValue);
-            }
-            mBuilder.append(VCARD_ITEM_SEPARATOR);
-            mBuilder.append(encodedValue);
-        }
-        mBuilder.append(VCARD_END_OF_LINE);
-    }
-
-    public void appendLineWithCharsetAndQPDetection(final String propertyName,
-            final String rawValue) {
-        appendLineWithCharsetAndQPDetection(propertyName, null, rawValue);
-    }
-
-    public void appendLineWithCharsetAndQPDetection(
-            final String propertyName, final List<String> rawValueList) {
-        appendLineWithCharsetAndQPDetection(propertyName, null, rawValueList);
-    }
-
-    public void appendLineWithCharsetAndQPDetection(final String propertyName,
-            final List<String> parameterList, final String rawValue) {
-        final boolean needCharset =
-                !VCardUtils.containsOnlyPrintableAscii(rawValue);
-        final boolean reallyUseQuotedPrintable =
-                (mShouldUseQuotedPrintable &&
-                        !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValue));
-        appendLine(propertyName, parameterList,
-                rawValue, needCharset, reallyUseQuotedPrintable);
-    }
-
-    public void appendLineWithCharsetAndQPDetection(final String propertyName,
-            final List<String> parameterList, final List<String> rawValueList) {
-        boolean needCharset =
-            (mShouldAppendCharsetParam &&
-                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
-        boolean reallyUseQuotedPrintable =
-            (mShouldUseQuotedPrintable &&
-                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
-        appendLine(propertyName, parameterList, rawValueList,
-                needCharset, reallyUseQuotedPrintable);
-    }
-
-    /**
-     * Appends one line with a given property name and value.  
-     */
-    public void appendLine(final String propertyName, final String rawValue) {
-        appendLine(propertyName, rawValue, false, false);
-    }
-
-    public void appendLine(final String propertyName, final List<String> rawValueList) {
-        appendLine(propertyName, rawValueList, false, false);
-    }
-
-    public void appendLine(final String propertyName,
-            final String rawValue, final boolean needCharset,
-            boolean reallyUseQuotedPrintable) {
-        appendLine(propertyName, null, rawValue, needCharset, reallyUseQuotedPrintable);
-    }
-
-    public void appendLine(final String propertyName, final List<String> parameterList,
-            final String rawValue) {
-        appendLine(propertyName, parameterList, rawValue, false, false);
-    }
-
-    public void appendLine(final String propertyName, final List<String> parameterList,
-            final String rawValue, final boolean needCharset,
-            boolean reallyUseQuotedPrintable) {
-        mBuilder.append(propertyName);
-        if (parameterList != null && parameterList.size() > 0) {
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            appendTypeParameters(parameterList);
-        }
-        if (needCharset) {
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            mBuilder.append(mVCardCharsetParameter);
-        }
-
-        final String encodedValue;
-        if (reallyUseQuotedPrintable) {
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            mBuilder.append(VCARD_PARAM_ENCODING_QP);
-            encodedValue = encodeQuotedPrintable(rawValue);
-        } else {
-            // TODO: one line may be too huge, which may be invalid in vCard spec, though
-            //       several (even well-known) applications do not care that violation.
-            encodedValue = escapeCharacters(rawValue);
-        }
-
-        mBuilder.append(VCARD_DATA_SEPARATOR);
-        mBuilder.append(encodedValue);
-        mBuilder.append(VCARD_END_OF_LINE);
-    }
-
-    public void appendLine(final String propertyName, final List<String> rawValueList,
-            final boolean needCharset, boolean needQuotedPrintable) {
-        appendLine(propertyName, null, rawValueList, needCharset, needQuotedPrintable);
-    }
-
-    public void appendLine(final String propertyName, final List<String> parameterList,
-            final List<String> rawValueList, final boolean needCharset,
-            final boolean needQuotedPrintable) {
-        mBuilder.append(propertyName);
-        if (parameterList != null && parameterList.size() > 0) {
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            appendTypeParameters(parameterList);
-        }
-        if (needCharset) {
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            mBuilder.append(mVCardCharsetParameter);
-        }
-        if (needQuotedPrintable) {
-            mBuilder.append(VCARD_PARAM_SEPARATOR);
-            mBuilder.append(VCARD_PARAM_ENCODING_QP);
-        }
-
-        mBuilder.append(VCARD_DATA_SEPARATOR);
-        boolean first = true;
-        for (String rawValue : rawValueList) {
-            final String encodedValue;
-            if (needQuotedPrintable) {
-                encodedValue = encodeQuotedPrintable(rawValue);
-            } else {
-                // TODO: one line may be too huge, which may be invalid in vCard 3.0
-                //        (which says "When generating a content line, lines longer than
-                //        75 characters SHOULD be folded"), though several
-                //        (even well-known) applications do not care this.
-                encodedValue = escapeCharacters(rawValue);
-            }
-
-            if (first) {
-                first = false;
-            } else {
-                mBuilder.append(VCARD_ITEM_SEPARATOR);
-            }
-            mBuilder.append(encodedValue);
-        }
-        mBuilder.append(VCARD_END_OF_LINE);
-    }
-
-    /**
-     * VCARD_PARAM_SEPARATOR must be appended before this method being called.
-     */
-    private void appendTypeParameters(final List<String> types) {
-        // 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.
-        boolean first = true;
-        for (final String typeValue : types) {
-            if (VCardConfig.isVersion30(mVCardType) || VCardConfig.isVersion40(mVCardType)) {
-                final String encoded = (VCardConfig.isVersion40(mVCardType) ?
-                        VCardUtils.toStringAsV40ParamValue(typeValue) :
-                        VCardUtils.toStringAsV30ParamValue(typeValue));
-                if (TextUtils.isEmpty(encoded)) {
-                    continue;
-                }
-
-                if (first) {
-                    first = false;
-                } else {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                }
-                appendTypeParameter(encoded);
-            } else {  // vCard 2.1
-                if (!VCardUtils.isV21Word(typeValue)) {
-                    continue;
-                }
-                if (first) {
-                    first = false;
-                } else {
-                    mBuilder.append(VCARD_PARAM_SEPARATOR);
-                }
-                appendTypeParameter(typeValue);
-            }
-        }
-    }
-
-    /**
-     * VCARD_PARAM_SEPARATOR must be appended before this method being called.
-     */
-    private void appendTypeParameter(final String type) {
-        appendTypeParameter(mBuilder, type);
-    }
-
-    private void appendTypeParameter(final StringBuilder builder, final String type) {
-        // Refrain from using appendType() so that "TYPE=" is not be appended when the
-        // device is DoCoMo's (just for safety).
-        //
-        // Note: In vCard 3.0, Type strings also can be like this: "TYPE=HOME,PREF"
-        if (VCardConfig.isVersion40(mVCardType) ||
-                ((VCardConfig.isVersion30(mVCardType) || mAppendTypeParamName) && !mIsDoCoMo)) {
-            builder.append(VCardConstants.PARAM_TYPE).append(VCARD_PARAM_EQUAL);
-        }
-        builder.append(type);
-    }
-
-    /**
-     * Returns true when the property line should contain charset parameter
-     * information. This method may return true even when vCard version is 3.0.
-     *
-     * Strictly, adding charset information is invalid in VCard 3.0.
-     * However we'll add the info only when charset we use is not UTF-8
-     * in vCard 3.0 format, since parser side may be able to use the charset
-     * via this field, though we may encounter another problem by adding it.
-     *
-     * e.g. Japanese mobile phones use Shift_Jis while RFC 2426
-     * recommends UTF-8. By adding this field, parsers may be able
-     * to know this text is NOT UTF-8 but Shift_Jis.
-     */
-    private boolean shouldAppendCharsetParam(String...propertyValueList) {
-        if (!mShouldAppendCharsetParam) {
-            return false;
-        }
-        for (String propertyValue : propertyValueList) {
-            if (!VCardUtils.containsOnlyPrintableAscii(propertyValue)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private String encodeQuotedPrintable(final String str) {
-        if (TextUtils.isEmpty(str)) {
-            return "";
-        }
-
-        final StringBuilder builder = new StringBuilder();
-        int index = 0;
-        int lineCount = 0;
-        byte[] strArray = null;
-
-        try {
-            strArray = str.getBytes(mCharset);
-        } catch (UnsupportedEncodingException e) {
-            Log.e(LOG_TAG, "Charset " + mCharset + " cannot be used. "
-                    + "Try default charset");
-            strArray = str.getBytes();
-        }
-        while (index < strArray.length) {
-            builder.append(String.format("=%02X", strArray[index]));
-            index += 1;
-            lineCount += 3;
-
-            if (lineCount >= 67) {
-                // Specification requires CRLF must be inserted before the
-                // length of the line
-                // becomes more than 76.
-                // Assuming that the next character is a multi-byte character,
-                // it will become
-                // 6 bytes.
-                // 76 - 6 - 3 = 67
-                builder.append("=\r\n");
-                lineCount = 0;
-            }
-        }
-
-        return builder.toString();
-    }
-
-    /**
-     * Append '\' to the characters which should be escaped. The character set is different
-     * not only between vCard 2.1 and vCard 3.0 but also among each device.
-     *
-     * Note that Quoted-Printable string must not be input here.
-     */
-    @SuppressWarnings("fallthrough")
-    private String escapeCharacters(final String unescaped) {
-        if (TextUtils.isEmpty(unescaped)) {
-            return "";
-        }
-
-        final StringBuilder tmpBuilder = new StringBuilder();
-        final int length = unescaped.length();
-        for (int i = 0; i < length; i++) {
-            final char ch = unescaped.charAt(i);
-            switch (ch) {
-                case ';': {
-                    tmpBuilder.append('\\');
-                    tmpBuilder.append(';');
-                    break;
-                }
-                case '\r': {
-                    if (i + 1 < length) {
-                        char nextChar = unescaped.charAt(i);
-                        if (nextChar == '\n') {
-                            break;
-                        } else {
-                            // fall through
-                        }
-                    } else {
-                        // fall through
-                    }
-                }
-                case '\n': {
-                    // In vCard 2.1, there's no specification about this, while
-                    // vCard 3.0 explicitly requires this should be encoded to "\n".
-                    tmpBuilder.append("\\n");
-                    break;
-                }
-                case '\\': {
-                    if (mIsV30OrV40) {
-                        tmpBuilder.append("\\\\");
-                        break;
-                    } else {
-                        // fall through
-                    }
-                }
-                case '<':
-                case '>': {
-                    if (mIsDoCoMo) {
-                        tmpBuilder.append('\\');
-                        tmpBuilder.append(ch);
-                    } else {
-                        tmpBuilder.append(ch);
-                    }
-                    break;
-                }
-                case ',': {
-                    if (mIsV30OrV40) {
-                        tmpBuilder.append("\\,");
-                    } else {
-                        tmpBuilder.append(ch);
-                    }
-                    break;
-                }
-                default: {
-                    tmpBuilder.append(ch);
-                    break;
-                }
-            }
-        }
-        return tmpBuilder.toString();
-    }
-
-    @Override
-    public String toString() {
-        if (!mEndAppended) {
-            if (mIsDoCoMo) {
-                appendLine(VCardConstants.PROPERTY_X_CLASS, VCARD_DATA_PUBLIC);
-                appendLine(VCardConstants.PROPERTY_X_REDUCTION, "");
-                appendLine(VCardConstants.PROPERTY_X_NO, "");
-                appendLine(VCardConstants.PROPERTY_X_DCM_HMN_MODE, "");
-            }
-            appendLine(VCardConstants.PROPERTY_END, VCARD_DATA_VCARD);
-            mEndAppended = true;
-        }
-        return mBuilder.toString();
-    }
-}
diff --git a/src/com/android/vcard/VCardConfig.java b/src/com/android/vcard/VCardConfig.java
deleted file mode 100644
index c43d672..0000000
--- a/src/com/android/vcard/VCardConfig.java
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import android.telephony.PhoneNumberUtils;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * The class representing VCard related configurations. Useful static methods are not in this class
- * but in VCardUtils.
- */
-public class VCardConfig {
-    private static final String LOG_TAG = "VCardConfig";
-
-    /* package */ static final int LOG_LEVEL_NONE = 0;
-    /* package */ static final int LOG_LEVEL_PERFORMANCE_MEASUREMENT = 0x1;
-    /* package */ static final int LOG_LEVEL_SHOW_WARNING = 0x2;
-    /* package */ static final int LOG_LEVEL_VERBOSE =
-        LOG_LEVEL_PERFORMANCE_MEASUREMENT | LOG_LEVEL_SHOW_WARNING;
-
-    /* package */ static final int LOG_LEVEL = LOG_LEVEL_NONE;
-
-    /**
-     * <p>
-     * The charset used during import.
-     * </p>
-     * <p>
-     * We cannot determine which charset should be used to interpret lines in vCard,
-     * while Java requires us to specify it when InputStream is used.
-     * We need to rely on the mechanism due to some performance reason.
-     * </p>
-     * <p>
-     * In order to avoid "misinterpretation" of charset and lose any data in vCard,
-     * "ISO-8859-1" is first used for reading the stream.
-     * When a charset is specified in a property (with "CHARSET=..." parameter),
-     * the string is decoded to raw bytes and encoded into the specific charset,
-     * </p>
-     * <p>
-     * Unicode specification there's a one to one mapping between each byte in ISO-8859-1
-     * and a codepoint, and Java specification requires runtime must have the charset.
-     * Thus, ISO-8859-1 is one effective mapping for intermediate mapping.
-     * </p>
-     */
-    public static final String DEFAULT_INTERMEDIATE_CHARSET = "ISO-8859-1";
-
-    /**
-     * The charset used when there's no information affbout what charset should be used to
-     * encode the binary given from vCard.
-     */
-    public static final String DEFAULT_IMPORT_CHARSET = "UTF-8";
-    public static final String DEFAULT_EXPORT_CHARSET = "UTF-8";
-
-    /**
-     * Do not use statically like "version == VERSION_V21"
-     */
-    public static final int VERSION_21 = 0;
-    public static final int VERSION_30 = 1;
-    public static final int VERSION_40 = 2;
-    public static final int VERSION_MASK = 3;
-
-    public static final int NAME_ORDER_DEFAULT = 0;
-    public static final int NAME_ORDER_EUROPE = 0x4;
-    public static final int NAME_ORDER_JAPANESE = 0x8;
-    private static final int NAME_ORDER_MASK = 0xC;
-
-    // 0x10 is reserved for safety
-
-    /**
-     * <p>
-     * The flag indicating the vCard composer will add some "X-" properties used only in Android
-     * when the formal vCard specification does not have appropriate fields for that data.
-     * </p>
-     * <p>
-     * For example, Android accepts nickname information while vCard 2.1 does not.
-     * When this flag is on, vCard composer emits alternative "X-" property (like "X-NICKNAME")
-     * instead of just dropping it.
-     * </p>
-     * <p>
-     * vCard parser code automatically parses the field emitted even when this flag is off.
-     * </p>
-     */
-    private static final int FLAG_USE_ANDROID_PROPERTY = 0x80000000;
-    
-    /**
-     * <p>
-     * The flag indicating the vCard composer will add some "X-" properties seen in the
-     * vCard data emitted by the other softwares/devices when the formal vCard specification
-     * does not have appropriate field(s) for that data.
-     * </p> 
-     * <p>
-     * One example is X-PHONETIC-FIRST-NAME/X-PHONETIC-MIDDLE-NAME/X-PHONETIC-LAST-NAME, which are
-     * for phonetic name (how the name is pronounced), seen in the vCard emitted by some other
-     * non-Android devices/softwares. We chose to enable the vCard composer to use those
-     * defact properties since they are also useful for Android devices.
-     * </p>
-     * <p>
-     * Note for developers: only "X-" properties should be added with this flag. vCard 2.1/3.0
-     * allows any kind of "X-" properties but does not allow non-"X-" properties (except IANA tokens
-     * in vCard 3.0). Some external parsers may get confused with non-valid, non-"X-" properties.
-     * </p>
-     */
-    private static final int FLAG_USE_DEFACT_PROPERTY = 0x40000000;
-
-    /**
-     * <p>
-     * The flag indicating some specific dialect seen in vCard of DoCoMo (one of Japanese
-     * mobile careers) should be used. This flag does not include any other information like
-     * that "the vCard is for Japanese". So it is "possible" that "the vCard should have DoCoMo's
-     * dialect but the name order should be European", but it is not recommended.
-     * </p>
-     */
-    private static final int FLAG_DOCOMO = 0x20000000;
-
-    /**
-     * <p>
-     * The flag indicating the vCard composer does "NOT" use Quoted-Printable toward "primary"
-     * properties even though it is required by vCard 2.1 (QP is prohibited in vCard 3.0).
-     * </p>
-     * <p>
-     * We actually cannot define what is the "primary" property. Note that this is NOT defined
-     * in vCard specification either. Also be aware that it is NOT related to "primary" notion
-     * used in {@link android.provider.ContactsContract}.
-     * This notion is just for vCard composition in Android.
-     * </p>
-     * <p>
-     * We added this Android-specific notion since some (incomplete) vCard exporters for vCard 2.1
-     * do NOT use Quoted-Printable encoding toward some properties related names like "N", "FN", etc.
-     * even when their values contain non-ascii or/and CR/LF, while they use the encoding in the
-     * other properties like "ADR", "ORG", etc.
-     * <p>
-     * We are afraid of the case where some vCard importer also forget handling QP presuming QP is
-     * not used in such fields.
-     * </p>
-     * <p>
-     * This flag is useful when some target importer you are going to focus on does not accept
-     * such properties with Quoted-Printable encoding.
-     * </p>
-     * <p>
-     * Again, we should not use this flag at all for complying vCard 2.1 spec.
-     * </p>
-     * <p>
-     * In vCard 3.0, Quoted-Printable is explicitly "prohibitted", so we don't need to care this
-     * kind of problem (hopefully).
-     * </p>
-     * @hide
-     */
-    public static final int FLAG_REFRAIN_QP_TO_NAME_PROPERTIES = 0x10000000;
-
-    /**
-     * <p>
-     * The flag indicating that phonetic name related fields must be converted to
-     * appropriate form. Note that "appropriate" is not defined in any vCard specification.
-     * This is Android-specific.
-     * </p>
-     * <p>
-     * One typical (and currently sole) example where we need this flag is the time when
-     * we need to emit Japanese phonetic names into vCard entries. The property values
-     * should be encoded into half-width katakana when the target importer is Japanese mobile
-     * phones', which are probably not able to parse full-width hiragana/katakana for
-     * historical reasons, while the vCard importers embedded to softwares for PC should be
-     * able to parse them as we expect.
-     * </p>
-     */
-    public static final int FLAG_CONVERT_PHONETIC_NAME_STRINGS = 0x08000000;
-
-    /**
-     * <p>
-     * The flag indicating the vCard composer "for 2.1" emits "TYPE=" string toward TYPE params
-     * every time possible. The default behavior does not emit it and is valid in the spec.
-     * In vCrad 3.0, this flag is unnecessary, since "TYPE=" is MUST in vCard 3.0 specification.
-     * </p>
-     * <p>
-     * Detail:
-     * How more than one TYPE fields are expressed is different between vCard 2.1 and vCard 3.0.
-     * </p>
-     * <p>
-     * e.g.
-     * </p>
-     * <ol>
-     * <li>Probably valid in both vCard 2.1 and vCard 3.0: "ADR;TYPE=DOM;TYPE=HOME:..."</li>
-     * <li>Valid in vCard 2.1 but not in vCard 3.0: "ADR;DOM;HOME:..."</li>
-     * <li>Valid in vCard 3.0 but not in vCard 2.1: "ADR;TYPE=DOM,HOME:..."</li>
-     * </ol>
-     * <p>
-     * If you are targeting to the importer which cannot accept TYPE params without "TYPE="
-     * strings (which should be rare though), please use this flag.
-     * </p>
-     * <p>
-     * Example usage:
-     * <pre class="prettyprint">int type = (VCARD_TYPE_V21_GENERIC | FLAG_APPEND_TYPE_PARAM);</pre>
-     * </p>
-     */
-    public static final int FLAG_APPEND_TYPE_PARAM = 0x04000000;
-
-    /**
-     * <p>
-     * The flag indicating the vCard composer does touch nothing toward phone number Strings
-     * but leave it as is.
-     * </p>
-     * <p>
-     * The vCard specifications mention nothing toward phone numbers, while some devices
-     * do (wrongly, but with innevitable reasons).
-     * For example, there's a possibility Japanese mobile phones are expected to have
-     * just numbers, hypens, plus, etc. but not usual alphabets, while US mobile phones
-     * should get such characters. To make exported vCard simple for external parsers,
-     * we have used {@link PhoneNumberUtils#formatNumber(String)} during export, and
-     * removed unnecessary characters inside the number (e.g. "111-222-3333 (Miami)"
-     * becomes "111-222-3333").
-     * Unfortunate side effect of that use was some control characters used in the other
-     * areas may be badly affected by the formatting.
-     * </p>
-     * <p>
-     * This flag disables that formatting, affecting both importer and exporter.
-     * If the user is aware of some side effects due to the implicit formatting, use this flag.
-     * </p>
-     */
-    public static final int FLAG_REFRAIN_PHONE_NUMBER_FORMATTING = 0x02000000;
-
-    /**
-     * <p>
-     * For importer only. Ignored in exporter.
-     * </p>
-     * <p>
-     * The flag indicating the parser should handle a nested vCard, in which vCard clause starts
-     * in another vCard clause. Here's a typical example.
-     * </p>
-     * <pre class="prettyprint">BEGIN:VCARD
-     * BEGIN:VCARD
-     * VERSION:2.1
-     * ...
-     * END:VCARD
-     * END:VCARD</pre>
-     * <p>
-     * The vCard 2.1 specification allows the nest, but also let parsers ignore nested entries,
-     * while some mobile devices emit nested ones as primary data to be imported.
-     * </p>
-     * <p>
-     * This flag forces a vCard parser to torelate such a nest and understand its content.
-     * </p>
-     */
-    public static final int FLAG_TORELATE_NEST = 0x01000000;
-
-    /**
-     * <P>
-     * The flag asking exporter to refrain image export.
-     * </P>
-     * @hide will be deleted in the near future.
-     */
-    public static final int FLAG_REFRAIN_IMAGE_EXPORT = 0x00800000;
-
-    //// The followings are VCard types available from importer/exporter. ////
-
-    /**
-     * <p>
-     * The type indicating nothing. Used by {@link VCardSourceDetector} when it
-     * was not able to guess the exact vCard type.
-     * </p>
-     */
-    public static final int VCARD_TYPE_UNKNOWN = 0;
-
-    /**
-     * <p>
-     * Generic vCard format with the vCard 2.1. When composing a vCard entry,
-     * the US convension will be used toward formatting some values.
-     * </p>
-     * <p>
-     * e.g. The order of the display name would be "Prefix Given Middle Family Suffix",
-     * while it should be "Prefix Family Middle Given Suffix" in Japan for example.
-     * </p>
-     * <p>
-     * Uses UTF-8 for the charset as a charset for exporting. Note that old vCard importer
-     * outside Android cannot accept it since vCard 2.1 specifically does not allow
-     * that charset, while we need to use it to support various languages around the world.
-     * </p>
-     * <p>
-     * If you want to use alternative charset, you should notify the charset to the other
-     * compontent to be used.
-     * </p>
-     */
-    public static final int VCARD_TYPE_V21_GENERIC =
-        (VERSION_21 | NAME_ORDER_DEFAULT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
-
-    /* package */ static String VCARD_TYPE_V21_GENERIC_STR = "v21_generic";
-    
-    /**
-     * <p>
-     * General vCard format with the version 3.0. Uses UTF-8 for the charset.
-     * </p>
-     * <p>
-     * Not fully ready yet. Use with caution when you use this.
-     * </p>
-     */
-    public static final int VCARD_TYPE_V30_GENERIC =
-        (VERSION_30 | NAME_ORDER_DEFAULT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
-
-    /* package */ static final String VCARD_TYPE_V30_GENERIC_STR = "v30_generic";
-
-    /**
-     * General vCard format with the version 4.0.
-     * @hide vCard 4.0 is not published yet.
-     */
-    public static final int VCARD_TYPE_V40_GENERIC =
-        (VERSION_40 | NAME_ORDER_DEFAULT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
-
-    /* package */ static final String VCARD_TYPE_V40_GENERIC_STR = "v40_generic";
-
-    /**
-     * <p>
-     * General vCard format for the vCard 2.1 with some Europe convension. Uses Utf-8.
-     * Currently, only name order is considered ("Prefix Middle Given Family Suffix")
-     * </p>
-     */
-    public static final int VCARD_TYPE_V21_EUROPE =
-        (VERSION_21 | NAME_ORDER_EUROPE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
-
-    /* package */ static final String VCARD_TYPE_V21_EUROPE_STR = "v21_europe";
-    
-    /**
-     * <p>
-     * General vCard format with the version 3.0 with some Europe convension. Uses UTF-8.
-     * </p>
-     * <p>
-     * Not ready yet. Use with caution when you use this.
-     * </p>
-     */
-    public static final int VCARD_TYPE_V30_EUROPE =
-        (VERSION_30 | NAME_ORDER_EUROPE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
-    
-    /* package */ static final String VCARD_TYPE_V30_EUROPE_STR = "v30_europe";
-
-    /**
-     * <p>
-     * The vCard 2.1 format for miscellaneous Japanese devices, using UTF-8 as default charset.
-     * </p>
-     * <p>
-     * Not ready yet. Use with caution when you use this.
-     * </p>
-     */
-    public static final int VCARD_TYPE_V21_JAPANESE =
-        (VERSION_21 | NAME_ORDER_JAPANESE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
-
-    /* package */ static final String VCARD_TYPE_V21_JAPANESE_STR = "v21_japanese_utf8";
-
-    /**
-     * <p>
-     * The vCard 3.0 format for miscellaneous Japanese devices, using UTF-8 as default charset.
-     * </p>
-     * <p>
-     * Not ready yet. Use with caution when you use this.
-     * </p>
-     */
-    public static final int VCARD_TYPE_V30_JAPANESE =
-        (VERSION_30 | NAME_ORDER_JAPANESE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
-
-    /* package */ static final String VCARD_TYPE_V30_JAPANESE_STR = "v30_japanese_utf8";
-
-    /**
-     * <p>
-     * The vCard 2.1 based format which (partially) considers the convention in Japanese
-     * mobile phones, where phonetic names are translated to half-width katakana if
-     * possible, etc. It would be better to use Shift_JIS as a charset for maximum
-     * compatibility.
-     * </p>
-     * @hide Should not be available world wide.
-     */
-    public static final int VCARD_TYPE_V21_JAPANESE_MOBILE =
-        (VERSION_21 | NAME_ORDER_JAPANESE |
-                FLAG_CONVERT_PHONETIC_NAME_STRINGS | FLAG_REFRAIN_QP_TO_NAME_PROPERTIES);
-
-    /* package */ static final String VCARD_TYPE_V21_JAPANESE_MOBILE_STR = "v21_japanese_mobile";
-
-    /**
-     * <p>
-     * The vCard format used in DoCoMo, which is one of Japanese mobile phone careers.
-     * </p>
-     * <p>
-     * Base version is vCard 2.1, but the data has several DoCoMo-specific convensions.
-     * No Android-specific property nor defact property is included. The "Primary" properties
-     * are NOT encoded to Quoted-Printable.
-     * </p>
-     * @hide Should not be available world wide.
-     */
-    public static final int VCARD_TYPE_DOCOMO =
-        (VCARD_TYPE_V21_JAPANESE_MOBILE | FLAG_DOCOMO);
-
-    /* package */ static final String VCARD_TYPE_DOCOMO_STR = "docomo";
-
-    public static int VCARD_TYPE_DEFAULT = VCARD_TYPE_V21_GENERIC;
-
-    private static final Map<String, Integer> sVCardTypeMap;
-    private static final Set<Integer> sJapaneseMobileTypeSet;
-    
-    static {
-        sVCardTypeMap = new HashMap<String, Integer>();
-        sVCardTypeMap.put(VCARD_TYPE_V21_GENERIC_STR, VCARD_TYPE_V21_GENERIC);
-        sVCardTypeMap.put(VCARD_TYPE_V30_GENERIC_STR, VCARD_TYPE_V30_GENERIC);
-        sVCardTypeMap.put(VCARD_TYPE_V21_EUROPE_STR, VCARD_TYPE_V21_EUROPE);
-        sVCardTypeMap.put(VCARD_TYPE_V30_EUROPE_STR, VCARD_TYPE_V30_EUROPE);
-        sVCardTypeMap.put(VCARD_TYPE_V21_JAPANESE_STR, VCARD_TYPE_V21_JAPANESE);
-        sVCardTypeMap.put(VCARD_TYPE_V30_JAPANESE_STR, VCARD_TYPE_V30_JAPANESE);
-        sVCardTypeMap.put(VCARD_TYPE_V21_JAPANESE_MOBILE_STR, VCARD_TYPE_V21_JAPANESE_MOBILE);
-        sVCardTypeMap.put(VCARD_TYPE_DOCOMO_STR, VCARD_TYPE_DOCOMO);
-
-        sJapaneseMobileTypeSet = new HashSet<Integer>();
-        sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE);
-        sJapaneseMobileTypeSet.add(VCARD_TYPE_V30_JAPANESE);
-        sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE_MOBILE);
-        sJapaneseMobileTypeSet.add(VCARD_TYPE_DOCOMO);
-    }
-
-    public static int getVCardTypeFromString(final String vcardTypeString) {
-        final String loweredKey = vcardTypeString.toLowerCase();
-        if (sVCardTypeMap.containsKey(loweredKey)) {
-            return sVCardTypeMap.get(loweredKey);
-        } else if ("default".equalsIgnoreCase(vcardTypeString)) {
-            return VCARD_TYPE_DEFAULT;
-        } else {
-            Log.e(LOG_TAG, "Unknown vCard type String: \"" + vcardTypeString + "\"");
-            return VCARD_TYPE_DEFAULT;
-        }
-    }
-
-    public static boolean isVersion21(final int vcardType) {
-        return (vcardType & VERSION_MASK) == VERSION_21;
-    }
-
-    public static boolean isVersion30(final int vcardType) {
-        return (vcardType & VERSION_MASK) == VERSION_30;
-    }
-
-    public static boolean isVersion40(final int vcardType) {
-        return (vcardType & VERSION_MASK) == VERSION_40;
-    }
-
-    public static boolean shouldUseQuotedPrintable(final int vcardType) {
-        return !isVersion30(vcardType);
-    }
-
-    public static int getNameOrderType(final int vcardType) {
-        return vcardType & NAME_ORDER_MASK;
-    }
-
-    public static boolean usesAndroidSpecificProperty(final int vcardType) {
-        return ((vcardType & FLAG_USE_ANDROID_PROPERTY) != 0);
-    }
-
-    public static boolean usesDefactProperty(final int vcardType) {
-        return ((vcardType & FLAG_USE_DEFACT_PROPERTY) != 0);
-    }
-
-    public static boolean showPerformanceLog() {
-        return (VCardConfig.LOG_LEVEL & VCardConfig.LOG_LEVEL_PERFORMANCE_MEASUREMENT) != 0;
-    }
-
-    public static boolean shouldRefrainQPToNameProperties(final int vcardType) {
-       return (!shouldUseQuotedPrintable(vcardType) ||
-               ((vcardType & FLAG_REFRAIN_QP_TO_NAME_PROPERTIES) != 0));
-    }
-
-    public static boolean appendTypeParamName(final int vcardType) {
-        return (isVersion30(vcardType) || ((vcardType & FLAG_APPEND_TYPE_PARAM) != 0));
-    }
-
-    /**
-     * @return true if the device is Japanese and some Japanese convension is
-     * applied to creating "formatted" something like FORMATTED_ADDRESS.
-     */
-    public static boolean isJapaneseDevice(final int vcardType) {
-        // TODO: Some mask will be required so that this method wrongly interpret
-        //        Japanese"-like" vCard type.
-        //        e.g. VCARD_TYPE_V21_JAPANESE_SJIS | FLAG_APPEND_TYPE_PARAMS
-        return sJapaneseMobileTypeSet.contains(vcardType);
-    }
-
-    /* package */ static boolean refrainPhoneNumberFormatting(final int vcardType) {
-        return ((vcardType & FLAG_REFRAIN_PHONE_NUMBER_FORMATTING) != 0);
-    }
-
-    public static boolean needsToConvertPhoneticString(final int vcardType) {
-        return ((vcardType & FLAG_CONVERT_PHONETIC_NAME_STRINGS) != 0);
-    }
-
-    public static boolean onlyOneNoteFieldIsAvailable(final int vcardType) {
-        return vcardType == VCARD_TYPE_DOCOMO;
-    }
-
-    public static boolean isDoCoMo(final int vcardType) {
-        return ((vcardType & FLAG_DOCOMO) != 0);
-    }
-
-    private VCardConfig() {
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/vcard/VCardConstants.java b/src/com/android/vcard/VCardConstants.java
deleted file mode 100644
index 1c4e42b..0000000
--- a/src/com/android/vcard/VCardConstants.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-/**
- * Constants used in both exporter and importer code.
- */
-public class VCardConstants {
-    public static final String VERSION_V21 = "2.1";
-    public static final String VERSION_V30 = "3.0";
-    public static final String VERSION_V40 = "4.0";
-
-    // The property names valid both in vCard 2.1 and 3.0.
-    public static final String PROPERTY_BEGIN = "BEGIN";
-    public static final String PROPERTY_VERSION = "VERSION";
-    public static final String PROPERTY_N = "N";
-    public static final String PROPERTY_FN = "FN";
-    public static final String PROPERTY_ADR = "ADR";
-    public static final String PROPERTY_EMAIL = "EMAIL";
-    public static final String PROPERTY_NOTE = "NOTE";
-    public static final String PROPERTY_ORG = "ORG";
-    public static final String PROPERTY_SOUND = "SOUND";  // Not fully supported.
-    public static final String PROPERTY_TEL = "TEL";
-    public static final String PROPERTY_TITLE = "TITLE";
-    public static final String PROPERTY_ROLE = "ROLE";
-    public static final String PROPERTY_PHOTO = "PHOTO";
-    public static final String PROPERTY_LOGO = "LOGO";
-    public static final String PROPERTY_URL = "URL";
-    public static final String PROPERTY_BDAY = "BDAY";  // Birthday (3.0, 4.0)
-    public static final String PROPERTY_BIRTH = "BIRTH";  // Place of birth (4.0)
-    public static final String PROPERTY_ANNIVERSARY = "ANNIVERSARY";  // Date of marriage (4.0)
-    public static final String PROPERTY_NAME = "NAME";  // (3.0, 4,0)
-    public static final String PROPERTY_NICKNAME = "NICKNAME";  // (3.0, 4.0)
-    public static final String PROPERTY_SORT_STRING = "SORT-STRING";  // (3.0, 4.0)
-    public static final String PROPERTY_IMPP = "IMPP";  // RFC 4770 (vCard 3.0) and vCard 4.0
-    public static final String PROPERTY_END = "END";
-
-    // defact SIP property which had been used till RFC 4770.
-    public static final String PROPERTY_X_SIP = "X-SIP";
-
-    // Valid property names not supported (not appropriately handled) by our importer.
-    // TODO: Should be removed from the view of memory efficiency?
-    public static final String PROPERTY_REV = "REV";
-    public static final String PROPERTY_AGENT = "AGENT";  // (3.0)
-    public static final String PROPERTY_DDAY = "DDAY";  // Date of death (4.0)
-    public static final String PROPERTY_DEATH = "DEATH";  // Place of death (4.0)
-
-    // Available in vCard 3.0. Shoud not use when composing vCard 2.1 file.
-    
-    // De-fact property values expressing phonetic names.
-    public static final String PROPERTY_X_PHONETIC_FIRST_NAME = "X-PHONETIC-FIRST-NAME";
-    public static final String PROPERTY_X_PHONETIC_MIDDLE_NAME = "X-PHONETIC-MIDDLE-NAME";
-    public static final String PROPERTY_X_PHONETIC_LAST_NAME = "X-PHONETIC-LAST-NAME";
-
-    // Properties both ContactsStruct and de-fact vCard extensions
-    // Shown in http://en.wikipedia.org/wiki/VCard support are defined here.
-    public static final String PROPERTY_X_AIM = "X-AIM";
-    public static final String PROPERTY_X_MSN = "X-MSN";
-    public static final String PROPERTY_X_YAHOO = "X-YAHOO";
-    public static final String PROPERTY_X_ICQ = "X-ICQ";
-    public static final String PROPERTY_X_JABBER = "X-JABBER";
-    public static final String PROPERTY_X_GOOGLE_TALK = "X-GOOGLE-TALK";
-    public static final String PROPERTY_X_SKYPE_USERNAME = "X-SKYPE-USERNAME";
-    // Properties only ContactsStruct has. We alse use this.
-    public static final String PROPERTY_X_QQ = "X-QQ";
-    public static final String PROPERTY_X_NETMEETING = "X-NETMEETING";
-
-    // Phone number for Skype, available as usual phone.
-    public static final String PROPERTY_X_SKYPE_PSTNNUMBER = "X-SKYPE-PSTNNUMBER";
-
-    // Property for Android-specific fields.
-    public static final String PROPERTY_X_ANDROID_CUSTOM = "X-ANDROID-CUSTOM";
-
-    // Properties for DoCoMo vCard.
-    public static final String PROPERTY_X_CLASS = "X-CLASS";
-    public static final String PROPERTY_X_REDUCTION = "X-REDUCTION";
-    public static final String PROPERTY_X_NO = "X-NO";
-    public static final String PROPERTY_X_DCM_HMN_MODE = "X-DCM-HMN-MODE";
-
-    public static final String PARAM_TYPE = "TYPE";
-
-    public static final String PARAM_TYPE_HOME = "HOME";
-    public static final String PARAM_TYPE_WORK = "WORK";
-    public static final String PARAM_TYPE_FAX = "FAX";
-    public static final String PARAM_TYPE_CELL = "CELL";
-    public static final String PARAM_TYPE_VOICE = "VOICE";
-    public static final String PARAM_TYPE_INTERNET = "INTERNET";
-
-    public static final String PARAM_CHARSET = "CHARSET";
-    public static final String PARAM_ENCODING = "ENCODING";
-
-    // Abbreviation of "prefered" according to vCard 2.1 specification.
-    // We interpret this value as "primary" property during import/export.
-    //
-    // Note: Both vCard specs does not mention anything about the requirement for this parameter,
-    //       but there may be some vCard importer which will get confused with more than
-    //       one "PREF"s in one property name, while Android accepts them.
-    public static final String PARAM_TYPE_PREF = "PREF";
-
-    // Phone type parameters valid in vCard and known to ContactsContract, but not so common.
-    public static final String PARAM_TYPE_CAR = "CAR";
-    public static final String PARAM_TYPE_ISDN = "ISDN";
-    public static final String PARAM_TYPE_PAGER = "PAGER";
-    public static final String PARAM_TYPE_TLX = "TLX";  // Telex
-
-    // Phone types existing in vCard 2.1 but not known to ContactsContract.
-    public static final String PARAM_TYPE_MODEM = "MODEM";
-    public static final String PARAM_TYPE_MSG = "MSG";
-    public static final String PARAM_TYPE_BBS = "BBS";
-    public static final String PARAM_TYPE_VIDEO = "VIDEO";
-
-    public static final String PARAM_ENCODING_7BIT = "7BIT";
-    public static final String PARAM_ENCODING_8BIT = "8BIT";
-    public static final String PARAM_ENCODING_QP = "QUOTED-PRINTABLE";
-    public static final String PARAM_ENCODING_BASE64 = "BASE64";  // Available in vCard 2.1
-    public static final String PARAM_ENCODING_B = "B";  // Available in vCard 3.0
-
-    // TYPE parameters for Phones, which are not formally valid in vCard (at least 2.1).
-    // These types are basically encoded to "X-" parameters when composing vCard.
-    // Parser passes these when "X-" is added to the parameter or not.
-    public static final String PARAM_PHONE_EXTRA_TYPE_CALLBACK = "CALLBACK";
-    public static final String PARAM_PHONE_EXTRA_TYPE_RADIO = "RADIO";
-    public static final String PARAM_PHONE_EXTRA_TYPE_TTY_TDD = "TTY-TDD";
-    public static final String PARAM_PHONE_EXTRA_TYPE_ASSISTANT = "ASSISTANT";
-    // vCard composer translates this type to "WORK" + "PREF". Just for parsing.
-    public static final String PARAM_PHONE_EXTRA_TYPE_COMPANY_MAIN = "COMPANY-MAIN";
-    // vCard composer translates this type to "VOICE" Just for parsing.
-    public static final String PARAM_PHONE_EXTRA_TYPE_OTHER = "OTHER";
-
-    // TYPE parameters for postal addresses.
-    public static final String PARAM_ADR_TYPE_PARCEL = "PARCEL";
-    public static final String PARAM_ADR_TYPE_DOM = "DOM";
-    public static final String PARAM_ADR_TYPE_INTL = "INTL";
-
-    public static final String PARAM_LANGUAGE = "LANGUAGE";
-
-    // SORT-AS parameter introduced in vCard 4.0 (as of rev.13)
-    public static final String PARAM_SORT_AS = "SORT-AS";
-
-    // TYPE parameters not officially valid but used in some vCard exporter.
-    // Do not use in composer side.
-    public static final String PARAM_EXTRA_TYPE_COMPANY = "COMPANY";
-
-    public interface ImportOnly {
-        public static final String PROPERTY_X_NICKNAME = "X-NICKNAME";
-        // Some device emits this "X-" parameter for expressing Google Talk,
-        // which is specifically invalid but should be always properly accepted, and emitted
-        // in some special case (for that device/application).
-        public static final String PROPERTY_X_GOOGLE_TALK_WITH_SPACE = "X-GOOGLE TALK";
-    }
-
-    //// Mainly for package constants.
-
-    // DoCoMo specific type parameter. Used with "SOUND" property, which is alternate of
-    // SORT-STRING invCard 3.0.
-    /* package */ static final String PARAM_TYPE_X_IRMC_N = "X-IRMC-N";
-
-    // Used in unit test.
-    public static final int MAX_DATA_COLUMN = 15;
-
-    /* package */ static final int MAX_CHARACTER_NUMS_QP = 76;
-    static final int MAX_CHARACTER_NUMS_BASE64_V30 = 75;
-
-    private VCardConstants() {
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/vcard/VCardEntry.java b/src/com/android/vcard/VCardEntry.java
deleted file mode 100644
index 3422322..0000000
--- a/src/com/android/vcard/VCardEntry.java
+++ /dev/null
@@ -1,1561 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import android.accounts.Account;
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderResult;
-import android.content.ContentResolver;
-import android.content.OperationApplicationException;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Event;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Nickname;
-import android.provider.ContactsContract.CommonDataKinds.Note;
-import android.provider.ContactsContract.CommonDataKinds.Organization;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.provider.ContactsContract.CommonDataKinds.Website;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.RawContacts;
-import android.telephony.PhoneNumberUtils;
-import android.text.TextUtils;
-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.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * This class bridges between data structure of Contact app and VCard data.
- */
-public class VCardEntry {
-    private static final String LOG_TAG = "VCardEntry";
-
-    private final static int DEFAULT_ORGANIZATION_TYPE = Organization.TYPE_WORK;
-
-    private static final Map<String, Integer> sImMap = new HashMap<String, Integer>();
-
-    static {
-        sImMap.put(VCardConstants.PROPERTY_X_AIM, Im.PROTOCOL_AIM);
-        sImMap.put(VCardConstants.PROPERTY_X_MSN, Im.PROTOCOL_MSN);
-        sImMap.put(VCardConstants.PROPERTY_X_YAHOO, Im.PROTOCOL_YAHOO);
-        sImMap.put(VCardConstants.PROPERTY_X_ICQ, Im.PROTOCOL_ICQ);
-        sImMap.put(VCardConstants.PROPERTY_X_JABBER, Im.PROTOCOL_JABBER);
-        sImMap.put(VCardConstants.PROPERTY_X_SKYPE_USERNAME, Im.PROTOCOL_SKYPE);
-        sImMap.put(VCardConstants.PROPERTY_X_GOOGLE_TALK, Im.PROTOCOL_GOOGLE_TALK);
-        sImMap.put(VCardConstants.ImportOnly.PROPERTY_X_GOOGLE_TALK_WITH_SPACE,
-                Im.PROTOCOL_GOOGLE_TALK);
-    }
-
-    public static class PhoneData {
-        public final int type;
-        public final String data;
-        public final String label;
-        // 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;
-            this.data = data;
-            this.label = label;
-            this.isPrimary = isPrimary;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof PhoneData)) {
-                return false;
-            }
-            PhoneData phoneData = (PhoneData)obj;
-            return (type == phoneData.type && data.equals(phoneData.data) &&
-                    label.equals(phoneData.label) && isPrimary == phoneData.isPrimary);
-        }
-
-        @Override
-        public String toString() {
-            return String.format("type: %d, data: %s, label: %s, isPrimary: %s",
-                    type, data, label, isPrimary);
-        }
-    }
-
-    public static class EmailData {
-        public final int type;
-        public final String data;
-        // Used only when TYPE is TYPE_CUSTOM.
-        public final String label;
-        public boolean isPrimary;
-        public EmailData(int type, String data, String label, boolean isPrimary) {
-            this.type = type;
-            this.data = data;
-            this.label = label;
-            this.isPrimary = isPrimary;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof EmailData)) {
-                return false;
-            }
-            EmailData emailData = (EmailData)obj;
-            return (type == emailData.type && data.equals(emailData.data) &&
-                    label.equals(emailData.label) && isPrimary == emailData.isPrimary);
-        }
-
-        @Override
-        public String toString() {
-            return String.format("type: %d, data: %s, label: %s, isPrimary: %s",
-                    type, data, label, isPrimary);
-        }
-    }
-
-    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;
-        public final String extendedAddress;
-        public final String street;
-        public final String localty;
-        public final String region;
-        public final String postalCode;
-        public final String country;
-        public final int type;
-        public final String label;
-        public 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];
-
-            int size = propValueList.size();
-            if (size > ADDR_MAX_DATA_SIZE) {
-                size = ADDR_MAX_DATA_SIZE;
-            }
-
-            // 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.
-            int i = 0;
-            for (String addressElement : propValueList) {
-                dataArray[i] = addressElement;
-                if (++i >= size) {
-                    break;
-                }
-            }
-            while (i < ADDR_MAX_DATA_SIZE) {
-                dataArray[i++] = null;
-            }
-
-            this.pobox = dataArray[0];
-            this.extendedAddress = dataArray[1];
-            this.street = dataArray[2];
-            this.localty = dataArray[3];
-            this.region = dataArray[4];
-            this.postalCode = dataArray[5];
-            this.country = dataArray[6];
-            this.label = label;
-            this.isPrimary = isPrimary;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof PostalData)) {
-                return false;
-            }
-            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(final int vcardType) {
-            StringBuilder builder = new StringBuilder();
-            boolean empty = true;
-            if (VCardConfig.isJapaneseDevice(vcardType)) {
-                // In Japan, the order is reversed.
-                for (int i = ADDR_MAX_DATA_SIZE - 1; i >= 0; i--) {
-                    String addressPart = dataArray[i];
-                    if (!TextUtils.isEmpty(addressPart)) {
-                        if (!empty) {
-                            builder.append(' ');
-                        } else {
-                            empty = false;
-                        }
-                        builder.append(addressPart);
-                    }
-                }
-            } else {
-                for (int i = 0; i < ADDR_MAX_DATA_SIZE; i++) {
-                    String addressPart = dataArray[i];
-                    if (!TextUtils.isEmpty(addressPart)) {
-                        if (!empty) {
-                            builder.append(' ');
-                        } else {
-                            empty = false;
-                        }
-                        builder.append(addressPart);
-                    }
-                }
-            }
-
-            return builder.toString().trim();
-        }
-
-        @Override
-        public String toString() {
-            return String.format("type: %d, label: %s, isPrimary: %s",
-                    type, label, isPrimary);
-        }
-    }
-
-    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", and we have to cope with each field in
-        // different timing.
-        public String companyName;
-        public String departmentName;
-        public String titleName;
-        public final String phoneticName;  // We won't have this in "TITLE" property.
-        public boolean isPrimary;
-
-        public OrganizationData(int type,
-                final String companyName,
-                final String departmentName,
-                final String titleName,
-                final String phoneticName,
-                final boolean isPrimary) {
-            this.type = type;
-            this.companyName = companyName;
-            this.departmentName = departmentName;
-            this.titleName = titleName;
-            this.phoneticName = phoneticName;
-            this.isPrimary = isPrimary;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof OrganizationData)) {
-                return false;
-            }
-            OrganizationData organization = (OrganizationData)obj;
-            return (type == organization.type &&
-                    TextUtils.equals(companyName, organization.companyName) &&
-                    TextUtils.equals(departmentName, organization.departmentName) &&
-                    TextUtils.equals(titleName, organization.titleName) &&
-                    isPrimary == organization.isPrimary);
-        }
-
-        public String getFormattedString() {
-            final StringBuilder builder = new StringBuilder();
-            if (!TextUtils.isEmpty(companyName)) {
-                builder.append(companyName);
-            }
-
-            if (!TextUtils.isEmpty(departmentName)) {
-                if (builder.length() > 0) {
-                    builder.append(", ");
-                }
-                builder.append(departmentName);
-            }
-
-            if (!TextUtils.isEmpty(titleName)) {
-                if (builder.length() > 0) {
-                    builder.append(", ");
-                }
-                builder.append(titleName);
-            }
-
-            return builder.toString();
-        }
-
-        @Override
-        public String toString() {
-            return String.format(
-                    "type: %d, company: %s, department: %s, title: %s, isPrimary: %s",
-                    type, companyName, departmentName, titleName, isPrimary);
-        }
-    }
-
-    public static class ImData {
-        public final int protocol;
-        public final String customProtocol;
-        public final int type;
-        public final String data;
-        public final 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)) {
-                return false;
-            }
-            ImData imData = (ImData)obj;
-            return (type == imData.type && protocol == imData.protocol
-                    && (customProtocol != null ? customProtocol.equals(imData.customProtocol) :
-                        (imData.customProtocol == null))
-                    && (data != null ? data.equals(imData.data) : (imData.data == null))
-                    && isPrimary == imData.isPrimary);
-        }
-
-        @Override
-        public String toString() {
-            return String.format(
-                    "type: %d, protocol: %d, custom_protcol: %s, data: %s, isPrimary: %s",
-                    type, protocol, customProtocol, data, isPrimary);
-        }
-    }
-
-    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.
-        public final byte[] photoBytes;
-        public final boolean isPrimary;
-
-        public PhotoData(int type, String formatName, byte[] photoBytes, boolean isPrimary) {
-            this.type = type;
-            this.formatName = formatName;
-            this.photoBytes = photoBytes;
-            this.isPrimary = isPrimary;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof PhotoData)) {
-                return false;
-            }
-            PhotoData photoData = (PhotoData)obj;
-            return (type == photoData.type &&
-                    (formatName == null ? (photoData.formatName == null) :
-                            formatName.equals(photoData.formatName)) &&
-                    (Arrays.equals(photoBytes, photoData.photoBytes)) &&
-                    (isPrimary == photoData.isPrimary));
-        }
-
-        @Override
-        public String toString() {
-            return String.format("type: %d, format: %s: size: %d, isPrimary: %s",
-                    type, formatName, photoBytes.length, isPrimary);
-        }
-    }
-
-    /* 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;
-        }
-
-        public void addParameter(final String paramName, final String paramValue) {
-            Collection<String> values;
-            if (!mParameterMap.containsKey(paramName)) {
-                if (paramName.equals("TYPE")) {
-                    values = new HashSet<String>();
-                } else {
-                    values = new ArrayList<String>();
-                }
-                mParameterMap.put(paramName, values);
-            } else {
-                values = mParameterMap.get(paramName);
-            }
-            values.add(paramValue);
-        }
-
-        public void addToPropertyValueList(final String propertyValue) {
-            mPropertyValueList.add(propertyValue);
-        }
-
-        public void setPropertyBytes(final byte[] propertyBytes) {
-            mPropertyBytes = propertyBytes;
-        }
-
-        public final Collection<String> getParameters(String type) {
-            return mParameterMap.get(type);
-        }
-
-        public final List<String> getPropertyValueList() {
-            return mPropertyValueList;
-        }
-
-        public void clear() {
-            mPropertyName = null;
-            mParameterMap.clear();
-            mPropertyValueList.clear();
-            mPropertyBytes = null;
-        }
-    }
-
-    // TODO(dmiyakawa): vCard 4.0 logically has multiple formatted names and we need to
-    // select the most preferable one using PREF parameter.
-    //
-    // e.g. (based on rev.13)
-    // FN;PREF=1:John M. Doe
-    // FN;PREF=2:John Doe
-    // FN;PREF=3;John
-
-    private String mFamilyName;
-    private String mGivenName;
-    private String mMiddleName;
-    private String mPrefix;
-    private String mSuffix;
-
-    // Used only when no family nor given name is found.
-    private String mFormattedName;
-
-    private String mPhoneticFamilyName;
-    private String mPhoneticGivenName;
-    private String mPhoneticMiddleName;
-
-    private String mPhoneticFullName;
-
-    private List<String> mNickNameList;
-
-    private String mDisplayName;
-
-    private String mBirthday;
-    private String mAnniversary;
-
-    private List<String> mNoteList;
-    private List<PhoneData> mPhoneList;
-    private List<EmailData> mEmailList;
-    private List<PostalData> mPostalList;
-    private List<OrganizationData> mOrganizationList;
-    private List<ImData> mImList;
-    private List<PhotoData> mPhotoList;
-    private List<String> mWebsiteList;
-    private Set<String> mSipSet;
-    private List<List<String>> mAndroidCustomPropertyList;
-
-    private final int mVCardType;
-    private final Account mAccount;
-
-    public VCardEntry() {
-        this(VCardConfig.VCARD_TYPE_V21_GENERIC);
-    }
-
-    public VCardEntry(int vcardType) {
-        this(vcardType, null);
-    }
-
-    public VCardEntry(int vcardType, Account account) {
-        mVCardType = vcardType;
-        mAccount = account;
-    }
-
-    private void addPhone(int type, String data, String label, boolean isPrimary) {
-        if (mPhoneList == null) {
-            mPhoneList = new ArrayList<PhoneData>();
-        }
-        final StringBuilder builder = new StringBuilder();
-        final String trimed = data.trim();
-        final String formattedNumber;
-        if (type == Phone.TYPE_PAGER || VCardConfig.refrainPhoneNumberFormatting(mVCardType)) {
-            formattedNumber = trimed;
-        } else {
-            final int length = trimed.length();
-            for (int i = 0; i < length; i++) {
-                char ch = trimed.charAt(i);
-                if (('0' <= ch && ch <= '9') || (i == 0 && ch == '+')) {
-                    builder.append(ch);
-                }
-            }
-
-            final int formattingType = VCardUtils.getPhoneNumberFormat(mVCardType);
-            formattedNumber = PhoneNumberUtils.formatNumber(builder.toString()); //, formattingType);
-        }
-        PhoneData phoneData = new PhoneData(type, formattedNumber, label, isPrimary);
-        mPhoneList.add(phoneData);
-    }
-
-    private void addNickName(final String nickName) {
-        if (mNickNameList == null) {
-            mNickNameList = new ArrayList<String>();
-        }
-        mNickNameList.add(nickName);
-    }
-
-    private void addEmail(int type, String data, String label, boolean isPrimary){
-        if (mEmailList == null) {
-            mEmailList = new ArrayList<EmailData>();
-        }
-        mEmailList.add(new EmailData(type, data, label, isPrimary));
-    }
-
-    private void addPostal(int type, List<String> propValueList, String label, boolean isPrimary){
-        if (mPostalList == null) {
-            mPostalList = new ArrayList<PostalData>(0);
-        }
-        mPostalList.add(new PostalData(type, propValueList, label, isPrimary));
-    }
-
-    /**
-     * Should be called via {@link #handleOrgValue(int, List, Map, boolean) or
-     * {@link #handleTitleValue(String)}.
-     */
-    private void addNewOrganization(int type, final String companyName,
-            final String departmentName,
-            final String titleName,
-            final String phoneticName,
-            final boolean isPrimary) {
-        if (mOrganizationList == null) {
-            mOrganizationList = new ArrayList<OrganizationData>();
-        }
-        mOrganizationList.add(new OrganizationData(type, companyName,
-                departmentName, titleName, phoneticName, isPrimary));
-    }
-
-    private static final List<String> sEmptyList =
-            Collections.unmodifiableList(new ArrayList<String>(0));
-
-    private String buildSinglePhoneticNameFromSortAsParam(Map<String, Collection<String>> paramMap) {
-        final Collection<String> sortAsCollection = paramMap.get(VCardConstants.PARAM_SORT_AS);
-        if (sortAsCollection != null && sortAsCollection.size() != 0) {
-            if (sortAsCollection.size() > 1) {
-                Log.w(LOG_TAG, "Incorrect multiple SORT_AS parameters detected: " +
-                        Arrays.toString(sortAsCollection.toArray()));
-            }
-            final List<String> sortNames =
-                    VCardUtils.constructListFromValue(sortAsCollection.iterator().next(),
-                            mVCardType);
-            final StringBuilder builder = new StringBuilder();
-            for (final String elem : sortNames) {
-                builder.append(elem);
-            }
-            return builder.toString();
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Set "ORG" related values to the appropriate data. If there's more than one
-     * {@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,
-            Map<String, Collection<String>> paramMap, boolean isPrimary) {
-        final String phoneticName = buildSinglePhoneticNameFromSortAsParam(paramMap);
-        if (orgList == null) {
-            orgList = sEmptyList;
-        }
-        final String companyName;
-        final String departmentName;
-        final int size = orgList.size();
-        switch (size) {
-            case 0: {
-                companyName = "";
-                departmentName = null;
-                break;
-            }
-            case 1: {
-                companyName = orgList.get(0);
-                departmentName = null;
-                break;
-            }
-            default: {  // More than 1.
-                companyName = orgList.get(0);
-                // We're not sure which is the correct string for department.
-                // In order to keep all the data, concatinate the rest of elements.
-                StringBuilder builder = new StringBuilder();
-                for (int i = 1; i < size; i++) {
-                    if (i > 1) {
-                        builder.append(' ');
-                    }
-                    builder.append(orgList.get(i));
-                }
-                departmentName = builder.toString();
-            }
-        }
-        if (mOrganizationList == null) {
-            // Create new first organization entry, with "null" title which may be
-            // added via handleTitleValue().
-            addNewOrganization(type, companyName, departmentName, null, phoneticName, isPrimary);
-            return;
-        }
-        for (OrganizationData organizationData : mOrganizationList) {
-            // Not use TextUtils.isEmpty() since ORG was set but the elements might be empty.
-            // e.g. "ORG;PREF:;" -> Both companyName and departmentName become empty but not null.
-            if (organizationData.companyName == null &&
-                    organizationData.departmentName == null) {
-                // Probably the "TITLE" property comes before the "ORG" property via
-                // handleTitleLine().
-                organizationData.companyName = companyName;
-                organizationData.departmentName = departmentName;
-                organizationData.isPrimary = isPrimary;
-                return;
-            }
-        }
-        // No OrganizatioData is available. Create another one, with "null" title, which may be
-        // added via handleTitleValue().
-        addNewOrganization(type, companyName, departmentName, null, phoneticName, isPrimary);
-    }
-
-    /**
-     * 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
-     * have valid title value (not including empty but only null). If there's no
-     * OrganizationData object, a new OrganizationData is created, whose company name is
-     * set to null.
-     */
-    private void handleTitleValue(final String title) {
-        if (mOrganizationList == null) {
-            // Create new first organization entry, with "null" other info, which may be
-            // added via handleOrgValue().
-            addNewOrganization(DEFAULT_ORGANIZATION_TYPE, null, null, title, null, false);
-            return;
-        }
-        for (OrganizationData organizationData : mOrganizationList) {
-            if (organizationData.titleName == null) {
-                organizationData.titleName = title;
-                return;
-            }
-        }
-        // No Organization is available. Create another one, with "null" other info, which may be
-        // added via handleOrgValue().
-        addNewOrganization(DEFAULT_ORGANIZATION_TYPE, null, null, title, null, false);
-    }
-
-    private void addIm(int protocol, String customProtocol, int type,
-            String propValue, boolean isPrimary) {
-        if (mImList == null) {
-            mImList = new ArrayList<ImData>();
-        }
-        mImList.add(new ImData(protocol, customProtocol, type, propValue, isPrimary));
-    }
-
-    private void addNote(final String note) {
-        if (mNoteList == null) {
-            mNoteList = new ArrayList<String>(1);
-        }
-        mNoteList.add(note);
-    }
-
-    private void addPhotoBytes(String formatName, byte[] photoBytes, boolean isPrimary) {
-        if (mPhotoList == null) {
-            mPhotoList = new ArrayList<PhotoData>(1);
-        }
-        final PhotoData photoData = new PhotoData(0, null, photoBytes, isPrimary);
-        mPhotoList.add(photoData);
-    }
-
-    /**
-     * Tries to extract paramMap, constructs SORT-AS parameter values, and store them in
-     * appropriate phonetic name variables.
-     *
-     * This method does not care the vCard version. Even when we have SORT-AS parameters in
-     * invalid versions (i.e. 2.1 and 3.0), we scilently accept them so that we won't drop
-     * meaningful information. If we had this parameter in the N field of vCard 3.0, and
-     * the contact data also have SORT-STRING, we will prefer SORT-STRING, since it is
-     * regitimate property to be understood.
-     */
-    private void tryHandleSortAsName(final Map<String, Collection<String>> paramMap) {
-        if (VCardConfig.isVersion30(mVCardType) &&
-                !(TextUtils.isEmpty(mPhoneticFamilyName) &&
-                        TextUtils.isEmpty(mPhoneticMiddleName) &&
-                        TextUtils.isEmpty(mPhoneticGivenName))) {
-            return;
-        }
-
-        final Collection<String> sortAsCollection = paramMap.get(VCardConstants.PARAM_SORT_AS);
-        if (sortAsCollection != null && sortAsCollection.size() != 0) {
-            if (sortAsCollection.size() > 1) {
-                Log.w(LOG_TAG, "Incorrect multiple SORT_AS parameters detected: " +
-                        Arrays.toString(sortAsCollection.toArray()));
-            }
-            final List<String> sortNames =
-                    VCardUtils.constructListFromValue(sortAsCollection.iterator().next(),
-                            mVCardType);
-            int size = sortNames.size();
-            if (size > 3) {
-                size = 3;
-            }
-            switch (size) {
-            case 3: mPhoneticMiddleName = sortNames.get(2); //$FALL-THROUGH$
-            case 2: mPhoneticGivenName = sortNames.get(1); //$FALL-THROUGH$
-            default: mPhoneticFamilyName = sortNames.get(0); break;
-            }
-        }
-    }
-
-    @SuppressWarnings("fallthrough")
-    private void handleNProperty(final List<String> paramValues,
-            Map<String, Collection<String>> paramMap) {
-        // in vCard 4.0, SORT-AS parameter is available.
-        tryHandleSortAsName(paramMap);
-
-        // Family, Given, Middle, Prefix, Suffix. (1 - 5)
-        int size;
-        if (paramValues == null || (size = paramValues.size()) < 1) {
-            return;
-        }
-        if (size > 5) {
-            size = 5;
-        }
-
-        switch (size) {
-        // Fall-through.
-        case 5: mSuffix = paramValues.get(4);
-        case 4: mPrefix = paramValues.get(3);
-        case 3: mMiddleName = paramValues.get(2);
-        case 2: mGivenName = paramValues.get(1);
-        default: mFamilyName = paramValues.get(0);
-        }
-    }
-
-    /**
-     * 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) {
-        if (!(TextUtils.isEmpty(mPhoneticFamilyName) &&
-                TextUtils.isEmpty(mPhoneticMiddleName) &&
-                TextUtils.isEmpty(mPhoneticGivenName))) {
-            // This means the other properties like "X-PHONETIC-FIRST-NAME" was already found.
-            // Ignore "SOUND;X-IRMC-N".
-            return;
-        }
-
-        int size;
-        if (elems == null || (size = elems.size()) < 1) {
-            return;
-        }
-
-        // Assume that the order is "Family, Given, Middle".
-        // This is not from specification but mere assumption. Some Japanese phones use this order.
-        if (size > 3) {
-            size = 3;
-        }
-
-        if (elems.get(0).length() > 0) {
-            boolean onlyFirstElemIsNonEmpty = true;
-            for (int i = 1; i < size; i++) {
-                if (elems.get(i).length() > 0) {
-                    onlyFirstElemIsNonEmpty = false;
-                    break;
-                }
-            }
-            if (onlyFirstElemIsNonEmpty) {
-                final String[] namesArray = elems.get(0).split(" ");
-                final int nameArrayLength = namesArray.length;
-                if (nameArrayLength == 3) {
-                    // Assume the string is "Family Middle Given".
-                    mPhoneticFamilyName = namesArray[0];
-                    mPhoneticMiddleName = namesArray[1];
-                    mPhoneticGivenName = namesArray[2];
-                } else if (nameArrayLength == 2) {
-                    // Assume the string is "Family Given" based on the Japanese mobile
-                    // phones' preference.
-                    mPhoneticFamilyName = namesArray[0];
-                    mPhoneticGivenName = namesArray[1];
-                } else {
-                    mPhoneticFullName = elems.get(0);
-                }
-                return;
-            }
-        }
-
-        switch (size) {
-            // fallthrough
-            case 3: mPhoneticMiddleName = elems.get(2);
-            case 2: mPhoneticGivenName = elems.get(1);
-            default: mPhoneticFamilyName = elems.get(0);
-        }
-    }
-
-    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;
-
-        if (propValueList.size() == 0) {
-            return;
-        }
-        final String propValue = listToString(propValueList).trim();
-
-        if (propName.equals(VCardConstants.PROPERTY_VERSION)) {
-            // vCard version. Ignore this.
-        } else if (propName.equals(VCardConstants.PROPERTY_FN)) {
-            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.
-            mFormattedName = propValue;
-        } else if (propName.equals(VCardConstants.PROPERTY_N)) {
-            handleNProperty(propValueList, paramMap);
-        } else if (propName.equals(VCardConstants.PROPERTY_SORT_STRING)) {
-            mPhoneticFullName = propValue;
-        } else if (propName.equals(VCardConstants.PROPERTY_NICKNAME) ||
-                propName.equals(VCardConstants.ImportOnly.PROPERTY_X_NICKNAME)) {
-            addNickName(propValue);
-        } else if (propName.equals(VCardConstants.PROPERTY_SOUND)) {
-            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
-            if (typeCollection != null
-                    && typeCollection.contains(VCardConstants.PARAM_TYPE_X_IRMC_N)) {
-                // As of 2009-10-08, Parser side does not split a property value into separated
-                // values using ';' (in other words, propValueList.size() == 1),
-                // which is correct behavior from the view of vCard 2.1.
-                // But we want it to be separated, so do the separation here.
-                final List<String> phoneticNameList =
-                        VCardUtils.constructListFromValue(propValue, mVCardType);
-                handlePhoneticNameFromSound(phoneticNameList);
-            } else {
-                // Ignore this field since Android cannot understand what it is.
-            }
-        } else if (propName.equals(VCardConstants.PROPERTY_ADR)) {
-            boolean valuesAreAllEmpty = true;
-            for (String value : propValueList) {
-                if (value.length() > 0) {
-                    valuesAreAllEmpty = false;
-                    break;
-                }
-            }
-            if (valuesAreAllEmpty) {
-                return;
-            }
-
-            int type = -1;
-            String label = "";
-            boolean isPrimary = false;
-            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
-            if (typeCollection != null) {
-                for (String typeString : typeCollection) {
-                    typeString = typeString.toUpperCase();
-                    if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) {
-                        isPrimary = true;
-                    } else if (typeString.equals(VCardConstants.PARAM_TYPE_HOME)) {
-                        type = StructuredPostal.TYPE_HOME;
-                        label = "";
-                    } else if (typeString.equals(VCardConstants.PARAM_TYPE_WORK) ||
-                            typeString.equalsIgnoreCase(VCardConstants.PARAM_EXTRA_TYPE_COMPANY)) {
-                        // "COMPANY" seems emitted by Windows Mobile, which is not
-                        // specifically supported by vCard 2.1. We assume this is same
-                        // as "WORK".
-                        type = StructuredPostal.TYPE_WORK;
-                        label = "";
-                    } else if (typeString.equals(VCardConstants.PARAM_ADR_TYPE_PARCEL) ||
-                            typeString.equals(VCardConstants.PARAM_ADR_TYPE_DOM) ||
-                            typeString.equals(VCardConstants.PARAM_ADR_TYPE_INTL)) {
-                        // We do not have any appropriate way to store this information.
-                    } else {
-                        if (typeString.startsWith("X-") && type < 0) {
-                            typeString = typeString.substring(2);
-                        }
-                        // vCard 3.0 allows iana-token. Also some vCard 2.1 exporters
-                        // emit non-standard types. We do not handle their values now.
-                        type = StructuredPostal.TYPE_CUSTOM;
-                        label = typeString;
-                    }
-                }
-            }
-            // We use "HOME" as default
-            if (type < 0) {
-                type = StructuredPostal.TYPE_HOME;
-            }
-
-            addPostal(type, propValueList, label, isPrimary);
-        } else if (propName.equals(VCardConstants.PROPERTY_EMAIL)) {
-            int type = -1;
-            String label = null;
-            boolean isPrimary = false;
-            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
-            if (typeCollection != null) {
-                for (String typeString : typeCollection) {
-                    typeString = typeString.toUpperCase();
-                    if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) {
-                        isPrimary = true;
-                    } else if (typeString.equals(VCardConstants.PARAM_TYPE_HOME)) {
-                        type = Email.TYPE_HOME;
-                    } else if (typeString.equals(VCardConstants.PARAM_TYPE_WORK)) {
-                        type = Email.TYPE_WORK;
-                    } else if (typeString.equals(VCardConstants.PARAM_TYPE_CELL)) {
-                        type = Email.TYPE_MOBILE;
-                    } else {
-                        if (typeString.startsWith("X-") && type < 0) {
-                            typeString = typeString.substring(2);
-                        }
-                        // vCard 3.0 allows iana-token.
-                        // We may have INTERNET (specified in vCard spec),
-                        // SCHOOL, etc.
-                        type = Email.TYPE_CUSTOM;
-                        label = typeString;
-                    }
-                }
-            }
-            if (type < 0) {
-                type = Email.TYPE_OTHER;
-            }
-            addEmail(type, propValue, label, isPrimary);
-        } else if (propName.equals(VCardConstants.PROPERTY_ORG)) {
-            // vCard specification does not specify other types.
-            final int type = Organization.TYPE_WORK;
-            boolean isPrimary = false;
-            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
-            if (typeCollection != null) {
-                for (String typeString : typeCollection) {
-                    if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) {
-                        isPrimary = true;
-                    }
-                }
-            }
-            handleOrgValue(type, propValueList, paramMap, isPrimary);
-        } else if (propName.equals(VCardConstants.PROPERTY_TITLE)) {
-            handleTitleValue(propValue);
-        } else if (propName.equals(VCardConstants.PROPERTY_ROLE)) {
-            // This conflicts with TITLE. Ignore for now...
-            // handleTitleValue(propValue);
-        } else if (propName.equals(VCardConstants.PROPERTY_PHOTO) ||
-                propName.equals(VCardConstants.PROPERTY_LOGO)) {
-            Collection<String> paramMapValue = paramMap.get("VALUE");
-            if (paramMapValue != null && paramMapValue.contains("URL")) {
-                // Currently we do not have appropriate example for testing this case.
-            } else {
-                final Collection<String> typeCollection = paramMap.get("TYPE");
-                String formatName = null;
-                boolean isPrimary = false;
-                if (typeCollection != null) {
-                    for (String typeValue : typeCollection) {
-                        if (VCardConstants.PARAM_TYPE_PREF.equals(typeValue)) {
-                            isPrimary = true;
-                        } else if (formatName == null){
-                            formatName = typeValue;
-                        }
-                    }
-                }
-                addPhotoBytes(formatName, propBytes, isPrimary);
-            }
-        } else if (propName.equals(VCardConstants.PROPERTY_TEL)) {
-            final String phoneNumber;
-            if (VCardConfig.isVersion40(mVCardType)) {
-                // Given propValue is in URI format, not in phone number format used until
-                // vCard 3.0.
-                if (propValue.startsWith("sip:") ) {
-                    if (propValue.length() > 4) {
-                        if (mSipSet == null) {
-                            mSipSet = new LinkedHashSet<String>();
-                        }
-                        mSipSet.add(propValue.substring(4));
-                    }
-                    return;
-                } else if (propValue.startsWith("tel:")) {
-                    phoneNumber = propValue.substring(4);
-                } else {
-                    // We don't know appropriate way to handle the other schemas. Also,
-                    // we may still have non-URI phone number. To keep given data as much as
-                    // we can, just save original value here.
-                    phoneNumber = propValue;
-                }
-            } else {
-                phoneNumber = propValue;
-            }
-
-            if (propValue.length() == 0) {
-                return;
-            }
-            final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
-            final Object typeObject =
-                    VCardUtils.getPhoneTypeFromStrings(typeCollection, phoneNumber);
-            final int type;
-            final String label;
-            if (typeObject instanceof Integer) {
-                type = (Integer)typeObject;
-                label = null;
-            } else {
-                type = Phone.TYPE_CUSTOM;
-                label = typeObject.toString();
-            }
-
-            final boolean isPrimary;
-            if (typeCollection != null &&
-                    typeCollection.contains(VCardConstants.PARAM_TYPE_PREF)) {
-                isPrimary = true;
-            } else {
-                isPrimary = false;
-            }
-            addPhone(type, phoneNumber, label, isPrimary);
-        } else if (propName.equals(VCardConstants.PROPERTY_X_SKYPE_PSTNNUMBER)) {
-            // The phone number available via Skype.
-            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
-            final int type = Phone.TYPE_OTHER;
-            final boolean isPrimary;
-            if (typeCollection != null && typeCollection.contains(VCardConstants.PARAM_TYPE_PREF)) {
-                isPrimary = true;
-            } else {
-                isPrimary = false;
-            }
-            addPhone(type, propValue, null, isPrimary);
-        } else if (sImMap.containsKey(propName)) {
-            final int protocol = sImMap.get(propName);
-            boolean isPrimary = false;
-            int type = -1;
-            final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
-            if (typeCollection != null) {
-                for (String typeString : typeCollection) {
-                    if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) {
-                        isPrimary = true;
-                    } else if (type < 0) {
-                        if (typeString.equalsIgnoreCase(VCardConstants.PARAM_TYPE_HOME)) {
-                            type = Im.TYPE_HOME;
-                        } else if (typeString.equalsIgnoreCase(VCardConstants.PARAM_TYPE_WORK)) {
-                            type = Im.TYPE_WORK;
-                        }
-                    }
-                }
-            }
-            if (type < 0) {
-                type = Im.TYPE_HOME;
-            }
-            addIm(protocol, null, type, propValue, isPrimary);
-        } else if (propName.equals(VCardConstants.PROPERTY_NOTE)) {
-            addNote(propValue);
-        } else if (propName.equals(VCardConstants.PROPERTY_URL)) {
-            if (mWebsiteList == null) {
-                mWebsiteList = new ArrayList<String>(1);
-            }
-            mWebsiteList.add(propValue);
-        } else if (propName.equals(VCardConstants.PROPERTY_BDAY)) {
-            mBirthday = propValue;
-        } else if (propName.equals(VCardConstants.PROPERTY_ANNIVERSARY)) {
-            mAnniversary = propValue;
-        } else if (propName.equals(VCardConstants.PROPERTY_X_PHONETIC_FIRST_NAME)) {
-            mPhoneticGivenName = propValue;
-        } else if (propName.equals(VCardConstants.PROPERTY_X_PHONETIC_MIDDLE_NAME)) {
-            mPhoneticMiddleName = propValue;
-        } else if (propName.equals(VCardConstants.PROPERTY_X_PHONETIC_LAST_NAME)) {
-            mPhoneticFamilyName = propValue;
-        } else if (propName.equals(VCardConstants.PROPERTY_IMPP)) {
-            // See also RFC 4770 (for vCard 3.0)
-            if (propValue.startsWith("sip:") && propValue.length() > 4) {
-                if (mSipSet == null) {
-                    mSipSet = new LinkedHashSet<String>();
-                }
-                mSipSet.add(propValue.substring(4));
-            }
-        } else if (propName.equals(VCardConstants.PROPERTY_X_SIP)) {
-            if (!TextUtils.isEmpty(propValue)) {
-                if (mSipSet == null) {
-                    mSipSet = new LinkedHashSet<String>();
-                }
-
-                if (propValue.startsWith("sip:")) {
-                    if (propValue.length() > 4) {
-                        mSipSet.add(propValue.substring(4));
-                    } else {
-                        // Empty sip value. Ignore.
-                    }
-                } else {
-                    mSipSet.add(propValue);
-                }
-            }
-        } else if (propName.equals(VCardConstants.PROPERTY_X_ANDROID_CUSTOM)) {
-            final List<String> customPropertyList =
-                VCardUtils.constructListFromValue(propValue, mVCardType);
-            handleAndroidCustomProperty(customPropertyList);
-        } else {
-        }
-        // Be careful when adding some logic here, as some blocks above may use "return".
-    }
-
-    private void handleAndroidCustomProperty(final List<String> customPropertyList) {
-        if (mAndroidCustomPropertyList == null) {
-            mAndroidCustomPropertyList = new ArrayList<List<String>>();
-        }
-        mAndroidCustomPropertyList.add(customPropertyList);
-    }
-
-    /**
-     * Construct the display name. The constructed data must not be null.
-     */
-    private void constructDisplayName() {
-        // FullName (created via "FN" or "NAME" field) is prefered.
-        if (!TextUtils.isEmpty(mFormattedName)) {
-            mDisplayName = mFormattedName;
-        } else if (!(TextUtils.isEmpty(mFamilyName) && TextUtils.isEmpty(mGivenName))) {
-            mDisplayName = VCardUtils.constructNameFromElements(mVCardType,
-                    mFamilyName, mMiddleName, mGivenName, mPrefix, mSuffix);
-        } else if (!(TextUtils.isEmpty(mPhoneticFamilyName) &&
-                TextUtils.isEmpty(mPhoneticGivenName))) {
-            mDisplayName = VCardUtils.constructNameFromElements(mVCardType,
-                    mPhoneticFamilyName, mPhoneticMiddleName, mPhoneticGivenName);
-        } else if (mEmailList != null && mEmailList.size() > 0) {
-            mDisplayName = mEmailList.get(0).data;
-        } else if (mPhoneList != null && mPhoneList.size() > 0) {
-            mDisplayName = mPhoneList.get(0).data;
-        } else if (mPostalList != null && mPostalList.size() > 0) {
-            mDisplayName = mPostalList.get(0).getFormattedAddress(mVCardType);
-        } else if (mOrganizationList != null && mOrganizationList.size() > 0) {
-            mDisplayName = mOrganizationList.get(0).getFormattedString();
-        }
-
-        if (mDisplayName == null) {
-            mDisplayName = "";
-        }
-    }
-
-    /**
-     * Consolidate several fielsds (like mName) using name candidates,
-     */
-    public void consolidateFields() {
-        constructDisplayName();
-
-        if (mPhoneticFullName != null) {
-            mPhoneticFullName = mPhoneticFullName.trim();
-        }
-    }
-
-    public Uri pushIntoContentResolver(ContentResolver resolver) {
-        ArrayList<ContentProviderOperation> operationList =
-            new ArrayList<ContentProviderOperation>();
-        // After applying the batch the first result's Uri is returned so it is important that
-        // the RawContact is the first operation that gets inserted into the list
-        ContentProviderOperation.Builder builder =
-            ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
-        String myGroupsId = null;
-        if (mAccount != null) {
-            builder.withValue(RawContacts.ACCOUNT_NAME, mAccount.name);
-            builder.withValue(RawContacts.ACCOUNT_TYPE, mAccount.type);
-        } else {
-            builder.withValue(RawContacts.ACCOUNT_NAME, null);
-            builder.withValue(RawContacts.ACCOUNT_TYPE, null);
-        }
-        operationList.add(builder.build());
-
-        if (!nameFieldsAreEmpty()) {
-            builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-            builder.withValueBackReference(StructuredName.RAW_CONTACT_ID, 0);
-            builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
-
-            builder.withValue(StructuredName.GIVEN_NAME, mGivenName);
-            builder.withValue(StructuredName.FAMILY_NAME, mFamilyName);
-            builder.withValue(StructuredName.MIDDLE_NAME, mMiddleName);
-            builder.withValue(StructuredName.PREFIX, mPrefix);
-            builder.withValue(StructuredName.SUFFIX, mSuffix);
-
-            if (!(TextUtils.isEmpty(mPhoneticGivenName)
-                    && TextUtils.isEmpty(mPhoneticFamilyName)
-                    && TextUtils.isEmpty(mPhoneticMiddleName))) {
-                builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, mPhoneticGivenName);
-                builder.withValue(StructuredName.PHONETIC_FAMILY_NAME, mPhoneticFamilyName);
-                builder.withValue(StructuredName.PHONETIC_MIDDLE_NAME, mPhoneticMiddleName);
-            } else if (!TextUtils.isEmpty(mPhoneticFullName)) {
-                builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, mPhoneticFullName);
-            }
-
-            builder.withValue(StructuredName.DISPLAY_NAME, getDisplayName());
-            operationList.add(builder.build());
-        }
-
-        if (mNickNameList != null && mNickNameList.size() > 0) {
-            for (String nickName : mNickNameList) {
-                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-                builder.withValueBackReference(Nickname.RAW_CONTACT_ID, 0);
-                builder.withValue(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE);
-                builder.withValue(Nickname.TYPE, Nickname.TYPE_DEFAULT);
-                builder.withValue(Nickname.NAME, nickName);
-                operationList.add(builder.build());
-            }
-        }
-
-        if (mPhoneList != null) {
-            for (PhoneData phoneData : mPhoneList) {
-                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-                builder.withValueBackReference(Phone.RAW_CONTACT_ID, 0);
-                builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-
-                builder.withValue(Phone.TYPE, phoneData.type);
-                if (phoneData.type == Phone.TYPE_CUSTOM) {
-                    builder.withValue(Phone.LABEL, phoneData.label);
-                }
-                builder.withValue(Phone.NUMBER, phoneData.data);
-                if (phoneData.isPrimary) {
-                    builder.withValue(Phone.IS_PRIMARY, 1);
-                }
-                operationList.add(builder.build());
-            }
-        }
-
-        if (mOrganizationList != null) {
-            for (OrganizationData organizationData : mOrganizationList) {
-                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-                builder.withValueBackReference(Organization.RAW_CONTACT_ID, 0);
-                builder.withValue(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
-                builder.withValue(Organization.TYPE, organizationData.type);
-                if (organizationData.companyName != null) {
-                    builder.withValue(Organization.COMPANY, organizationData.companyName);
-                }
-                if (organizationData.departmentName != null) {
-                    builder.withValue(Organization.DEPARTMENT, organizationData.departmentName);
-                }
-                if (organizationData.titleName != null) {
-                    builder.withValue(Organization.TITLE, organizationData.titleName);
-                }
-                if (organizationData.phoneticName != null) {
-                    builder.withValue(Organization.PHONETIC_NAME, organizationData.phoneticName);
-                }
-                if (organizationData.isPrimary) {
-                    builder.withValue(Organization.IS_PRIMARY, 1);
-                }
-                operationList.add(builder.build());
-            }
-        }
-
-        if (mEmailList != null) {
-            for (EmailData emailData : mEmailList) {
-                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-                builder.withValueBackReference(Email.RAW_CONTACT_ID, 0);
-                builder.withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
-
-                builder.withValue(Email.TYPE, emailData.type);
-                if (emailData.type == Email.TYPE_CUSTOM) {
-                    builder.withValue(Email.LABEL, emailData.label);
-                }
-                builder.withValue(Email.DATA, emailData.data);
-                if (emailData.isPrimary) {
-                    builder.withValue(Data.IS_PRIMARY, 1);
-                }
-                operationList.add(builder.build());
-            }
-        }
-
-        if (mPostalList != null) {
-            for (PostalData postalData : mPostalList) {
-                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-                builder.withValueBackReference(Event.RAW_CONTACT_ID, 0);
-                VCardUtils.insertStructuredPostalDataUsingContactsStruct(
-                        mVCardType, builder, postalData);
-                operationList.add(builder.build());
-            }
-        }
-
-        if (mImList != null) {
-            for (ImData imData : mImList) {
-                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-                builder.withValueBackReference(Im.RAW_CONTACT_ID, 0);
-                builder.withValue(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
-                builder.withValue(Im.TYPE, imData.type);
-                builder.withValue(Im.PROTOCOL, imData.protocol);
-                builder.withValue(Im.DATA, imData.data);
-                if (imData.protocol == Im.PROTOCOL_CUSTOM) {
-                    builder.withValue(Im.CUSTOM_PROTOCOL, imData.customProtocol);
-                }
-                if (imData.isPrimary) {
-                    builder.withValue(Data.IS_PRIMARY, 1);
-                }
-                operationList.add(builder.build());
-            }
-        }
-
-        if (mNoteList != null) {
-            for (String note : mNoteList) {
-                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-                builder.withValueBackReference(Note.RAW_CONTACT_ID, 0);
-                builder.withValue(Data.MIMETYPE, Note.CONTENT_ITEM_TYPE);
-                builder.withValue(Note.NOTE, note);
-                operationList.add(builder.build());
-            }
-        }
-
-        if (mPhotoList != null) {
-            for (PhotoData photoData : mPhotoList) {
-                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-                builder.withValueBackReference(Photo.RAW_CONTACT_ID, 0);
-                builder.withValue(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
-                builder.withValue(Photo.PHOTO, photoData.photoBytes);
-                if (photoData.isPrimary) {
-                    builder.withValue(Photo.IS_PRIMARY, 1);
-                }
-                operationList.add(builder.build());
-            }
-        }
-
-        if (mWebsiteList != null) {
-            for (String website : mWebsiteList) {
-                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-                builder.withValueBackReference(Website.RAW_CONTACT_ID, 0);
-                builder.withValue(Data.MIMETYPE, Website.CONTENT_ITEM_TYPE);
-                builder.withValue(Website.URL, website);
-                // There's no information about the type of URL in vCard.
-                // We use TYPE_HOMEPAGE for safety.
-                builder.withValue(Website.TYPE, Website.TYPE_HOMEPAGE);
-                operationList.add(builder.build());
-            }
-        }
-
-        if (!TextUtils.isEmpty(mBirthday)) {
-            builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-            builder.withValueBackReference(Event.RAW_CONTACT_ID, 0);
-            builder.withValue(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
-            builder.withValue(Event.START_DATE, mBirthday);
-            builder.withValue(Event.TYPE, Event.TYPE_BIRTHDAY);
-            operationList.add(builder.build());
-        }
-
-        if (!TextUtils.isEmpty(mAnniversary)) {
-            builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-            builder.withValueBackReference(Event.RAW_CONTACT_ID, 0);
-            builder.withValue(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
-            builder.withValue(Event.START_DATE, mAnniversary);
-            builder.withValue(Event.TYPE, Event.TYPE_ANNIVERSARY);
-            operationList.add(builder.build());
-        }
-
-        if (mSipSet != null && !mSipSet.isEmpty()) {
-            for (String sipAddress : mSipSet) {
-                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-                builder.withValueBackReference(Event.RAW_CONTACT_ID, 0);
-                builder.withValue(Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
-                builder.withValue(SipAddress.SIP_ADDRESS, sipAddress);
-                operationList.add(builder.build());
-            }
-        }
-
-        if (mAndroidCustomPropertyList != null) {
-            for (List<String> customPropertyList : mAndroidCustomPropertyList) {
-                int size = customPropertyList.size();
-                if (size < 2 || TextUtils.isEmpty(customPropertyList.get(0))) {
-                    continue;
-                } else if (size > VCardConstants.MAX_DATA_COLUMN + 1) {
-                    size = VCardConstants.MAX_DATA_COLUMN + 1;
-                    customPropertyList =
-                        customPropertyList.subList(0, VCardConstants.MAX_DATA_COLUMN + 2);
-                }
-
-                int i = 0;
-                for (final String customPropertyValue : customPropertyList) {
-                    if (i == 0) {
-                        final String mimeType = customPropertyValue;
-                        builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-                        builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, 0);
-                        builder.withValue(Data.MIMETYPE, mimeType);
-                    } else {  // 1 <= i && i <= MAX_DATA_COLUMNS
-                        if (!TextUtils.isEmpty(customPropertyValue)) {
-                            builder.withValue("data" + i, customPropertyValue);
-                        }
-                    }
-
-                    i++;
-                }
-                operationList.add(builder.build());
-            }
-        }
-
-        if (myGroupsId != null) {
-            builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
-            builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, 0);
-            builder.withValue(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE);
-            builder.withValue(GroupMembership.GROUP_SOURCE_ID, myGroupsId);
-            operationList.add(builder.build());
-        }
-
-        try {
-            ContentProviderResult[] results = resolver.applyBatch(
-                        ContactsContract.AUTHORITY, operationList);
-            // the first result is always the raw_contact. return it's uri so
-            // that it can be found later. do null checking for badly behaving
-            // ContentResolvers
-            return (results == null || results.length == 0 || results[0] == null)
-                ? null
-                : results[0].uri;
-        } catch (RemoteException e) {
-            Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage()));
-            return null;
-        } catch (OperationApplicationException e) {
-            Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage()));
-            return null;
-        }
-    }
-
-    public static VCardEntry buildFromResolver(ContentResolver resolver) {
-        return buildFromResolver(resolver, Contacts.CONTENT_URI);
-    }
-
-    public static VCardEntry buildFromResolver(ContentResolver resolver, Uri uri) {
-
-        return null;
-    }
-
-    private boolean nameFieldsAreEmpty() {
-        return (TextUtils.isEmpty(mFamilyName)
-                && TextUtils.isEmpty(mMiddleName)
-                && TextUtils.isEmpty(mGivenName)
-                && TextUtils.isEmpty(mPrefix)
-                && TextUtils.isEmpty(mSuffix)
-                && TextUtils.isEmpty(mFormattedName)
-                && TextUtils.isEmpty(mPhoneticFamilyName)
-                && TextUtils.isEmpty(mPhoneticMiddleName)
-                && TextUtils.isEmpty(mPhoneticGivenName)
-                && TextUtils.isEmpty(mPhoneticFullName));
-    }
-
-    public boolean isIgnorable() {
-        return getDisplayName().length() == 0;
-    }
-
-    private String listToString(List<String> list){
-        final int size = list.size();
-        if (size > 1) {
-            StringBuilder builder = new StringBuilder();
-            int i = 0;
-            for (String type : list) {
-                builder.append(type);
-                if (i < size - 1) {
-                    builder.append(";");
-                }
-            }
-            return builder.toString();
-        } else if (size == 1) {
-            return list.get(0);
-        } else {
-            return "";
-        }
-    }
-
-    // All getter methods should be used carefully, since they may change
-    // in the future as of 2009-10-05, on which I cannot be sure this structure
-    // is completely consolidated.
-    //
-    // Also note that these getter methods should be used only after
-    // all properties being pushed into this object. If not, incorrect
-    // value will "be stored in the local cache and" be returned to you.
-
-    public String getFamilyName() {
-        return mFamilyName;
-    }
-
-    public String getGivenName() {
-        return mGivenName;
-    }
-
-    public String getMiddleName() {
-        return mMiddleName;
-    }
-
-    public String getPrefix() {
-        return mPrefix;
-    }
-
-    public String getSuffix() {
-        return mSuffix;
-    }
-
-    public String getFullName() {
-        return mFormattedName;
-    }
-
-    public String getPhoneticFamilyName() {
-        return mPhoneticFamilyName;
-    }
-
-    public String getPhoneticGivenName() {
-        return mPhoneticGivenName;
-    }
-
-    public String getPhoneticMiddleName() {
-        return mPhoneticMiddleName;
-    }
-
-    public String getPhoneticFullName() {
-        return mPhoneticFullName;
-    }
-
-    public final List<String> getNickNameList() {
-        return mNickNameList;
-    }
-
-    public String getBirthday() {
-        return mBirthday;
-    }
-
-    public final List<String> getNotes() {
-        return mNoteList;
-    }
-
-    public final List<PhoneData> getPhoneList() {
-        return mPhoneList;
-    }
-
-    public final List<EmailData> getEmailList() {
-        return mEmailList;
-    }
-
-    public final List<PostalData> getPostalList() {
-        return mPostalList;
-    }
-
-    public final List<OrganizationData> getOrganizationList() {
-        return mOrganizationList;
-    }
-
-    public final List<ImData> getImList() {
-        return mImList;
-    }
-
-    public final List<PhotoData> getPhotoList() {
-        return mPhotoList;
-    }
-
-    public final List<String> getWebsiteList() {
-        return mWebsiteList;
-    }
-
-    public String getDisplayName() {
-        if (mDisplayName == null) {
-            constructDisplayName();
-        }
-        return mDisplayName;
-    }
-}
diff --git a/src/com/android/vcard/VCardEntryCommitter.java b/src/com/android/vcard/VCardEntryCommitter.java
deleted file mode 100644
index 7bd314e..0000000
--- a/src/com/android/vcard/VCardEntryCommitter.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.util.Log;
-
-import java.util.ArrayList;
-
-/**
- * <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 = "VCardEntryComitter";
-
-    private final ContentResolver mContentResolver;
-    private long mTimeToCommit;
-    private ArrayList<Uri> mCreatedUris = new ArrayList<Uri>();
-
-    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));
-        }
-    }
-
-    public void onEntryCreated(final VCardEntry vcardEntry) {
-        long start = System.currentTimeMillis();
-        mCreatedUris.add(vcardEntry.pushIntoContentResolver(mContentResolver));
-        mTimeToCommit += System.currentTimeMillis() - start;
-    }
-
-    /**
-     * Returns the list of created Uris. This list should not be modified by the caller as it is
-     * not a clone.
-     */
-   public ArrayList<Uri> getCreatedUris() {
-        return mCreatedUris;
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/vcard/VCardEntryConstructor.java b/src/com/android/vcard/VCardEntryConstructor.java
deleted file mode 100644
index 8acad7e..0000000
--- a/src/com/android/vcard/VCardEntryConstructor.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import android.accounts.Account;
-import android.text.TextUtils;
-import android.util.Base64;
-//import android.util.CharsetUtils;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * <p>
- * The {@link VCardInterpreter} implementation which enables {@link VCardEntryHandler} objects
- * to easily handle each vCard entry.
- * </p>
- * <p>
- * 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.
- * </p>
- * <p>
- * 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.
- * </p>
- */
-public class VCardEntryConstructor implements VCardInterpreter {
-    private static String LOG_TAG = "VCardEntryConstructor";
-
-    private VCardEntry.Property mCurrentProperty = new VCardEntry.Property();
-    private VCardEntry mCurrentVCardEntry;
-    private String mParamType;
-    
-    // The charset using which {@link VCardInterpreter} parses the text.
-    // Each String is first decoded into binary stream with this charset, and encoded back
-    // to "target charset", which may be explicitly specified by the vCard with "CHARSET"
-    // property or implicitly mentioned by its version (e.g. vCard 3.0 recommends UTF-8).
-    private final String mSourceCharset;
-
-    private final boolean mStrictLineBreaking;
-    private final int mVCardType;
-    private final Account mAccount;
-    
-    // For measuring performance.
-    private long mTimePushIntoContentResolver;
-
-    private final List<VCardEntryHandler> mEntryHandlers = new ArrayList<VCardEntryHandler>();
-
-    public VCardEntryConstructor() {
-        this(VCardConfig.VCARD_TYPE_V21_GENERIC, null);
-    }
-
-    public VCardEntryConstructor(final int vcardType) {
-        this(vcardType, null, null, false);
-    }
-
-    public VCardEntryConstructor(final int vcardType, final Account account) {
-        this(vcardType, account, null, false);
-    }
-
-    public VCardEntryConstructor(final int vcardType, final Account account,
-            final String inputCharset) {
-        this(vcardType, account, inputCharset, false);
-    }
-
-    /**
-     * @hide Just for testing.
-     */
-    public VCardEntryConstructor(final int vcardType, final Account account,
-            final String inputCharset, final boolean strictLineBreakParsing) {
-        if (inputCharset != null) {
-            mSourceCharset = inputCharset;
-        } else {
-            mSourceCharset = VCardConfig.DEFAULT_INTERMEDIATE_CHARSET;
-        }
-        mStrictLineBreaking = strictLineBreakParsing;
-        mVCardType = vcardType;
-        mAccount = account;
-    }
-
-    public void addEntryHandler(VCardEntryHandler entryHandler) {
-        mEntryHandlers.add(entryHandler);
-    }
-
-    @Override
-    public void start() {
-        for (VCardEntryHandler entryHandler : mEntryHandlers) {
-            entryHandler.onStart();
-        }
-    }
-
-    @Override
-    public void end() {
-        for (VCardEntryHandler entryHandler : mEntryHandlers) {
-            entryHandler.onEnd();
-        }
-    }
-
-    public void clear() {
-        mCurrentVCardEntry = null;
-        mCurrentProperty = new VCardEntry.Property();
-    }
-
-    @Override
-    public void startEntry() {
-        if (mCurrentVCardEntry != null) {
-            Log.e(LOG_TAG, "Nested VCard code is not supported now.");
-        }
-        mCurrentVCardEntry = new VCardEntry(mVCardType, mAccount);
-    }
-
-    @Override
-    public void endEntry() {
-        mCurrentVCardEntry.consolidateFields();
-        for (VCardEntryHandler entryHandler : mEntryHandlers) {
-            entryHandler.onEntryCreated(mCurrentVCardEntry);
-        }
-        mCurrentVCardEntry = null;
-    }
-
-    @Override
-    public void startProperty() {
-        mCurrentProperty.clear();
-    }
-
-    @Override
-    public void endProperty() {
-        mCurrentVCardEntry.addProperty(mCurrentProperty);
-    }
-    
-    @Override
-    public void propertyName(String name) {
-        mCurrentProperty.setPropertyName(name);
-    }
-
-    @Override
-    public void propertyGroup(String group) {
-    }
-
-    @Override
-    public void propertyParamType(String type) {
-        if (mParamType != null) {
-            Log.e(LOG_TAG, "propertyParamType() is called more than once " +
-                    "before propertyParamValue() is called");
-        }
-        mParamType = type;
-    }
-
-    @Override
-    public void propertyParamValue(String value) {
-        if (mParamType == null) {
-            // From vCard 2.1 specification. vCard 3.0 formally does not allow this case.
-            mParamType = "TYPE";
-        }
-        if (!VCardUtils.containsOnlyAlphaDigitHyphen(value)) {
-            value = VCardUtils.convertStringCharset(
-                    value, mSourceCharset, VCardConfig.DEFAULT_IMPORT_CHARSET);
-        }
-        mCurrentProperty.addParameter(mParamType, value);
-        mParamType = null;
-    }
-
-    private String handleOneValue(String value,
-            String sourceCharset, String targetCharset, String encoding) {
-        // It is possible when some of multiple values are empty.
-        // e.g. N:;a;;; -> values are "", "a", "", "", and "".
-        if (TextUtils.isEmpty(value)) {
-            return "";
-        }
-
-        if (encoding != null) {
-            if (encoding.equals("BASE64") || encoding.equals("B")) {
-                mCurrentProperty.setPropertyBytes(Base64.decode(value.getBytes(), Base64.DEFAULT));
-                return value;
-            } else if (encoding.equals("QUOTED-PRINTABLE")) {
-                return VCardUtils.parseQuotedPrintable(
-                        value, mStrictLineBreaking, sourceCharset, targetCharset);
-            }
-            Log.w(LOG_TAG, "Unknown encoding. Fall back to default.");
-        }
-
-        // Just translate the charset of a given String from inputCharset to a system one. 
-        return VCardUtils.convertStringCharset(value, sourceCharset, targetCharset);
-    }
-    
-    public void propertyValues(List<String> values) {
-        if (values == null || values.isEmpty()) {
-            return;
-        }
-
-        final Collection<String> charsetCollection =
-                mCurrentProperty.getParameters(VCardConstants.PARAM_CHARSET);
-        final Collection<String> encodingCollection =
-                mCurrentProperty.getParameters(VCardConstants.PARAM_ENCODING);
-        final String encoding =
-            ((encodingCollection != null) ? encodingCollection.iterator().next() : null);
-        String targetCharset = CharsetUtils.nameForDefaultVendor(
-                ((charsetCollection != null) ? charsetCollection.iterator().next() : null));
-        if (TextUtils.isEmpty(targetCharset)) {
-            targetCharset = VCardConfig.DEFAULT_IMPORT_CHARSET;
-        }
-
-        for (final String value : values) {
-            mCurrentProperty.addToPropertyValueList(
-                    handleOneValue(value, mSourceCharset, targetCharset, encoding));
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void showPerformanceInfo() {
-        Log.d(LOG_TAG, "time for insert ContactStruct to database: " + 
-                mTimePushIntoContentResolver + " ms");
-    }
-}
diff --git a/src/com/android/vcard/VCardEntryCounter.java b/src/com/android/vcard/VCardEntryCounter.java
deleted file mode 100644
index 7bfe977..0000000
--- a/src/com/android/vcard/VCardEntryCounter.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.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;
-
-    public int getCount() {
-        return mCount;
-    }
-
-    public void start() {
-    }
-
-    public void end() {
-    }
-
-    public void startEntry() {
-    }
-
-    public void endEntry() {
-        mCount++;
-    }
-
-    public void startProperty() {
-    }
-
-    public void endProperty() {
-    }
-
-    public void propertyGroup(String group) {
-    }
-
-    public void propertyName(String name) {
-    }
-
-    public void propertyParamType(String type) {
-    }
-
-    public void propertyParamValue(String value) {
-    }
-
-    public void propertyValues(List<String> values) {
-    }    
-}
diff --git a/src/com/android/vcard/VCardEntryHandler.java b/src/com/android/vcard/VCardEntryHandler.java
deleted file mode 100644
index ef35a20..0000000
--- a/src/com/android/vcard/VCardEntryHandler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-/**
- * <p>
- * The interface called by {@link VCardEntryConstructor}.
- * </p>
- * <p>
- * 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}.
- * </p>
- */
-public interface VCardEntryHandler {
-    /**
-     * Called when the parsing started.
-     */
-    public void onStart();
-
-    /**
-     * The method called when one VCard entry is successfully created
-     */
-    public void onEntryCreated(final VCardEntry entry);
-
-    /**
-     * Called when the parsing ended.
-     * Able to be use this method for showing performance log, etc.
-     */
-    public void onEnd();
-}
diff --git a/src/com/android/vcard/VCardInterpreter.java b/src/com/android/vcard/VCardInterpreter.java
deleted file mode 100644
index 2d98764..0000000
--- a/src/com/android/vcard/VCardInterpreter.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import java.util.List;
-
-/**
- * <P>
- * The interface which should be implemented by the classes which have to analyze each
- * vCard entry minutely.
- * </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();
-
-    /** 
-     * Called when parsing one vCard entry started.
-     * More specifically, this method is called when "BEGIN:VCARD" is read.
-     */
-    void startEntry();
-
-    /**
-     * 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 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 A property name like "N", "FN", "ADR", etc.
-     */
-    void propertyName(String name);
-
-    /**
-     * @param type A parameter name like "ENCODING", "CHARSET", etc.
-     */
-    void propertyParamType(String type);
-
-    /**
-     * @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);
-}
diff --git a/src/com/android/vcard/VCardInterpreterCollection.java b/src/com/android/vcard/VCardInterpreterCollection.java
deleted file mode 100644
index adf577e..0000000
--- a/src/com/android/vcard/VCardInterpreterCollection.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 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 final class VCardInterpreterCollection implements VCardInterpreter {
-    private final Collection<VCardInterpreter> mInterpreterCollection;
-
-    public VCardInterpreterCollection(Collection<VCardInterpreter> interpreterCollection) {
-        mInterpreterCollection = interpreterCollection;
-    }
-
-    public Collection<VCardInterpreter> getCollection() {
-        return mInterpreterCollection;
-    }
-
-    public void start() {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.start();
-        }
-    }
-
-    public void end() {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.end();
-        }
-    }
-
-    public void startEntry() {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.startEntry();
-        }
-    }
-
-    public void endEntry() {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.endEntry();
-        }
-    }
-
-    public void startProperty() {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.startProperty();
-        }
-    }
-
-    public void endProperty() {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.endProperty();
-        }
-    }
-
-    public void propertyGroup(String group) {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.propertyGroup(group);
-        }
-    }
-
-    public void propertyName(String name) {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.propertyName(name);
-        }
-    }
-
-    public void propertyParamType(String type) {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.propertyParamType(type);
-        }
-    }
-
-    public void propertyParamValue(String value) {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.propertyParamValue(value);
-        }
-    }
-
-    public void propertyValues(List<String> values) {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.propertyValues(values);
-        }
-    }
-}
diff --git a/src/com/android/vcard/VCardParser.java b/src/com/android/vcard/VCardParser.java
deleted file mode 100644
index b7b8291..0000000
--- a/src/com/android/vcard/VCardParser.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import com.android.vcard.exception.VCardException;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public interface 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 allowed in vCard 3.0. In vCard 2.1,
-     * In some exreme case, it is allowed for vCard to have different charsets in one vCard.
-     * </p>
-     * <p>
-     * We recommend you 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 interepreter A {@link VCardInterpreter} object which used to construct data.
-     * @throws IOException, VCardException
-     */
-    public void parse(InputStream is, VCardInterpreter interepreter)
-            throws IOException, VCardException;
-
-    /**
-     * <p>
-     * Cancel parsing vCard. Useful when you want to stop the parse in the other threads.
-     * </p>
-     * <p>
-     * Actual cancel is done after parsing the current vcard.
-     * </p>
-     */
-    public abstract void cancel();
-}
diff --git a/src/com/android/vcard/VCardParserImpl_V21.java b/src/com/android/vcard/VCardParserImpl_V21.java
deleted file mode 100644
index f030c6e..0000000
--- a/src/com/android/vcard/VCardParserImpl_V21.java
+++ /dev/null
@@ -1,1047 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.vcard.exception.VCardAgentNotSupportedException;
-import com.android.vcard.exception.VCardException;
-import com.android.vcard.exception.VCardInvalidCommentLineException;
-import com.android.vcard.exception.VCardInvalidLineException;
-import com.android.vcard.exception.VCardNestedException;
-import com.android.vcard.exception.VCardVersionException;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * <p>
- * Basic implementation achieving vCard parsing. Based on vCard 2.1,
- * </p>
- * @hide
- */
-/* package */ class VCardParserImpl_V21 {
-    private static final String LOG_TAG = "VCardParserImpl_V21";
-
-    private static final class EmptyInterpreter implements VCardInterpreter {
-        @Override
-        public void end() {
-        }
-        @Override
-        public void endEntry() {
-        }
-        @Override
-        public void endProperty() {
-        }
-        @Override
-        public void propertyGroup(String group) {
-        }
-        @Override
-        public void propertyName(String name) {
-        }
-        @Override
-        public void propertyParamType(String type) {
-        }
-        @Override
-        public void propertyParamValue(String value) {
-        }
-        @Override
-        public void propertyValues(List<String> values) {
-        }
-        @Override
-        public void start() {
-        }
-        @Override
-        public void startEntry() {
-        }
-        @Override
-        public void startProperty() {
-        }
-    }
-
-    protected static final class CustomBufferedReader extends BufferedReader {
-        private long mTime;
-
-        /**
-         * Needed since "next line" may be null due to end of line.
-         */
-        private boolean mNextLineIsValid;
-        private String mNextLine;
-
-        public CustomBufferedReader(Reader in) {
-            super(in);
-        }
-
-        @Override
-        public String readLine() throws IOException {
-            if (mNextLineIsValid) {
-                final String ret = mNextLine;
-                mNextLine = null;
-                mNextLineIsValid = false;
-                return ret;
-            }
-
-            long start = System.currentTimeMillis();
-            final String line = super.readLine();
-            long end = System.currentTimeMillis();
-            mTime += end - start;
-            return line;
-        }
-
-        /**
-         * Read one line, but make this object store it in its queue.
-         */
-        public String peekLine() throws IOException {
-            if (!mNextLineIsValid) {
-                long start = System.currentTimeMillis();
-                final String line = super.readLine();
-                long end = System.currentTimeMillis();
-                mTime += end - start;
-
-                mNextLine = line;
-                mNextLineIsValid = true;
-            }
-
-            return mNextLine;
-        }
-
-        public long getTotalmillisecond() {
-            return mTime;
-        }
-    }
-
-    private static final String DEFAULT_ENCODING = "8BIT";
-
-    protected boolean mCanceled;
-    protected VCardInterpreter mInterpreter;
-
-    protected final String mIntermediateCharset;
-
-    /**
-     * <p>
-     * The encoding type for deconding byte streams. This member variable is
-     * reset to a default encoding every time when a new item comes.
-     * </p>
-     * <p>
-     * "Encoding" in vCard is different from "Charset". It is mainly used for
-     * addresses, notes, images. "7BIT", "8BIT", "BASE64", and
-     * "QUOTED-PRINTABLE" are known examples.
-     * </p>
-     */
-    protected String mCurrentEncoding;
-
-    /**
-     * <p>
-     * The reader object to be used internally.
-     * </p>
-     * <p>
-     * Developers should not directly read a line from this object. Use
-     * getLine() unless there some reason.
-     * </p>
-     */
-    protected CustomBufferedReader mReader;
-
-    /**
-     * <p>
-     * Set for storing unkonwn TYPE attributes, which is not acceptable in vCard
-     * specification, but happens to be seen in real world vCard.
-     * </p>
-     */
-    protected final Set<String> mUnknownTypeSet = new HashSet<String>();
-
-    /**
-     * <p>
-     * Set for storing unkonwn VALUE attributes, which is not acceptable in
-     * vCard specification, but happens to be seen in real world vCard.
-     * </p>
-     */
-    protected final Set<String> mUnknownValueSet = new HashSet<String>();
-
-
-    // In some cases, vCard is nested. Currently, we only consider the most
-    // interior vCard data.
-    // See v21_foma_1.vcf in test directory for more information.
-    // TODO: Don't ignore by using count, but read all of information outside vCard.
-    private int mNestCount;
-
-    // Used only for parsing END:VCARD.
-    private String mPreviousLine;
-
-    // For measuring performance.
-    private long mTimeTotal;
-    private long mTimeReadStartRecord;
-    private long mTimeReadEndRecord;
-    private long mTimeStartProperty;
-    private long mTimeEndProperty;
-    private long mTimeParseItems;
-    private long mTimeParseLineAndHandleGroup;
-    private long mTimeParsePropertyValues;
-    private long mTimeParseAdrOrgN;
-    private long mTimeHandleMiscPropertyValue;
-    private long mTimeHandleQuotedPrintable;
-    private long mTimeHandleBase64;
-
-    public VCardParserImpl_V21() {
-        this(VCardConfig.VCARD_TYPE_DEFAULT);
-    }
-
-    public VCardParserImpl_V21(int vcardType) {
-        if ((vcardType & VCardConfig.FLAG_TORELATE_NEST) != 0) {
-            mNestCount = 1;
-        }
-
-        mIntermediateCharset =  VCardConfig.DEFAULT_INTERMEDIATE_CHARSET;
-    }
-
-    /**
-     * <p>
-     * Parses the file at the given position.
-     * </p>
-     */
-    // <pre class="prettyprint">vcard_file = [wsls] vcard [wsls]</pre>
-    protected void parseVCardFile() throws IOException, VCardException {
-        boolean readingFirstFile = true;
-        while (true) {
-            if (mCanceled) {
-                break;
-            }
-            if (!parseOneVCard(readingFirstFile)) {
-                break;
-            }
-            readingFirstFile = false;
-        }
-
-        if (mNestCount > 0) {
-            boolean useCache = true;
-            for (int i = 0; i < mNestCount; i++) {
-                readEndVCard(useCache, true);
-                useCache = false;
-            }
-        }
-    }
-
-    /**
-     * @return true when a given property name is a valid property name.
-     */
-    protected boolean isValidPropertyName(final String propertyName) {
-        if (!(getKnownPropertyNameSet().contains(propertyName.toUpperCase()) ||
-                propertyName.startsWith("X-"))
-                && !mUnknownTypeSet.contains(propertyName)) {
-            mUnknownTypeSet.add(propertyName);
-            Log.w(LOG_TAG, "Property name unsupported by vCard 2.1: " + propertyName);
-        }
-        return true;
-    }
-
-    /**
-     * @return String. It may be null, or its length may be 0
-     * @throws IOException
-     */
-    protected String getLine() throws IOException {
-        return mReader.readLine();
-    }
-
-    protected String peekLine() throws IOException {
-        return mReader.peekLine();
-    }
-
-    /**
-     * @return String with it's length > 0
-     * @throws IOException
-     * @throws VCardException when the stream reached end of line
-     */
-    protected String getNonEmptyLine() throws IOException, VCardException {
-        String line;
-        while (true) {
-            line = getLine();
-            if (line == null) {
-                throw new VCardException("Reached end of buffer.");
-            } else if (line.trim().length() > 0) {
-                return line;
-            }
-        }
-    }
-
-    /*
-     * vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF
-     *         items *CRLF
-     *         "END" [ws] ":" [ws] "VCARD"
-     */
-    private boolean parseOneVCard(boolean firstRead) throws IOException, VCardException {
-        boolean allowGarbage = false;
-        if (firstRead) {
-            if (mNestCount > 0) {
-                for (int i = 0; i < mNestCount; i++) {
-                    if (!readBeginVCard(allowGarbage)) {
-                        return false;
-                    }
-                    allowGarbage = true;
-                }
-            }
-        }
-
-        if (!readBeginVCard(allowGarbage)) {
-            return false;
-        }
-        final long beforeStartEntry = System.currentTimeMillis();
-        mInterpreter.startEntry();
-        mTimeReadStartRecord += System.currentTimeMillis() - beforeStartEntry;
-
-        final long beforeParseItems = System.currentTimeMillis();
-        parseItems();
-        mTimeParseItems += System.currentTimeMillis() - beforeParseItems;
-
-        readEndVCard(true, false);
-
-        final long beforeEndEntry = System.currentTimeMillis();
-        mInterpreter.endEntry();
-        mTimeReadEndRecord += System.currentTimeMillis() - beforeEndEntry;
-        return true;
-    }
-
-    /**
-     * @return True when successful. False when reaching the end of line
-     * @throws IOException
-     * @throws VCardException
-     */
-    protected boolean readBeginVCard(boolean allowGarbage) throws IOException, VCardException {
-        String line;
-        do {
-            while (true) {
-                line = getLine();
-                if (line == null) {
-                    return false;
-                } else if (line.trim().length() > 0) {
-                    break;
-                }
-            }
-            final String[] strArray = line.split(":", 2);
-            final int length = strArray.length;
-
-            // Although vCard 2.1/3.0 specification does not allow lower cases,
-            // we found 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")) {
-                return true;
-            } else if (!allowGarbage) {
-                if (mNestCount > 0) {
-                    mPreviousLine = line;
-                    return false;
-                } else {
-                    throw new VCardException("Expected String \"BEGIN:VCARD\" did not come "
-                            + "(Instead, \"" + line + "\" came)");
-                }
-            }
-        } while (allowGarbage);
-
-        throw new VCardException("Reached where must not be reached.");
-    }
-
-    /**
-     * <p>
-     * The arguments useCache and allowGarbase are usually true and false
-     * accordingly when this function is called outside this function itself.
-     * </p>
-     * 
-     * @param useCache When true, line is obtained from mPreviousline.
-     *            Otherwise, getLine() is used.
-     * @param allowGarbage When true, ignore non "END:VCARD" line.
-     * @throws IOException
-     * @throws VCardException
-     */
-    protected void readEndVCard(boolean useCache, boolean allowGarbage) throws IOException,
-            VCardException {
-        String line;
-        do {
-            if (useCache) {
-                // Though vCard specification does not allow lower cases,
-                // some data may have them, so we allow it.
-                line = mPreviousLine;
-            } else {
-                while (true) {
-                    line = getLine();
-                    if (line == null) {
-                        throw new VCardException("Expected END:VCARD was not found.");
-                    } else if (line.trim().length() > 0) {
-                        break;
-                    }
-                }
-            }
-
-            String[] strArray = line.split(":", 2);
-            if (strArray.length == 2 && strArray[0].trim().equalsIgnoreCase("END")
-                    && strArray[1].trim().equalsIgnoreCase("VCARD")) {
-                return;
-            } else if (!allowGarbage) {
-                throw new VCardException("END:VCARD != \"" + mPreviousLine + "\"");
-            }
-            useCache = false;
-        } while (allowGarbage);
-    }
-
-    /*
-     * items = *CRLF item / item
-     */
-    protected void parseItems() throws IOException, VCardException {
-        boolean ended = false;
-
-        final long beforeBeginProperty = System.currentTimeMillis();
-        mInterpreter.startProperty();
-        mTimeStartProperty += System.currentTimeMillis() - beforeBeginProperty;
-        ended = parseItem();
-        if (!ended) {
-            final long beforeEndProperty = System.currentTimeMillis();
-            mInterpreter.endProperty();
-            mTimeEndProperty += System.currentTimeMillis() - beforeEndProperty;
-        }
-
-        while (!ended) {
-            final long beforeStartProperty = System.currentTimeMillis();
-            mInterpreter.startProperty();
-            mTimeStartProperty += System.currentTimeMillis() - beforeStartProperty;
-            try {
-                ended = parseItem();
-            } catch (VCardInvalidCommentLineException e) {
-                Log.e(LOG_TAG, "Invalid line which looks like some comment was found. Ignored.");
-                ended = false;
-            }
-
-            if (!ended) {
-                final long beforeEndProperty = System.currentTimeMillis();
-                mInterpreter.endProperty();
-                mTimeEndProperty += System.currentTimeMillis() - beforeEndProperty;
-            }
-        }
-    }
-
-    /*
-     * item = [groups "."] name [params] ":" value CRLF / [groups "."] "ADR"
-     * [params] ":" addressparts CRLF / [groups "."] "ORG" [params] ":" orgparts
-     * CRLF / [groups "."] "N" [params] ":" nameparts CRLF / [groups "."]
-     * "AGENT" [params] ":" vcard CRLF
-     */
-    protected boolean parseItem() throws IOException, VCardException {
-        mCurrentEncoding = DEFAULT_ENCODING;
-
-        final String line = getNonEmptyLine();
-        long start = System.currentTimeMillis();
-
-        String[] propertyNameAndValue = separateLineAndHandleGroup(line);
-        if (propertyNameAndValue == null) {
-            return true;
-        }
-        if (propertyNameAndValue.length != 2) {
-            throw new VCardInvalidLineException("Invalid line \"" + line + "\"");
-        }
-        String propertyName = propertyNameAndValue[0].toUpperCase();
-        String propertyValue = propertyNameAndValue[1];
-
-        mTimeParseLineAndHandleGroup += System.currentTimeMillis() - start;
-
-        if (propertyName.equals("ADR") || propertyName.equals("ORG") || propertyName.equals("N")) {
-            start = System.currentTimeMillis();
-            handleMultiplePropertyValue(propertyName, propertyValue);
-            mTimeParseAdrOrgN += System.currentTimeMillis() - start;
-            return false;
-        } else if (propertyName.equals("AGENT")) {
-            handleAgent(propertyValue);
-            return false;
-        } else if (isValidPropertyName(propertyName)) {
-            if (propertyName.equals("BEGIN")) {
-                if (propertyValue.equals("VCARD")) {
-                    throw new VCardNestedException("This vCard has nested vCard data in it.");
-                } else {
-                    throw new VCardException("Unknown BEGIN type: " + propertyValue);
-                }
-            } else if (propertyName.equals("VERSION") && !propertyValue.equals(getVersionString())) {
-                throw new VCardVersionException("Incompatible version: " + propertyValue + " != "
-                        + getVersionString());
-            }
-            start = System.currentTimeMillis();
-            handlePropertyValue(propertyName, propertyValue);
-            mTimeParsePropertyValues += System.currentTimeMillis() - start;
-            return false;
-        }
-
-        throw new VCardException("Unknown property name: \"" + propertyName + "\"");
-    }
-
-    // For performance reason, the states for group and property name are merged into one.
-    static private final int STATE_GROUP_OR_PROPERTY_NAME = 0;
-    static private final int STATE_PARAMS = 1;
-    // vCard 3.0 specification allows double-quoted parameters, while vCard 2.1 does not.
-    static private final int STATE_PARAMS_IN_DQUOTE = 2;
-
-    protected String[] separateLineAndHandleGroup(String line) throws VCardException {
-        final String[] propertyNameAndValue = new String[2];
-        final int length = line.length();
-        if (length > 0 && line.charAt(0) == '#') {
-            throw new VCardInvalidCommentLineException();
-        }
-
-        int state = STATE_GROUP_OR_PROPERTY_NAME;
-        int nameIndex = 0;
-
-        // This loop is developed so that we don't have to take care of bottle neck here.
-        // Refactor carefully when you need to do so.
-        for (int i = 0; i < length; i++) {
-            final char ch = line.charAt(i);
-            switch (state) {
-                case STATE_GROUP_OR_PROPERTY_NAME: {
-                    if (ch == ':') {  // End of a property name.
-                        final String propertyName = line.substring(nameIndex, i);
-                        if (propertyName.equalsIgnoreCase("END")) {
-                            mPreviousLine = line;
-                            return null;
-                        }
-                        mInterpreter.propertyName(propertyName);
-                        propertyNameAndValue[0] = propertyName;
-                        if (i < length - 1) {
-                            propertyNameAndValue[1] = line.substring(i + 1);
-                        } else {
-                            propertyNameAndValue[1] = "";
-                        }
-                        return propertyNameAndValue;
-                    } else if (ch == '.') {  // Each group is followed by the dot.
-                        final String groupName = line.substring(nameIndex, i);
-                        if (groupName.length() == 0) {
-                            Log.w(LOG_TAG, "Empty group found. Ignoring.");
-                        } else {
-                            mInterpreter.propertyGroup(groupName);
-                        }
-                        nameIndex = i + 1;  // Next should be another group or a property name.
-                    } else if (ch == ';') {  // End of property name and beginneng of parameters.  
-                        final String propertyName = line.substring(nameIndex, i);
-                        if (propertyName.equalsIgnoreCase("END")) {
-                            mPreviousLine = line;
-                            return null;
-                        }
-                        mInterpreter.propertyName(propertyName);
-                        propertyNameAndValue[0] = propertyName;
-                        nameIndex = i + 1;
-                        state = STATE_PARAMS;  // Start parameter parsing.
-                    }
-                    // TODO: comma support (in vCard 3.0 and 4.0).
-                    break;
-                }
-                case STATE_PARAMS: {
-                    if (ch == '"') {
-                        if (VCardConstants.VERSION_V21.equalsIgnoreCase(getVersionString())) {
-                            Log.w(LOG_TAG, "Double-quoted params found in vCard 2.1. " +
-                                    "Silently allow it");
-                        }
-                        state = STATE_PARAMS_IN_DQUOTE;
-                    } else if (ch == ';') {  // Starts another param.
-                        handleParams(line.substring(nameIndex, i));
-                        nameIndex = i + 1;
-                    } else if (ch == ':') {  // End of param and beginenning of values.
-                        handleParams(line.substring(nameIndex, i));
-                        if (i < length - 1) {
-                            propertyNameAndValue[1] = line.substring(i + 1);
-                        } else {
-                            propertyNameAndValue[1] = "";
-                        }
-                        return propertyNameAndValue;
-                    }
-                    break;
-                }
-                case STATE_PARAMS_IN_DQUOTE: {
-                    if (ch == '"') {
-                        if (VCardConstants.VERSION_V21.equalsIgnoreCase(getVersionString())) {
-                            Log.w(LOG_TAG, "Double-quoted params found in vCard 2.1. " +
-                                    "Silently allow it");
-                        }
-                        state = STATE_PARAMS;
-                    }
-                    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
-     */
-    protected void handleParams(String params) throws VCardException {
-        final String[] strArray = params.split("=", 2);
-        if (strArray.length == 2) {
-            final String paramName = strArray[0].trim().toUpperCase();
-            String paramValue = strArray[1].trim();
-            if (paramName.equals("TYPE")) {
-                handleType(paramValue);
-            } else if (paramName.equals("VALUE")) {
-                handleValue(paramValue);
-            } else if (paramName.equals("ENCODING")) {
-                handleEncoding(paramValue);
-            } else if (paramName.equals("CHARSET")) {
-                handleCharset(paramValue);
-            } else if (paramName.equals("LANGUAGE")) {
-                handleLanguage(paramValue);
-            } else if (paramName.startsWith("X-")) {
-                handleAnyParam(paramName, paramValue);
-            } else {
-                throw new VCardException("Unknown type \"" + paramName + "\"");
-            }
-        } else {
-            handleParamWithoutName(strArray[0]);
-        }
-    }
-
-    /**
-     * vCard 3.0 parser implementation may throw VCardException.
-     */
-    @SuppressWarnings("unused")
-    protected void handleParamWithoutName(final String paramValue) throws VCardException {
-        handleType(paramValue);
-    }
-
-    /*
-     * ptypeval = knowntype / "X-" word
-     */
-    protected void handleType(final String ptypeval) {
-        if (!(getKnownTypeSet().contains(ptypeval.toUpperCase())
-                || ptypeval.startsWith("X-"))
-                && !mUnknownTypeSet.contains(ptypeval)) {
-            mUnknownTypeSet.add(ptypeval);
-            Log.w(LOG_TAG, String.format("TYPE unsupported by %s: ", getVersion(), ptypeval));
-        }
-        mInterpreter.propertyParamType("TYPE");
-        mInterpreter.propertyParamValue(ptypeval);
-    }
-
-    /*
-     * pvalueval = "INLINE" / "URL" / "CONTENT-ID" / "CID" / "X-" word
-     */
-    protected void handleValue(final String pvalueval) {
-        if (!(getKnownValueSet().contains(pvalueval.toUpperCase())
-                || pvalueval.startsWith("X-")
-                || mUnknownValueSet.contains(pvalueval))) {
-            mUnknownValueSet.add(pvalueval);
-            Log.w(LOG_TAG, String.format(
-                    "The value unsupported by TYPE of %s: ", getVersion(), pvalueval));
-        }
-        mInterpreter.propertyParamType("VALUE");
-        mInterpreter.propertyParamValue(pvalueval);
-    }
-
-    /*
-     * pencodingval = "7BIT" / "8BIT" / "QUOTED-PRINTABLE" / "BASE64" / "X-" word
-     */
-    protected void handleEncoding(String pencodingval) throws VCardException {
-        if (getAvailableEncodingSet().contains(pencodingval) ||
-                pencodingval.startsWith("X-")) {
-            mInterpreter.propertyParamType("ENCODING");
-            mInterpreter.propertyParamValue(pencodingval);
-            mCurrentEncoding = pencodingval;
-        } else {
-            throw new VCardException("Unknown encoding \"" + pencodingval + "\"");
-        }
-    }
-
-    /**
-     * <p>
-     * vCard 2.1 specification only allows us-ascii and iso-8859-xxx (See RFC 1521),
-     * but recent vCard files often contain other charset like UTF-8, SHIFT_JIS, etc.
-     * We allow any charset.
-     * </p>
-     */
-    protected void handleCharset(String charsetval) {
-        mInterpreter.propertyParamType("CHARSET");
-        mInterpreter.propertyParamValue(charsetval);
-    }
-
-    /**
-     * See also Section 7.1 of RFC 1521
-     */
-    protected void handleLanguage(String langval) throws VCardException {
-        String[] strArray = langval.split("-");
-        if (strArray.length != 2) {
-            throw new VCardException("Invalid Language: \"" + langval + "\"");
-        }
-        String tmp = strArray[0];
-        int length = tmp.length();
-        for (int i = 0; i < length; i++) {
-            if (!isAsciiLetter(tmp.charAt(i))) {
-                throw new VCardException("Invalid Language: \"" + langval + "\"");
-            }
-        }
-        tmp = strArray[1];
-        length = tmp.length();
-        for (int i = 0; i < length; i++) {
-            if (!isAsciiLetter(tmp.charAt(i))) {
-                throw new VCardException("Invalid Language: \"" + langval + "\"");
-            }
-        }
-        mInterpreter.propertyParamType(VCardConstants.PARAM_LANGUAGE);
-        mInterpreter.propertyParamValue(langval);
-    }
-
-    private boolean isAsciiLetter(char ch) {
-        if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Mainly for "X-" type. This accepts any kind of type without check.
-     */
-    protected void handleAnyParam(String paramName, String paramValue) {
-        mInterpreter.propertyParamType(paramName);
-        mInterpreter.propertyParamValue(paramValue);
-    }
-
-    protected void handlePropertyValue(String propertyName, String propertyValue)
-            throws IOException, VCardException {
-        final String upperEncoding = mCurrentEncoding.toUpperCase();
-        if (upperEncoding.equals(VCardConstants.PARAM_ENCODING_QP)) {
-            final long start = System.currentTimeMillis();
-            final String result = getQuotedPrintable(propertyValue);
-            final ArrayList<String> v = new ArrayList<String>();
-            v.add(result);
-            mInterpreter.propertyValues(v);
-            mTimeHandleQuotedPrintable += System.currentTimeMillis() - start;
-        } else if (upperEncoding.equals(VCardConstants.PARAM_ENCODING_BASE64)
-                || upperEncoding.equals(VCardConstants.PARAM_ENCODING_B)) {
-            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 {
-                final ArrayList<String> arrayList = new ArrayList<String>();
-                arrayList.add(getBase64(propertyValue));
-                mInterpreter.propertyValues(arrayList);
-            } catch (OutOfMemoryError error) {
-                Log.e(LOG_TAG, "OutOfMemoryError happened during parsing BASE64 data!");
-                mInterpreter.propertyValues(null);
-            }
-            mTimeHandleBase64 += System.currentTimeMillis() - start;
-        } else {
-            if (!(upperEncoding.equals("7BIT") || upperEncoding.equals("8BIT") ||
-                    upperEncoding.startsWith("X-"))) {
-                Log.w(LOG_TAG,
-                        String.format("The encoding \"%s\" is unsupported by vCard %s",
-                                mCurrentEncoding, getVersionString()));
-            }
-
-            // Some device uses line folding defined in RFC 2425, which is not allowed
-            // in vCard 2.1 (while needed in vCard 3.0).
-            //
-            // e.g.
-            // BEGIN:VCARD
-            // VERSION:2.1
-            // N:;Omega;;;
-            // EMAIL;INTERNET:"Omega"
-            //   <omega@example.com>
-            // FN:Omega
-            // END:VCARD
-            //
-            // The vCard above assumes that email address should become:
-            // "Omega" <omega@example.com>
-            //
-            // But vCard 2.1 requires Quote-Printable when a line contains line break(s).
-            //
-            // For more information about line folding,
-            // see "5.8.1. Line delimiting and folding" in RFC 2425.
-            //
-            // We take care of this case more formally in vCard 3.0, so we only need to
-            // do this in vCard 2.1.
-            if (getVersion() == VCardConfig.VERSION_21) {
-                StringBuilder builder = null;
-                while (true) {
-                    final String nextLine = peekLine();
-                    // We don't need to care too much about this exceptional case,
-                    // but we should not wrongly eat up "END:VCARD", since it critically
-                    // breaks this parser's state machine.
-                    // Thus we roughly look over the next line and confirm it is at least not
-                    // "END:VCARD". This extra fee is worth paying. This is exceptional
-                    // anyway.
-                    if (!TextUtils.isEmpty(nextLine) &&
-                            nextLine.charAt(0) == ' ' &&
-                            !"END:VCARD".contains(nextLine.toUpperCase())) {
-                        getLine();  // Drop the next line.
-
-                        if (builder == null) {
-                            builder = new StringBuilder();
-                            builder.append(propertyValue);
-                        }
-                        builder.append(nextLine.substring(1));
-                    } else {
-                        break;
-                    }
-                }
-                if (builder != null) {
-                    propertyValue = builder.toString();
-                }
-            }
-
-            final long start = System.currentTimeMillis();
-            ArrayList<String> v = new ArrayList<String>();
-            v.add(maybeUnescapeText(propertyValue));
-            mInterpreter.propertyValues(v);
-            mTimeHandleMiscPropertyValue += System.currentTimeMillis() - start;
-        }
-    }
-
-    /**
-     * <p>
-     * Parses and returns Quoted-Printable.
-     * </p>
-     *
-     * @param firstString The string following a parameter name and attributes.
-     *            Example: "string" in
-     *            "ADR:ENCODING=QUOTED-PRINTABLE:string\n\r".
-     * @return whole Quoted-Printable string, including a given argument and
-     *         following lines. Excludes the last empty line following to Quoted
-     *         Printable lines.
-     * @throws IOException
-     * @throws VCardException
-     */
-    private String getQuotedPrintable(String firstString) throws IOException, VCardException {
-        // Specifically, there may be some padding between = and CRLF.
-        // See the following:
-        //
-        // qp-line := *(qp-segment transport-padding CRLF)
-        // qp-part transport-padding
-        // qp-segment := qp-section *(SPACE / TAB) "="
-        // ; Maximum length of 76 characters
-        //
-        // e.g. (from RFC 2045)
-        // Now's the time =
-        // for all folk to come=
-        // to the aid of their country.
-        if (firstString.trim().endsWith("=")) {
-            // remove "transport-padding"
-            int pos = firstString.length() - 1;
-            while (firstString.charAt(pos) != '=') {
-            }
-            StringBuilder builder = new StringBuilder();
-            builder.append(firstString.substring(0, pos + 1));
-            builder.append("\r\n");
-            String line;
-            while (true) {
-                line = getLine();
-                if (line == null) {
-                    throw new VCardException("File ended during parsing a Quoted-Printable String");
-                }
-                if (line.trim().endsWith("=")) {
-                    // remove "transport-padding"
-                    pos = line.length() - 1;
-                    while (line.charAt(pos) != '=') {
-                    }
-                    builder.append(line.substring(0, pos + 1));
-                    builder.append("\r\n");
-                } else {
-                    builder.append(line);
-                    break;
-                }
-            }
-            return builder.toString();
-        } else {
-            return firstString;
-        }
-    }
-
-    protected String getBase64(String firstString) throws IOException, VCardException {
-        StringBuilder builder = new StringBuilder();
-        builder.append(firstString);
-
-        while (true) {
-            String line = getLine();
-            if (line == null) {
-                throw new VCardException("File ended during parsing BASE64 binary");
-            }
-            if (line.length() == 0) {
-                break;
-            }
-            builder.append(line);
-        }
-
-        return builder.toString();
-    }
-
-    /**
-     * <p>
-     * Mainly for "ADR", "ORG", and "N"
-     * </p>
-     */
-    /*
-     * addressparts = 0*6(strnosemi ";") strnosemi ; PO Box, Extended Addr,
-     * Street, Locality, Region, Postal Code, Country Name orgparts =
-     * *(strnosemi ";") strnosemi ; First is Organization Name, remainder are
-     * Organization Units. nameparts = 0*4(strnosemi ";") strnosemi ; Family,
-     * Given, Middle, Prefix, Suffix. ; Example:Public;John;Q.;Reverend Dr.;III,
-     * Esq. strnosemi = *(*nonsemi ("\;" / "\" CRLF)) *nonsemi ; To include a
-     * semicolon in this string, it must be escaped ; with a "\" character. We
-     * do not care the number of "strnosemi" here. We are not sure whether we
-     * should add "\" CRLF to each value. We exclude them for now.
-     */
-    protected void handleMultiplePropertyValue(String propertyName, String propertyValue)
-            throws IOException, VCardException {
-        // vCard 2.1 does not allow QUOTED-PRINTABLE here, but some
-        // softwares/devices
-        // emit such data.
-        if (mCurrentEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
-            propertyValue = getQuotedPrintable(propertyValue);
-        }
-
-        mInterpreter.propertyValues(VCardUtils.constructListFromValue(propertyValue,
-                getVersion()));
-    }
-
-    /*
-     * vCard 2.1 specifies AGENT allows one vcard entry. Currently we emit an
-     * error toward the AGENT property.
-     * // TODO: Support AGENT property.
-     * 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 (!propertyValue.toUpperCase().contains("BEGIN:VCARD")) {
-            // Apparently invalid line seen in Windows Mobile 6.5. Ignore them.
-            return;
-        } else {
-            throw new VCardAgentNotSupportedException("AGENT Property is not supported now.");
-        }
-    }
-
-    /**
-     * For vCard 3.0.
-     */
-    protected String maybeUnescapeText(final String text) {
-        return text;
-    }
-
-    /**
-     * Returns unescaped String if the character should be unescaped. Return
-     * null otherwise. e.g. In vCard 2.1, "\;" should be unescaped into ";"
-     * while "\x" should not be.
-     */
-    protected String maybeUnescapeCharacter(final char ch) {
-        return unescapeCharacter(ch);
-    }
-
-    /* package */ static String unescapeCharacter(final char ch) {
-        // Original vCard 2.1 specification does not allow transformation
-        // "\:" -> ":", "\," -> ",", and "\\" -> "\", but previous
-        // implementation of
-        // this class allowed them, so keep it as is.
-        if (ch == '\\' || ch == ';' || ch == ':' || ch == ',') {
-            return String.valueOf(ch);
-        } else {
-            return null;
-        }
-    }
-
-    private void showPerformanceInfo() {
-        Log.d(LOG_TAG, "Total parsing time:  " + mTimeTotal + " ms");
-        Log.d(LOG_TAG, "Total readLine time: " + mReader.getTotalmillisecond() + " ms");
-        Log.d(LOG_TAG, "Time for handling the beggining of the record: " + mTimeReadStartRecord
-                + " ms");
-        Log.d(LOG_TAG, "Time for handling the end of the record: " + mTimeReadEndRecord + " ms");
-        Log.d(LOG_TAG, "Time for parsing line, and handling group: " + mTimeParseLineAndHandleGroup
-                + " ms");
-        Log.d(LOG_TAG, "Time for parsing ADR, ORG, and N fields:" + mTimeParseAdrOrgN + " ms");
-        Log.d(LOG_TAG, "Time for parsing property values: " + mTimeParsePropertyValues + " ms");
-        Log.d(LOG_TAG, "Time for handling normal property values: " + mTimeHandleMiscPropertyValue
-                + " ms");
-        Log.d(LOG_TAG, "Time for handling Quoted-Printable: " + mTimeHandleQuotedPrintable + " ms");
-        Log.d(LOG_TAG, "Time for handling Base64: " + mTimeHandleBase64 + " ms");
-    }
-
-    /**
-     * @return {@link VCardConfig#VERSION_21}
-     */
-    protected int getVersion() {
-        return VCardConfig.VERSION_21;
-    }
-
-    /**
-     * @return {@link VCardConfig#VERSION_30}
-     */
-    protected String getVersionString() {
-        return VCardConstants.VERSION_V21;
-    }
-
-    protected Set<String> getKnownPropertyNameSet() {
-        return VCardParser_V21.sKnownPropertyNameSet;
-    }
-
-    protected Set<String> getKnownTypeSet() {
-        return VCardParser_V21.sKnownTypeSet;
-    }
-
-    protected Set<String> getKnownValueSet() {
-        return VCardParser_V21.sKnownValueSet;
-    }
-
-    protected Set<String> getAvailableEncodingSet() {
-        return VCardParser_V21.sAvailableEncoding;
-    }
-
-    protected String getDefaultEncoding() {
-        return DEFAULT_ENCODING;
-    }
-
-
-    public void parse(InputStream is, VCardInterpreter interpreter)
-            throws IOException, VCardException {
-        if (is == null) {
-            throw new NullPointerException("InputStream must not be null.");
-        }
-
-        final InputStreamReader tmpReader = new InputStreamReader(is, mIntermediateCharset);
-        mReader = new CustomBufferedReader(tmpReader);
-
-        mInterpreter = (interpreter != null ? interpreter : new EmptyInterpreter());
-
-        final long start = System.currentTimeMillis();
-        if (mInterpreter != null) {
-            mInterpreter.start();
-        }
-        parseVCardFile();
-        if (mInterpreter != null) {
-            mInterpreter.end();
-        }
-        mTimeTotal += System.currentTimeMillis() - start;
-
-        if (VCardConfig.showPerformanceLog()) {
-            showPerformanceInfo();
-        }
-    }
-
-    public final void cancel() {
-        mCanceled = true;
-    }
-}
diff --git a/src/com/android/vcard/VCardParserImpl_V30.java b/src/com/android/vcard/VCardParserImpl_V30.java
deleted file mode 100644
index 648ce7e..0000000
--- a/src/com/android/vcard/VCardParserImpl_V30.java
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import android.util.Log;
-
-import com.android.vcard.exception.VCardException;
-
-import java.io.IOException;
-import java.util.Set;
-
-/**
- * <p>
- * Basic implementation achieving vCard 3.0 parsing.
- * </p>
- * <p>
- * This class inherits vCard 2.1 implementation since technically they are similar,
- * while specifically there's logical no relevance between them.
- * So that developers are not confused with the inheritance,
- * {@link VCardParser_V30} does not inherit {@link VCardParser_V21}, while
- * {@link VCardParserImpl_V30} inherits {@link VCardParserImpl_V21}.
- * </p>
- * @hide
- */
-/* package */ class VCardParserImpl_V30 extends VCardParserImpl_V21 {
-    private static final String LOG_TAG = "VCardParserImpl_V30";
-
-    private String mPreviousLine;
-    private boolean mEmittedAgentWarning = false;
-
-    public VCardParserImpl_V30() {
-        super();
-    }
-
-    public VCardParserImpl_V30(int vcardType) {
-        super(vcardType);
-    }
-
-    @Override
-    protected int getVersion() {
-        return VCardConfig.VERSION_30;
-    }
-
-    @Override
-    protected String getVersionString() {
-        return VCardConstants.VERSION_V30;
-    }
-
-    @Override
-    protected String getLine() throws IOException {
-        if (mPreviousLine != null) {
-            String ret = mPreviousLine;
-            mPreviousLine = null;
-            return ret;
-        } else {
-            return mReader.readLine();
-        }
-    }
-
-    /**
-     * vCard 3.0 requires that the line with space at the beginning of the line
-     * must be combined with previous line.
-     */
-    @Override
-    protected String getNonEmptyLine() throws IOException, VCardException {
-        String line;
-        StringBuilder builder = null;
-        while (true) {
-            line = mReader.readLine();
-            if (line == null) {
-                if (builder != null) {
-                    return builder.toString();
-                } else if (mPreviousLine != null) {
-                    String ret = mPreviousLine;
-                    mPreviousLine = null;
-                    return ret;
-                }
-                throw new VCardException("Reached end of buffer.");
-            } else if (line.length() == 0) {
-                if (builder != null) {
-                    return builder.toString();
-                } else if (mPreviousLine != null) {
-                    String ret = mPreviousLine;
-                    mPreviousLine = null;
-                    return ret;
-                }
-            } else if (line.charAt(0) == ' ' || line.charAt(0) == '\t') {
-                if (builder != null) {
-                    // See Section 5.8.1 of RFC 2425 (MIME-DIR document).
-                    // Following is the excerpts from it.
-                    //
-                    // DESCRIPTION:This is a long description that exists on a long line.
-                    //
-                    // Can be represented as:
-                    //
-                    // DESCRIPTION:This is a long description
-                    //  that exists on a long line.
-                    //
-                    // It could also be represented as:
-                    //
-                    // DESCRIPTION:This is a long descrip
-                    //  tion that exists o
-                    //  n a long line.
-                    builder.append(line.substring(1));
-                } else if (mPreviousLine != null) {
-                    builder = new StringBuilder();
-                    builder.append(mPreviousLine);
-                    mPreviousLine = null;
-                    builder.append(line.substring(1));
-                } else {
-                    throw new VCardException("Space exists at the beginning of the line");
-                }
-            } else {
-                if (mPreviousLine == null) {
-                    mPreviousLine = line;
-                    if (builder != null) {
-                        return builder.toString();
-                    }
-                } else {
-                    String ret = mPreviousLine;
-                    mPreviousLine = line;
-                    return ret;
-                }
-            }
-        }
-    }
-
-    /*
-     * vcard = [group "."] "BEGIN" ":" "VCARD" 1 * CRLF
-     *         1 * (contentline)
-     *         ;A vCard object MUST include the VERSION, FN and N types.
-     *         [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 {
-        // TODO: vCard 3.0 supports group.
-        super.readEndVCard(useCache, allowGarbage);
-    }
-
-    /**
-     * vCard 3.0 allows iana-token as paramType, while vCard 2.1 does not.
-     */
-    @Override
-    protected void handleParams(final String params) throws VCardException {
-        try {
-            super.handleParams(params);
-        } catch (VCardException e) {
-            // maybe IANA type
-            String[] strArray = params.split("=", 2);
-            if (strArray.length == 2) {
-                handleAnyParam(strArray[0], strArray[1]);
-            } else {
-                // Must not come here in the current implementation.
-                throw new VCardException(
-                        "Unknown params value: " + params);
-            }
-        }
-    }
-
-    @Override
-    protected void handleAnyParam(final String paramName, final String paramValue) {
-        mInterpreter.propertyParamType(paramName);
-        splitAndPutParamValue(paramValue);
-    }
-
-    @Override
-    protected void handleParamWithoutName(final String paramValue) {
-        handleType(paramValue);
-    }
-
-    /*
-     *  vCard 3.0 defines
-     *
-     *  param         = param-name "=" param-value *("," param-value)
-     *  param-name    = iana-token / x-name
-     *  param-value   = ptext / quoted-string
-     *  quoted-string = DQUOTE QSAFE-CHAR DQUOTE
-     *  QSAFE-CHAR    = WSP / %x21 / %x23-7E / NON-ASCII
-     *                ; Any character except CTLs, DQUOTE
-     *
-     *  QSAFE-CHAR must not contain DQUOTE, including escaped one (\").
-     */
-    @Override
-    protected void handleType(final String paramValue) {
-        mInterpreter.propertyParamType("TYPE");
-        splitAndPutParamValue(paramValue);
-    }
-
-    /**
-     * Splits parameter values into pieces in accordance with vCard 3.0 specification and
-     * puts pieces into mInterpreter.
-     */
-    /*
-     *  param-value   = ptext / quoted-string
-     *  quoted-string = DQUOTE QSAFE-CHAR DQUOTE
-     *  QSAFE-CHAR    = WSP / %x21 / %x23-7E / NON-ASCII
-     *                ; Any character except CTLs, DQUOTE
-     *
-     *  QSAFE-CHAR must not contain DQUOTE, including escaped one (\")
-     */
-    private void splitAndPutParamValue(String paramValue) {
-        // "comma,separated:inside.dquote",pref
-        //   -->
-        // - comma,separated:inside.dquote
-        // - pref
-        //
-        // Note: Though there's a code, we don't need to take much care of
-        // wrongly-added quotes like the example above, as they induce
-        // parse errors at the top level (when splitting a line into parts).
-        StringBuilder builder = null;  // Delay initialization.
-        boolean insideDquote = false;
-        final int length = paramValue.length();
-        for (int i = 0; i < length; i++) {
-            final char ch = paramValue.charAt(i);
-            if (ch == '"') {
-                if (insideDquote) {
-                    // End of Dquote.
-                    mInterpreter.propertyParamValue(builder.toString());
-                    builder = null;
-                    insideDquote = false;
-                } else {
-                    if (builder != null) {
-                        if (builder.length() > 0) {
-                            // e.g.
-                            // pref"quoted"
-                            Log.w(LOG_TAG, "Unexpected Dquote inside property.");
-                        } else {
-                            // e.g.
-                            // pref,"quoted"
-                            // "quoted",pref
-                            mInterpreter.propertyParamValue(builder.toString());
-                        }
-                    }
-                    insideDquote = true;
-                }
-            } else if (ch == ',' && !insideDquote) {
-                if (builder == null) {
-                    Log.w(LOG_TAG, "Comma is used before actual string comes. (" +
-                            paramValue + ")");
-                } else {
-                    mInterpreter.propertyParamValue(builder.toString());
-                    builder = null;
-                }
-            } else {
-                // To stop creating empty StringBuffer at the end of parameter,
-                // we delay creating this object until this point.
-                if (builder == null) {
-                    builder = new StringBuilder();
-                }
-                builder.append(ch);
-            }
-        }
-        if (insideDquote) {
-            // e.g.
-            // "non-quote-at-end
-            Log.d(LOG_TAG, "Dangling Dquote.");
-        }
-        if (builder != null) {
-            if (builder.length() == 0) {
-                Log.w(LOG_TAG, "Unintended behavior. We must not see empty StringBuilder " +
-                        "at the end of parameter value parsing.");
-            } else {
-                mInterpreter.propertyParamValue(builder.toString());
-            }
-        }
-    }
-
-    @Override
-    protected void handleAgent(final String propertyValue) {
-        // 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
-        //  TITLE:Area Administrator\, Assistant\n EMAIL\;TYPE=INTERN\n
-        //  ET:jfriday@host.com\nEND:VCARD\n
-        //
-        // TODO: fix this.
-        //
-        // issue:
-        //  vCard 3.0 also allows this as an example.
-        //
-        // AGENT;VALUE=uri:
-        //  CID:JQPUBLIC.part3.960129T083020.xyzMail@host3.com
-        //
-        // 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;
-        }
-    }
-
-    /**
-     * vCard 3.0 does not require two CRLF at the last of BASE64 data.
-     * It only requires that data should be MIME-encoded.
-     */
-    @Override
-    protected String getBase64(final String firstString)
-            throws IOException, VCardException {
-        final StringBuilder builder = new StringBuilder();
-        builder.append(firstString);
-
-        while (true) {
-            final String line = getLine();
-            if (line == null) {
-                throw new VCardException("File ended during parsing BASE64 binary");
-            }
-            if (line.length() == 0) {
-                break;
-            } else if (!line.startsWith(" ") && !line.startsWith("\t")) {
-                mPreviousLine = line;
-                break;
-            }
-            builder.append(line);
-        }
-
-        return builder.toString();
-    }
-
-    /**
-     * ESCAPED-CHAR = "\\" / "\;" / "\," / "\n" / "\N")
-     *              ; \\ encodes \, \n or \N encodes newline
-     *              ; \; encodes ;, \, encodes ,
-     *
-     * Note: Apple escapes ':' into '\:' while does not escape '\'
-     */
-    @Override
-    protected String maybeUnescapeText(final String text) {
-        return unescapeText(text);
-    }
-
-    public static String unescapeText(final String text) {
-        StringBuilder builder = new StringBuilder();
-        final int length = text.length();
-        for (int i = 0; i < length; i++) {
-            char ch = text.charAt(i);
-            if (ch == '\\' && i < length - 1) {
-                final char next_ch = text.charAt(++i);
-                if (next_ch == 'n' || next_ch == 'N') {
-                    builder.append("\n");
-                } else {
-                    builder.append(next_ch);
-                }
-            } else {
-                builder.append(ch);
-            }
-        }
-        return builder.toString();
-    }
-
-    @Override
-    protected String maybeUnescapeCharacter(final char ch) {
-        return unescapeCharacter(ch);
-    }
-
-    public static String unescapeCharacter(final char ch) {
-        if (ch == 'n' || ch == 'N') {
-            return "\n";
-        } else {
-            return String.valueOf(ch);
-        }
-    }
-
-    @Override
-    protected Set<String> getKnownPropertyNameSet() {
-        return VCardParser_V30.sKnownPropertyNameSet;
-    }
-}
diff --git a/src/com/android/vcard/VCardParserImpl_V40.java b/src/com/android/vcard/VCardParserImpl_V40.java
deleted file mode 100644
index 3a49444..0000000
--- a/src/com/android/vcard/VCardParserImpl_V40.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import java.util.Set;
-
-
-/**
- * <p>
- * Basic implementation parsing vCard 4.0.
- * </p>
- * <p>
- * vCard 4.0 is not published yet. Also this implementation is premature. 
- * </p>
- * @hide
- */
-/* package */ class VCardParserImpl_V40 extends VCardParserImpl_V30 {
-    // private static final String LOG_TAG = "VCardParserImpl_V40";
-
-    public VCardParserImpl_V40() {
-        super();
-    }
-
-    public VCardParserImpl_V40(final int vcardType) {
-        super(vcardType);
-    }
-
-    @Override
-    protected int getVersion() {
-        return VCardConfig.VERSION_40;
-    }
-
-    @Override
-    protected String getVersionString() {
-        return VCardConstants.VERSION_V40;
-    }
-
-    /**
-     * We escape "\N" into new line for safety.
-     */
-    @Override
-    protected String maybeUnescapeText(final String text) {
-        return unescapeText(text);
-    }
-
-    public static String unescapeText(final String text) {
-        // TODO: more strictly, vCard 4.0 requires different type of unescaping rule
-        //       toward each property.
-        final StringBuilder builder = new StringBuilder();
-        final int length = text.length();
-        for (int i = 0; i < length; i++) {
-            char ch = text.charAt(i);
-            if (ch == '\\' && i < length - 1) {
-                final char next_ch = text.charAt(++i);
-                if (next_ch == 'n' || next_ch == 'N') {
-                    builder.append("\n");
-                } else {
-                    builder.append(next_ch);
-                }
-            } else {
-                builder.append(ch);
-            }
-        }
-        return builder.toString();
-    }
-
-    public static String unescapeCharacter(final char ch) {
-        if (ch == 'n' || ch == 'N') {
-            return "\n";
-        } else {
-            return String.valueOf(ch);
-        }
-    }
-
-    @Override
-    protected Set<String> getKnownPropertyNameSet() {
-        return VCardParser_V40.sKnownPropertyNameSet;
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/vcard/VCardParser_V21.java b/src/com/android/vcard/VCardParser_V21.java
deleted file mode 100644
index 7aa7a82..0000000
--- a/src/com/android/vcard/VCardParser_V21.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import com.android.vcard.exception.VCardException;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * </p>
- * vCard parser for vCard 2.1. See the specification for more detail about the spec itself.
- * </p>
- * <p>
- * The spec is written in 1996, and currently various types of "vCard 2.1" exist.
- * To handle real the world vCard formats appropriately and effectively, this class does not
- * obey with strict vCard 2.1.
- * In stead, not only vCard spec but also real world vCard is considered.
- * </p>
- * e.g. A lot of devices and softwares let vCard importer/exporter to use
- * the PNG format to determine the type of image, while it is not allowed in
- * the original specification. As of 2010, we can see even the FLV format
- * (possible in Japanese mobile phones).
- * </p>
- */
-public final class VCardParser_V21 implements VCardParser {
-    /**
-     * A unmodifiable Set storing the property names available in the vCard 2.1 specification.
-     */
-    /* package */ static final Set<String> sKnownPropertyNameSet =
-            Collections.unmodifiableSet(new HashSet<String>(
-                    Arrays.asList("BEGIN", "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND",
-                            "VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL",
-                            "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER")));
-
-    /**
-     * A unmodifiable Set storing the types known in vCard 2.1.
-     */
-    /* package */ static final Set<String> sKnownTypeSet =
-            Collections.unmodifiableSet(new HashSet<String>(
-                    Arrays.asList("DOM", "INTL", "POSTAL", "PARCEL", "HOME", "WORK",
-                            "PREF", "VOICE", "FAX", "MSG", "CELL", "PAGER", "BBS",
-                            "MODEM", "CAR", "ISDN", "VIDEO", "AOL", "APPLELINK",
-                            "ATTMAIL", "CIS", "EWORLD", "INTERNET", "IBMMAIL",
-                            "MCIMAIL", "POWERSHARE", "PRODIGY", "TLX", "X400", "GIF",
-                            "CGM", "WMF", "BMP", "MET", "PMB", "DIB", "PICT", "TIFF",
-                            "PDF", "PS", "JPEG", "QTIME", "MPEG", "MPEG2", "AVI",
-                            "WAVE", "AIFF", "PCM", "X509", "PGP")));
-
-    /**
-     * A unmodifiable Set storing the values for the type "VALUE", available in the vCard 2.1.
-     */
-    /* package */ static final Set<String> sKnownValueSet =
-            Collections.unmodifiableSet(new HashSet<String>(
-                    Arrays.asList("INLINE", "URL", "CONTENT-ID", "CID")));
-
-    /**
-     * <p>
-     * A unmodifiable Set storing the values for the type "ENCODING", available in the vCard 2.1.
-     * </p>
-     * <p>
-     * Though vCard 2.1 specification does not allow "B" encoding, some data may have it.
-     * We allow it for safety.
-     * </p>
-     */
-    /* package */ static final Set<String> sAvailableEncoding =
-        Collections.unmodifiableSet(new HashSet<String>(
-                Arrays.asList(VCardConstants.PARAM_ENCODING_7BIT,
-                        VCardConstants.PARAM_ENCODING_8BIT,
-                        VCardConstants.PARAM_ENCODING_QP,
-                        VCardConstants.PARAM_ENCODING_BASE64,
-                        VCardConstants.PARAM_ENCODING_B)));
-
-    private final VCardParserImpl_V21 mVCardParserImpl;
-
-    public VCardParser_V21() {
-        mVCardParserImpl = new VCardParserImpl_V21();
-    }
-
-    public VCardParser_V21(int vcardType) {
-        mVCardParserImpl = new VCardParserImpl_V21(vcardType);
-    }
-
-    public void parse(InputStream is, VCardInterpreter interepreter)
-            throws IOException, VCardException {
-        mVCardParserImpl.parse(is, interepreter);
-    }
-
-    public void cancel() {
-        mVCardParserImpl.cancel();
-    }
-}
diff --git a/src/com/android/vcard/VCardParser_V30.java b/src/com/android/vcard/VCardParser_V30.java
deleted file mode 100644
index 711a00e..0000000
--- a/src/com/android/vcard/VCardParser_V30.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import com.android.vcard.exception.VCardException;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * <p>
- * vCard parser for vCard 3.0. See RFC 2426 for more detail.
- * </p>
- * <p>
- * This parser allows vCard format which is not allowed in the RFC, since
- * we have seen several vCard 3.0 files which don't comply with it.
- * </p>
- * <p>
- * e.g. vCard 3.0 does not allow "CHARSET" attribute, but some actual files
- * have it and they uses non UTF-8 charsets. UTF-8 is recommended in RFC 2426,
- * but it is not a must. We silently allow "CHARSET".
- * </p>
- */
-public class VCardParser_V30 implements VCardParser {
-    /* package */ static final Set<String> sKnownPropertyNameSet =
-            Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
-                    "BEGIN", "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND", 
-                    "VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL",
-                    "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER", // 2.1
-                    "NAME", "PROFILE", "SOURCE", "NICKNAME", "CLASS",
-                    "SORT-STRING", "CATEGORIES", "PRODID",  // 3.0
-                    "IMPP"))); // RFC 4770
-
-    /**
-     * <p>
-     * A unmodifiable Set storing the values for the type "ENCODING", available in the vCard 3.0.
-     * </p>
-     * <p>
-     * Though vCard 2.1 specification does not allow "7BIT" or "BASE64", we allow them for safety.
-     * </p>
-     * <p>
-     * "QUOTED-PRINTABLE" is not allowed in vCard 3.0 and not in this parser either,
-     * because the encoding ambiguates how the vCard file to be parsed.
-     * </p>
-     */
-    /* package */ static final Set<String> sAcceptableEncoding =
-            Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
-                    VCardConstants.PARAM_ENCODING_7BIT,
-                    VCardConstants.PARAM_ENCODING_8BIT,
-                    VCardConstants.PARAM_ENCODING_BASE64,
-                    VCardConstants.PARAM_ENCODING_B)));
-
-    private final VCardParserImpl_V30 mVCardParserImpl;
-
-    public VCardParser_V30() {
-        mVCardParserImpl = new VCardParserImpl_V30();
-    }
-
-    public VCardParser_V30(int vcardType) {
-        mVCardParserImpl = new VCardParserImpl_V30(vcardType);
-    }
-
-    public void parse(InputStream is, VCardInterpreter interepreter)
-            throws IOException, VCardException {
-        mVCardParserImpl.parse(is, interepreter);
-    }
-
-    public void cancel() {
-        mVCardParserImpl.cancel();
-    }
-}
diff --git a/src/com/android/vcard/VCardParser_V40.java b/src/com/android/vcard/VCardParser_V40.java
deleted file mode 100644
index 700cdfd..0000000
--- a/src/com/android/vcard/VCardParser_V40.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import com.android.vcard.exception.VCardException;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * <p>
- * vCard parser for vCard 4.0.
- * </p>
- * <p>
- * Currently this parser is based on vCard 4.0 specification rev 11.
- * </p>
- */
-public class VCardParser_V40 implements VCardParser {
-    /* package */ static final Set<String> sKnownPropertyNameSet =
-            Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
-                    "BEGIN", "END", "SOURCE", "NAME", "KIND", "XML",
-                    "FN", "N", "NICKNAME", "PHOTO", "BDAY", "DDAY",
-                    "BIRTH", "DEATH", "ANNIVERSARY", "SEX", "ADR",
-                    "LABEL", "TEL", "EMAIL", "IMPP", "LANG", "TZ",
-                    "GEO", "TITLE", "ROLE", "LOGO", "ORG", "MEMBER",
-                    "RELATED", "CATEGORIES", "NOTE", "PRODID",
-                    "REV", "SOUND", "UID", "CLIENTPIDMAP",
-                    "URL", "VERSION", "CLASS", "KEY", "FBURL", "CALENDRURI",
-                    "CALURI")));
-
-    /**
-     * <p>
-     * A unmodifiable Set storing the values for the type "ENCODING", available in vCard 4.0.
-     * </p>
-     */
-    /* package */ static final Set<String> sAcceptableEncoding =
-            Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
-                    VCardConstants.PARAM_ENCODING_8BIT,
-                    VCardConstants.PARAM_ENCODING_B)));
-
-    private final VCardParserImpl_V30 mVCardParserImpl;
-
-    public VCardParser_V40() {
-        mVCardParserImpl = new VCardParserImpl_V40();
-    }
-
-    public VCardParser_V40(int vcardType) {
-        mVCardParserImpl = new VCardParserImpl_V40(vcardType);
-    }
-
-    @Override
-    public void parse(InputStream is, VCardInterpreter interepreter)
-            throws IOException, VCardException {
-        mVCardParserImpl.parse(is, interepreter);
-    }
-
-    @Override
-    public void cancel() {
-        mVCardParserImpl.cancel();
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/vcard/VCardSourceDetector.java b/src/com/android/vcard/VCardSourceDetector.java
deleted file mode 100644
index c3e8ca8..0000000
--- a/src/com/android/vcard/VCardSourceDetector.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * <p>
- * The class which tries to detects the source of a vCard file from its contents.
- * </p>
- * <p>
- * The specification of vCard (including both 2.1 and 3.0) is not so strict as to
- * guess its format just by reading beginning few lines (usually we can, but in
- * some most pessimistic case, we cannot until at almost the end of the file).
- * Also we cannot store all vCard entries in memory, while there's no specification
- * how big the vCard entry would become after the parse.
- * </p>
- * <p>
- * This class is usually used for the "first scan", in which we can understand which vCard
- * version is used (and how many entries exist in a file).
- * </p>
- */
-public class VCardSourceDetector implements VCardInterpreter {
-    private static final String LOG_TAG = "VCardSourceDetector";
-
-    private static Set<String> APPLE_SIGNS = new HashSet<String>(Arrays.asList(
-            "X-PHONETIC-FIRST-NAME", "X-PHONETIC-MIDDLE-NAME", "X-PHONETIC-LAST-NAME",
-            "X-ABADR", "X-ABUID"));
-    
-    private static Set<String> JAPANESE_MOBILE_PHONE_SIGNS = new HashSet<String>(Arrays.asList(
-            "X-GNO", "X-GN", "X-REDUCTION"));
-    
-    private static Set<String> WINDOWS_MOBILE_PHONE_SIGNS = new HashSet<String>(Arrays.asList(
-            "X-MICROSOFT-ASST_TEL", "X-MICROSOFT-ASSISTANT", "X-MICROSOFT-OFFICELOC"));
-    
-    // Note: these signes appears before the signs of the other type (e.g. "X-GN").
-    // In other words, Japanese FOMA mobile phones are detected as FOMA, not JAPANESE_MOBILE_PHONES.
-    private static Set<String> FOMA_SIGNS = new HashSet<String>(Arrays.asList(
-            "X-SD-VERN", "X-SD-FORMAT_VER", "X-SD-CATEGORIES", "X-SD-CLASS", "X-SD-DCREATED",
-            "X-SD-DESCRIPTION"));
-    private static String TYPE_FOMA_CHARSET_SIGN = "X-SD-CHAR_CODE";
-
-    /**
-     * Represents that no estimation is available. Users of this class is able to this
-     * constant when you don't want to let a vCard parser rely on estimation for parse type.
-     */
-    public static final int PARSE_TYPE_UNKNOWN = 0;
-
-    // For Apple's software, which does not mean this type is effective for all its products.
-    // We confirmed they usually use UTF-8, but not sure about vCard type.
-    private static final int PARSE_TYPE_APPLE = 1;
-    // For Japanese mobile phones, which are usually using Shift_JIS as a charset.
-    private static final int PARSE_TYPE_MOBILE_PHONE_JP = 2;
-    // For some of mobile phones released from DoCoMo, which use nested vCard. 
-    private static final int PARSE_TYPE_DOCOMO_TORELATE_NEST = 3;
-    // For Japanese Windows Mobel phones. It's version is supposed to be 6.5.
-    private static final int PARSE_TYPE_WINDOWS_MOBILE_V65_JP = 4;
-
-    private int mParseType = 0;  // Not sure.
-
-    private boolean mNeedToParseVersion = false;
-    private int mVersion = -1;  // -1 == unknown
-
-    // Some mobile phones (like FOMA) tells us the charset of the data.
-    private boolean mNeedToParseCharset;
-    private String mSpecifiedCharset;
-    
-    public void start() {
-    }
-    
-    public void end() {
-    }
-
-    public void startEntry() {
-    }    
-
-    public void startProperty() {
-        mNeedToParseCharset = false;
-        mNeedToParseVersion = false;
-    }
-    
-    public void endProperty() {
-    }
-
-    public void endEntry() {
-    }
-
-    public void propertyGroup(String group) {
-    }
-    
-    public void propertyName(String name) {
-        if (name.equalsIgnoreCase(VCardConstants.PROPERTY_VERSION)) {
-            mNeedToParseVersion = true;
-            return;
-        } else if (name.equalsIgnoreCase(TYPE_FOMA_CHARSET_SIGN)) {
-            mParseType = PARSE_TYPE_DOCOMO_TORELATE_NEST;
-            // Probably Shift_JIS is used, but we should double confirm.
-            mNeedToParseCharset = true;
-            return;
-        }
-        if (mParseType != PARSE_TYPE_UNKNOWN) {
-            return;
-        }
-        if (WINDOWS_MOBILE_PHONE_SIGNS.contains(name)) {
-            mParseType = PARSE_TYPE_WINDOWS_MOBILE_V65_JP;
-        } else if (FOMA_SIGNS.contains(name)) {
-            mParseType = PARSE_TYPE_DOCOMO_TORELATE_NEST;
-        } else if (JAPANESE_MOBILE_PHONE_SIGNS.contains(name)) {
-            mParseType = PARSE_TYPE_MOBILE_PHONE_JP;
-        } else if (APPLE_SIGNS.contains(name)) {
-            mParseType = PARSE_TYPE_APPLE;
-        }
-    }
-
-    public void propertyParamType(String type) {
-    }
-
-    public void propertyParamValue(String value) {
-    }
-
-    public void propertyValues(List<String> values) {
-        if (mNeedToParseVersion && values.size() > 0) {
-            final String versionString = values.get(0);
-            if (versionString.equals(VCardConstants.VERSION_V21)) {
-                mVersion = VCardConfig.VERSION_21;
-            } else if (versionString.equals(VCardConstants.VERSION_V30)) {
-                mVersion = VCardConfig.VERSION_30;
-            } else if (versionString.equals(VCardConstants.VERSION_V40)) {
-                mVersion = VCardConfig.VERSION_40;
-            } else {
-                Log.w(LOG_TAG, "Invalid version string: " + versionString);
-            }
-        } else if (mNeedToParseCharset && values.size() > 0) {
-            mSpecifiedCharset = values.get(0);
-        }
-    }
-
-    /**
-     * @return The available type can be used with vCard parser. You probably need to
-     * use {{@link #getEstimatedCharset()} to understand the charset to be used.
-     */
-    public int getEstimatedType() {
-        switch (mParseType) {
-            case PARSE_TYPE_DOCOMO_TORELATE_NEST:
-                return VCardConfig.VCARD_TYPE_DOCOMO | VCardConfig.FLAG_TORELATE_NEST;
-            case PARSE_TYPE_MOBILE_PHONE_JP:
-                return VCardConfig.VCARD_TYPE_V21_JAPANESE_MOBILE;
-            case PARSE_TYPE_APPLE:
-            case PARSE_TYPE_WINDOWS_MOBILE_V65_JP:
-            default: {
-                if (mVersion == VCardConfig.VERSION_21) {
-                    return VCardConfig.VCARD_TYPE_V21_GENERIC;
-                } else if (mVersion == VCardConfig.VERSION_30) {
-                    return VCardConfig.VCARD_TYPE_V30_GENERIC;
-                } else if (mVersion == VCardConfig.VERSION_40) {
-                    return VCardConfig.VCARD_TYPE_V40_GENERIC;
-                } else {
-                    return VCardConfig.VCARD_TYPE_UNKNOWN;
-                }
-            }
-        }
-    }
-
-    /**
-     * <p>
-     * Returns charset String guessed from the source's properties.
-     * This method must be called after parsing target file(s).
-     * </p>
-     * @return Charset String. Null is returned if guessing the source fails.
-     */
-    public String getEstimatedCharset() {
-        if (TextUtils.isEmpty(mSpecifiedCharset)) {
-            return mSpecifiedCharset;
-        }
-        switch (mParseType) {
-            case PARSE_TYPE_WINDOWS_MOBILE_V65_JP:
-            case PARSE_TYPE_DOCOMO_TORELATE_NEST:
-            case PARSE_TYPE_MOBILE_PHONE_JP:
-                return "SHIFT_JIS";
-            case PARSE_TYPE_APPLE:
-                return "UTF-8";
-            default:
-                return null;
-        }
-    }
-}
diff --git a/src/com/android/vcard/VCardUtils.java b/src/com/android/vcard/VCardUtils.java
deleted file mode 100644
index a6eba12..0000000
--- a/src/com/android/vcard/VCardUtils.java
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard;
-
-import com.android.vcard.exception.VCardException;
-
-import android.content.ContentProviderOperation;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.telephony.PhoneNumberUtils;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Utilities for VCard handling codes.
- */
-public class VCardUtils {
-    private static final String LOG_TAG = "VCardUtils";
-
-    /**
-     * See org.apache.commons.codec.DecoderException
-     */
-    private static class DecoderException extends Exception {
-        public DecoderException(String pMessage) {
-            super(pMessage);
-        }
-    }
-
-    /**
-     * See org.apache.commons.codec.net.QuotedPrintableCodec
-     */
-    private static class QuotedPrintableCodecPort {
-        private static byte ESCAPE_CHAR = '=';
-        public static final byte[] decodeQuotedPrintable(byte[] bytes)
-                throws DecoderException {
-            if (bytes == null) {
-                return null;
-            }
-            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-            for (int i = 0; i < bytes.length; i++) {
-                int b = bytes[i];
-                if (b == ESCAPE_CHAR) {
-                    try {
-                        int u = Character.digit((char) bytes[++i], 16);
-                        int l = Character.digit((char) bytes[++i], 16);
-                        if (u == -1 || l == -1) {
-                            throw new DecoderException("Invalid quoted-printable encoding");
-                        }
-                        buffer.write((char) ((u << 4) + l));
-                    } catch (ArrayIndexOutOfBoundsException e) {
-                        throw new DecoderException("Invalid quoted-printable encoding");
-                    }
-                } else {
-                    buffer.write(b);
-                }
-            }
-            return buffer.toByteArray();
-        }
-    }
-
-    // Note that not all types are included in this map/set, since, for example, TYPE_HOME_FAX is
-    // converted to two parameter Strings. These only contain some minor fields valid in both
-    // vCard and current (as of 2009-08-07) Contacts structure. 
-    private static final Map<Integer, String> sKnownPhoneTypesMap_ItoS;
-    private static final Set<String> sPhoneTypesUnknownToContactsSet;
-    private static final Map<String, Integer> sKnownPhoneTypeMap_StoI;
-    private static final Map<Integer, String> sKnownImPropNameMap_ItoS;
-    private static final Set<String> sMobilePhoneLabelSet;
-
-    static {
-        sKnownPhoneTypesMap_ItoS = new HashMap<Integer, String>();
-        sKnownPhoneTypeMap_StoI = new HashMap<String, Integer>();
-
-        sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_CAR, VCardConstants.PARAM_TYPE_CAR);
-        sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_CAR, Phone.TYPE_CAR);
-        sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_PAGER, VCardConstants.PARAM_TYPE_PAGER);
-        sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_PAGER, Phone.TYPE_PAGER);
-        sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_ISDN, VCardConstants.PARAM_TYPE_ISDN);
-        sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_ISDN, Phone.TYPE_ISDN);
-        
-        sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_HOME, Phone.TYPE_HOME);
-        sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_WORK, Phone.TYPE_WORK);
-        sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_CELL, Phone.TYPE_MOBILE);
-                
-        sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_OTHER, Phone.TYPE_OTHER);
-        sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_CALLBACK,
-                Phone.TYPE_CALLBACK);
-        sKnownPhoneTypeMap_StoI.put(
-                VCardConstants.PARAM_PHONE_EXTRA_TYPE_COMPANY_MAIN, Phone.TYPE_COMPANY_MAIN);
-        sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_RADIO, Phone.TYPE_RADIO);
-        sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_TTY_TDD,
-                Phone.TYPE_TTY_TDD);
-        sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_ASSISTANT,
-                Phone.TYPE_ASSISTANT);
-
-        sPhoneTypesUnknownToContactsSet = new HashSet<String>();
-        sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_MODEM);
-        sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_MSG);
-        sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_BBS);
-        sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_VIDEO);
-
-        sKnownImPropNameMap_ItoS = new HashMap<Integer, String>();
-        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_AIM, VCardConstants.PROPERTY_X_AIM);
-        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_MSN, VCardConstants.PROPERTY_X_MSN);
-        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_YAHOO, VCardConstants.PROPERTY_X_YAHOO);
-        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_SKYPE, VCardConstants.PROPERTY_X_SKYPE_USERNAME);
-        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_GOOGLE_TALK,
-                VCardConstants.PROPERTY_X_GOOGLE_TALK);
-        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_ICQ, VCardConstants.PROPERTY_X_ICQ);
-        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_JABBER, VCardConstants.PROPERTY_X_JABBER);
-        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_QQ, VCardConstants.PROPERTY_X_QQ);
-        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_NETMEETING, VCardConstants.PROPERTY_X_NETMEETING);
-
-        // \u643A\u5E2F\u96FB\u8A71 = Full-width Hiragana "Keitai-Denwa" (mobile phone)
-        // \u643A\u5E2F = Full-width Hiragana "Keitai" (mobile phone)
-        // \u30B1\u30A4\u30BF\u30A4 = Full-width Katakana "Keitai" (mobile phone)
-        // \uFF79\uFF72\uFF80\uFF72 = Half-width Katakana "Keitai" (mobile phone)
-        sMobilePhoneLabelSet = new HashSet<String>(Arrays.asList(
-                "MOBILE", "\u643A\u5E2F\u96FB\u8A71", "\u643A\u5E2F", "\u30B1\u30A4\u30BF\u30A4",
-                "\uFF79\uFF72\uFF80\uFF72"));
-    }
-
-    public static String getPhoneTypeString(Integer type) {
-        return sKnownPhoneTypesMap_ItoS.get(type);
-    }
-
-    /**
-     * Returns Interger when the given types can be parsed as known type. Returns String object
-     * when not, which should be set to label. 
-     */
-    public static Object getPhoneTypeFromStrings(Collection<String> types,
-            String number) {
-        if (number == null) {
-            number = "";
-        }
-        int type = -1;
-        String label = null;
-        boolean isFax = false;
-        boolean hasPref = false;
-        
-        if (types != null) {
-            for (String typeString : types) {
-                if (typeString == null) {
-                    continue;
-                }
-                typeString = typeString.toUpperCase();
-                if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) {
-                    hasPref = true;
-                } else if (typeString.equals(VCardConstants.PARAM_TYPE_FAX)) {
-                    isFax = true;
-                } else {
-                    if (typeString.startsWith("X-") && type < 0) {
-                        typeString = typeString.substring(2);
-                    }
-                    if (typeString.length() == 0) {
-                        continue;
-                    }
-                    final Integer tmp = sKnownPhoneTypeMap_StoI.get(typeString);
-                    if (tmp != null) {
-                        final int typeCandidate = tmp;
-                        // TYPE_PAGER is prefered when the number contains @ surronded by
-                        // a pager number and a domain name.
-                        // e.g.
-                        // o 1111@domain.com
-                        // x @domain.com
-                        // x 1111@
-                        final int indexOfAt = number.indexOf("@");
-                        if ((typeCandidate == Phone.TYPE_PAGER
-                                && 0 < indexOfAt && indexOfAt < number.length() - 1)
-                                || type < 0
-                                || type == Phone.TYPE_CUSTOM) {
-                            type = tmp;
-                        }
-                    } else if (type < 0) {
-                        type = Phone.TYPE_CUSTOM;
-                        label = typeString;
-                    }
-                }
-            }
-        }
-        if (type < 0) {
-            if (hasPref) {
-                type = Phone.TYPE_MAIN;
-            } else {
-                // default to TYPE_HOME
-                type = Phone.TYPE_HOME;
-            }
-        }
-        if (isFax) {
-            if (type == Phone.TYPE_HOME) {
-                type = Phone.TYPE_FAX_HOME;
-            } else if (type == Phone.TYPE_WORK) {
-                type = Phone.TYPE_FAX_WORK;
-            } else if (type == Phone.TYPE_OTHER) {
-                type = Phone.TYPE_OTHER_FAX;
-            }
-        }
-        if (type == Phone.TYPE_CUSTOM) {
-            return label;
-        } else {
-            return type;
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    public static boolean isMobilePhoneLabel(final String label) {
-        // For backward compatibility.
-        // Detail: Until Donut, there isn't TYPE_MOBILE for email while there is now.
-        //         To support mobile type at that time, this custom label had been used.
-        return ("_AUTO_CELL".equals(label) || sMobilePhoneLabelSet.contains(label));
-    }
-
-    public static boolean isValidInV21ButUnknownToContactsPhoteType(final String label) {
-        return sPhoneTypesUnknownToContactsSet.contains(label);
-    }
-
-    public static String getPropertyNameForIm(final int protocol) {
-        return sKnownImPropNameMap_ItoS.get(protocol);
-    }
-
-    public static String[] sortNameElements(final int vcardType,
-            final String familyName, final String middleName, final String givenName) {
-        final String[] list = new String[3];
-        final int nameOrderType = VCardConfig.getNameOrderType(vcardType);
-        switch (nameOrderType) {
-            case VCardConfig.NAME_ORDER_JAPANESE: {
-                if (containsOnlyPrintableAscii(familyName) &&
-                        containsOnlyPrintableAscii(givenName)) {
-                    list[0] = givenName;
-                    list[1] = middleName;
-                    list[2] = familyName;
-                } else {
-                    list[0] = familyName;
-                    list[1] = middleName;
-                    list[2] = givenName;
-                }
-                break;
-            }
-            case VCardConfig.NAME_ORDER_EUROPE: {
-                list[0] = middleName;
-                list[1] = givenName;
-                list[2] = familyName;
-                break;
-            }
-            default: {
-                list[0] = givenName;
-                list[1] = middleName;
-                list[2] = familyName;
-                break;
-            }
-        }
-        return list;
-    }
-
-    public static int getPhoneNumberFormat(final int vcardType) {
-        if (VCardConfig.isJapaneseDevice(vcardType)) {
-            return PhoneNumberUtils.FORMAT_JAPAN;
-        } else {
-            return PhoneNumberUtils.FORMAT_NANP;
-        }
-    }
-
-    /**
-     * <p>
-     * Inserts postal data into the builder object.
-     * </p>
-     * <p>
-     * Note that the data structure of ContactsContract is different from that defined in vCard.
-     * So some conversion may be performed in this method.
-     * </p>
-     */
-    public static void insertStructuredPostalDataUsingContactsStruct(int vcardType,
-            final ContentProviderOperation.Builder builder,
-            final VCardEntry.PostalData postalData) {
-        builder.withValueBackReference(StructuredPostal.RAW_CONTACT_ID, 0);
-        builder.withValue(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
-
-        builder.withValue(StructuredPostal.TYPE, postalData.type);
-        if (postalData.type == StructuredPostal.TYPE_CUSTOM) {
-            builder.withValue(StructuredPostal.LABEL, postalData.label);
-        }
-
-        final String streetString;
-        if (TextUtils.isEmpty(postalData.street)) {
-            if (TextUtils.isEmpty(postalData.extendedAddress)) {
-                streetString = null;
-            } else {
-                streetString = postalData.extendedAddress;
-            }
-        } else {
-            if (TextUtils.isEmpty(postalData.extendedAddress)) {
-                streetString = postalData.street;
-            } else {
-                streetString = postalData.street + " " + postalData.extendedAddress;
-            }
-        }
-        builder.withValue(StructuredPostal.POBOX, postalData.pobox);
-        builder.withValue(StructuredPostal.STREET, streetString);
-        builder.withValue(StructuredPostal.CITY, postalData.localty);
-        builder.withValue(StructuredPostal.REGION, postalData.region);
-        builder.withValue(StructuredPostal.POSTCODE, postalData.postalCode);
-        builder.withValue(StructuredPostal.COUNTRY, postalData.country);
-
-        builder.withValue(StructuredPostal.FORMATTED_ADDRESS,
-                postalData.getFormattedAddress(vcardType));
-        if (postalData.isPrimary) {
-            builder.withValue(Data.IS_PRIMARY, 1);
-        }
-    }
-
-    public static String constructNameFromElements(final int vcardType,
-            final String familyName, final String middleName, final String givenName) {
-        return constructNameFromElements(vcardType, familyName, middleName, givenName,
-                null, null);
-    }
-
-    public static String constructNameFromElements(final int vcardType,
-            final String familyName, final String middleName, final String givenName,
-            final String prefix, final String suffix) {
-        final StringBuilder builder = new StringBuilder();
-        final String[] nameList = sortNameElements(vcardType, familyName, middleName, givenName);
-        boolean first = true;
-        if (!TextUtils.isEmpty(prefix)) {
-            first = false;
-            builder.append(prefix);
-        }
-        for (final String namePart : nameList) {
-            if (!TextUtils.isEmpty(namePart)) {
-                if (first) {
-                    first = false;
-                } else {
-                    builder.append(' ');
-                }
-                builder.append(namePart);
-            }
-        }
-        if (!TextUtils.isEmpty(suffix)) {
-            if (!first) {
-                builder.append(' ');
-            }
-            builder.append(suffix);
-        }
-        return builder.toString();
-    }
-
-    /**
-     * Splits the given value into pieces using the delimiter ';' inside it.
-     *
-     * Escaped characters in those values are automatically unescaped into original form.
-     */
-    public static List<String> constructListFromValue(final String value,
-            final int vcardType) {
-        final List<String> list = new ArrayList<String>();
-        StringBuilder builder = new StringBuilder();
-        final int length = value.length();
-        for (int i = 0; i < length; i++) {
-            char ch = value.charAt(i);
-            if (ch == '\\' && i < length - 1) {
-                char nextCh = value.charAt(i + 1);
-                final String unescapedString;
-                if (VCardConfig.isVersion40(vcardType)) {
-                    unescapedString = VCardParserImpl_V40.unescapeCharacter(nextCh);
-                } else if (VCardConfig.isVersion30(vcardType)) {
-                    unescapedString = VCardParserImpl_V30.unescapeCharacter(nextCh);
-                } else {
-                    if (!VCardConfig.isVersion21(vcardType)) {
-                        // Unknown vCard type
-                        Log.w(LOG_TAG, "Unknown vCard type");
-                    }
-                    unescapedString = VCardParserImpl_V21.unescapeCharacter(nextCh);
-                }
-
-                if (unescapedString != null) {
-                    builder.append(unescapedString);
-                    i++;
-                } else {
-                    builder.append(ch);
-                }
-            } else if (ch == ';') {
-                list.add(builder.toString());
-                builder = new StringBuilder();
-            } else {
-                builder.append(ch);
-            }
-        }
-        list.add(builder.toString());
-        return list;
-    }
-
-    public static boolean containsOnlyPrintableAscii(final String...values) {
-        if (values == null) {
-            return true;
-        }
-        return containsOnlyPrintableAscii(Arrays.asList(values));
-    }
-
-    public static boolean containsOnlyPrintableAscii(final Collection<String> values) {
-        if (values == null) {
-            return true;
-        }
-        for (final String value : values) {
-            if (TextUtils.isEmpty(value)) {
-                continue;
-            }
-            if (!TextUtils.isPrintableAsciiOnly(value)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * <p>
-     * This is useful when checking the string should be encoded into quoted-printable
-     * or not, which is required by vCard 2.1.
-     * </p>
-     * <p>
-     * See the definition of "7bit" in vCard 2.1 spec for more information.
-     * </p>
-     */
-    public static boolean containsOnlyNonCrLfPrintableAscii(final String...values) {
-        if (values == null) {
-            return true;
-        }
-        return containsOnlyNonCrLfPrintableAscii(Arrays.asList(values));
-    }
-
-    public static boolean containsOnlyNonCrLfPrintableAscii(final Collection<String> values) {
-        if (values == null) {
-            return true;
-        }
-        final int asciiFirst = 0x20;
-        final int asciiLast = 0x7E;  // included
-        for (final String value : values) {
-            if (TextUtils.isEmpty(value)) {
-                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>
-     * This is useful since vCard 3.0 often requires the ("X-") properties and groups
-     * should contain only alphabets, digits, and hyphen.
-     * </p>
-     * <p> 
-     * 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.
-     * </p>
-     */
-    public static boolean containsOnlyAlphaDigitHyphen(final String...values) {
-        if (values == null) {
-            return true;
-        }
-        return containsOnlyAlphaDigitHyphen(Arrays.asList(values));
-    }
-
-    public static boolean containsOnlyAlphaDigitHyphen(final Collection<String> values) {
-        if (values == null) {
-            return true;
-        }
-        final int upperAlphabetFirst = 0x41;  // A
-        final int upperAlphabetAfterLast = 0x5b;  // [
-        final int lowerAlphabetFirst = 0x61;  // a
-        final int lowerAlphabetAfterLast = 0x7b;  // {
-        final int digitFirst = 0x30;  // 0
-        final int digitAfterLast = 0x3A;  // :
-        final int hyphen = '-';
-        for (final String str : values) {
-            if (TextUtils.isEmpty(str)) {
-                continue;
-            }
-            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) ||
-                    (digitFirst <= codepoint && codepoint < digitAfterLast) ||
-                    (codepoint == hyphen))) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    public static boolean containsOnlyWhiteSpaces(final String...values) {
-        if (values == null) {
-            return true;
-        }
-        return containsOnlyWhiteSpaces(Arrays.asList(values));
-    }
-
-    public static boolean containsOnlyWhiteSpaces(final Collection<String> values) {
-        if (values == null) {
-            return true;
-        }
-        for (final String str : values) {
-            if (TextUtils.isEmpty(str)) {
-                continue;
-            }
-            final int length = str.length();
-            for (int i = 0; i < length; i = str.offsetByCodePoints(i, 1)) {
-                if (!Character.isWhitespace(str.codePointAt(i))) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    /**
-     * <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 true;
-    }
-
-    private static final int[] sEscapeIndicatorsV30 = new int[]{
-        ':', ';', ',', ' '
-    };
-
-    private static final int[] sEscapeIndicatorsV40 = new int[]{
-        ';', ':'
-    };
-
-    /**
-     * <P>
-     * Returns String available as parameter value in vCard 3.0.
-     * </P>
-     * <P>
-     * RFC 2426 requires vCard composer to quote parameter values when it contains
-     * semi-colon, for example (See RFC 2426 for more information).
-     * This method checks whether the given String can be used without quotes.
-     * </P>
-     * <P>
-     * Note: We remove DQUOTE inside the given value silently for now.
-     * </P>
-     */
-    public static String toStringAsV30ParamValue(String value) {
-        return toStringAsParamValue(value, sEscapeIndicatorsV30);
-    }
-
-    public static String toStringAsV40ParamValue(String value) {
-        return toStringAsParamValue(value, sEscapeIndicatorsV40);
-    }
-
-    private static String toStringAsParamValue(String value, final int[] escapeIndicators) {
-        if (TextUtils.isEmpty(value)) {
-            value = "";
-        }
-        final int asciiFirst = 0x20;
-        final int asciiLast = 0x7E;  // included
-        final StringBuilder builder = new StringBuilder();
-        final int length = value.length();
-        boolean needQuote = false;
-        for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) {
-            final int codePoint = value.codePointAt(i);
-            if (codePoint < asciiFirst || codePoint == '"') {
-                // CTL characters and DQUOTE are never accepted. Remove them.
-                continue;
-            }
-            builder.appendCodePoint(codePoint);
-            for (int indicator : escapeIndicators) {
-                if (codePoint == indicator) {
-                    needQuote = true;
-                    break;
-                }
-            }
-        }
-
-        final String result = builder.toString();
-        return ((result.isEmpty() || VCardUtils.containsOnlyWhiteSpaces(result))
-                ? ""
-                : (needQuote ? ('"' + result + '"')
-                : result));
-    }
-
-    public static String toHalfWidthString(final String orgString) {
-        if (TextUtils.isEmpty(orgString)) {
-            return null;
-        }
-        final StringBuilder builder = new StringBuilder();
-        final int length = orgString.length();
-        for (int i = 0; i < length; i = orgString.offsetByCodePoints(i, 1)) {
-            // All Japanese character is able to be expressed by char.
-            // Do not need to use String#codepPointAt().
-            final char ch = orgString.charAt(i);
-            final String halfWidthText = JapaneseUtils.tryGetHalfWidthText(ch);
-            if (halfWidthText != null) {
-                builder.append(halfWidthText);
-            } else {
-                builder.append(ch);
-            }
-        }
-        return builder.toString();
-    }
-
-    /**
-     * Guesses the format of input image. Currently just the first few bytes are used.
-     * The type "GIF", "PNG", or "JPEG" is returned when possible. Returns null when
-     * the guess failed.
-     * @param input Image as byte array.
-     * @return The image type or null when the type cannot be determined.
-     */
-    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') {
-            return "GIF";
-        } else if (input.length >= 4 && input[0] == (byte) 0x89
-                && input[1] == 'P' && input[2] == 'N' && input[3] == 'G') {
-            // Note: vCard 2.1 officially does not support PNG, but we may have it and
-            //       using X- word like "X-PNG" may not let importers know it is PNG.
-            //       So we use the String "PNG" as is...
-            return "PNG";
-        } else if (input.length >= 2 && input[0] == (byte) 0xff
-                && input[1] == (byte) 0xd8) {
-            return "JPEG";
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * @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;
-    }
-
-    //// The methods bellow may be used by unit test.
-
-    /**
-     * Unquotes given Quoted-Printable value. value must not be null.
-     */
-    public static String parseQuotedPrintable(
-            final String value, boolean strictLineBreaking,
-            String sourceCharset, String targetCharset) {
-        // "= " -> " ", "=\t" -> "\t".
-        // Previous code had done this replacement. Keep on the safe side.
-        final String quotedPrintable;
-        {
-            final StringBuilder builder = new StringBuilder();
-            final int length = value.length();
-            for (int i = 0; i < length; i++) {
-                char ch = value.charAt(i);
-                if (ch == '=' && i < length - 1) {
-                    char nextCh = value.charAt(i + 1);
-                    if (nextCh == ' ' || nextCh == '\t') {
-                        builder.append(nextCh);
-                        i++;
-                        continue;
-                    }
-                }
-                builder.append(ch);
-            }
-            quotedPrintable = builder.toString();
-        }
-
-        String[] lines;
-        if (strictLineBreaking) {
-            lines = quotedPrintable.split("\r\n");
-        } else {
-            StringBuilder builder = new StringBuilder();
-            final int length = quotedPrintable.length();
-            ArrayList<String> list = new ArrayList<String>();
-            for (int i = 0; i < length; i++) {
-                char ch = quotedPrintable.charAt(i);
-                if (ch == '\n') {
-                    list.add(builder.toString());
-                    builder = new StringBuilder();
-                } else if (ch == '\r') {
-                    list.add(builder.toString());
-                    builder = new StringBuilder();
-                    if (i < length - 1) {
-                        char nextCh = quotedPrintable.charAt(i + 1);
-                        if (nextCh == '\n') {
-                            i++;
-                        }
-                    }
-                } else {
-                    builder.append(ch);
-                }
-            }
-            final String lastLine = builder.toString();
-            if (lastLine.length() > 0) {
-                list.add(lastLine);
-            }
-            lines = list.toArray(new String[0]);
-        }
-
-        final StringBuilder builder = new StringBuilder();
-        for (String line : lines) {
-            if (line.endsWith("=")) {
-                line = line.substring(0, line.length() - 1);
-            }
-            builder.append(line);
-        }
-
-        final String rawString = builder.toString();
-        if (TextUtils.isEmpty(rawString)) {
-            Log.w(LOG_TAG, "Given raw string is empty.");
-        }
-
-        byte[] rawBytes = null;
-        try {
-            rawBytes = rawString.getBytes(sourceCharset); 
-        } catch (UnsupportedEncodingException e) {
-            Log.w(LOG_TAG, "Failed to decode: " + sourceCharset);
-            rawBytes = rawString.getBytes();
-        }
-
-        byte[] decodedBytes = null;
-        try {
-            decodedBytes = QuotedPrintableCodecPort.decodeQuotedPrintable(rawBytes);
-        } catch (DecoderException e) {
-            Log.e(LOG_TAG, "DecoderException is thrown.");
-            decodedBytes = rawBytes;
-        }
-
-        try {
-            return new String(decodedBytes, targetCharset);
-        } catch (UnsupportedEncodingException e) {
-            Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
-            return new String(decodedBytes);
-        }
-    }
-
-    public static final VCardParser getAppropriateParser(int vcardType)
-            throws VCardException {
-        if (VCardConfig.isVersion21(vcardType)) {
-            return new VCardParser_V21();
-        } else if (VCardConfig.isVersion30(vcardType)) {
-            return new VCardParser_V30();
-        } else if (VCardConfig.isVersion40(vcardType)) {
-            return new VCardParser_V40();
-        } else {
-            throw new VCardException("Version is not specified");
-        }
-    }
-
-    public static final String convertStringCharset(
-            String originalString, String sourceCharset, String targetCharset) {
-        if (sourceCharset.equalsIgnoreCase(targetCharset)) {
-            return originalString;
-        }
-        final Charset charset = Charset.forName(sourceCharset);
-        final ByteBuffer byteBuffer = charset.encode(originalString);
-        // byteBuffer.array() "may" return byte array which is larger than
-        // byteBuffer.remaining(). Here, we keep on the safe side.
-        final byte[] bytes = new byte[byteBuffer.remaining()];
-        byteBuffer.get(bytes);
-        try {
-            return new String(bytes, targetCharset);
-        } catch (UnsupportedEncodingException e) {
-            Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
-            return null;
-        }
-    }
-
-    // TODO: utilities for vCard 4.0: datetime, timestamp, integer, float, and boolean
-
-    private VCardUtils() {
-    }
-}
diff --git a/src/com/android/vcard/exception/VCardAgentNotSupportedException.java b/src/com/android/vcard/exception/VCardAgentNotSupportedException.java
deleted file mode 100644
index c408716..0000000
--- a/src/com/android/vcard/exception/VCardAgentNotSupportedException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard.exception;
-
-public class VCardAgentNotSupportedException extends VCardNotSupportedException {
-    public VCardAgentNotSupportedException() {
-        super();
-    }
-
-    public VCardAgentNotSupportedException(String message) {
-        super(message);
-    }
-
-}
\ No newline at end of file
diff --git a/src/com/android/vcard/exception/VCardException.java b/src/com/android/vcard/exception/VCardException.java
deleted file mode 100644
index 3ad7fd3..0000000
--- a/src/com/android/vcard/exception/VCardException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard.exception;
-
-public class VCardException extends java.lang.Exception {
-    /**
-     * Constructs a VCardException object
-     */
-    public VCardException() {
-        super();
-    }
-
-    /**
-     * Constructs a VCardException object
-     *
-     * @param message the error message
-     */
-    public VCardException(String message) {
-        super(message);
-    }
-
-}
diff --git a/src/com/android/vcard/exception/VCardInvalidCommentLineException.java b/src/com/android/vcard/exception/VCardInvalidCommentLineException.java
deleted file mode 100644
index 342769e..0000000
--- a/src/com/android/vcard/exception/VCardInvalidCommentLineException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.vcard.exception;
-
-/**
- * Thrown when the vCard has some line starting with '#'. In the specification,
- * both vCard 2.1 and vCard 3.0 does not allow such line, but some actual exporter emit
- * such lines.
- */
-public class VCardInvalidCommentLineException extends VCardInvalidLineException {
-    public VCardInvalidCommentLineException() {
-        super();
-    }
-
-    public VCardInvalidCommentLineException(final String message) {
-        super(message);
-    }
-}
diff --git a/src/com/android/vcard/exception/VCardInvalidLineException.java b/src/com/android/vcard/exception/VCardInvalidLineException.java
deleted file mode 100644
index 5c2250f..0000000
--- a/src/com/android/vcard/exception/VCardInvalidLineException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard.exception;
-
-/**
- * Thrown when the vCard has some line starting with '#'. In the specification,
- * both vCard 2.1 and vCard 3.0 does not allow such line, but some actual exporter emit
- * such lines.
- */
-public class VCardInvalidLineException extends VCardException {
-    public VCardInvalidLineException() {
-        super();
-    }
-
-    public VCardInvalidLineException(final String message) {
-        super(message);
-    }
-}
diff --git a/src/com/android/vcard/exception/VCardNestedException.java b/src/com/android/vcard/exception/VCardNestedException.java
deleted file mode 100644
index 2b9b1ac..0000000
--- a/src/com/android/vcard/exception/VCardNestedException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.vcard.exception;
-
-/**
- * VCardException thrown when VCard is nested without VCardParser's being notified.
- */
-public class VCardNestedException extends VCardNotSupportedException {
-    public VCardNestedException() {
-        super();
-    }
-    public VCardNestedException(String message) {
-        super(message);
-    }
-}
diff --git a/src/com/android/vcard/exception/VCardNotSupportedException.java b/src/com/android/vcard/exception/VCardNotSupportedException.java
deleted file mode 100644
index 61ff752..0000000
--- a/src/com/android/vcard/exception/VCardNotSupportedException.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard.exception;
-
-/**
- * The exception which tells that the input VCard is probably valid from the view of
- * specification but not supported in the current framework for now.
- * 
- * This is a kind of a good news from the view of development.
- * It may be good to ask users to send a report with the VCard example
- * for the future development.
- */
-public class VCardNotSupportedException extends VCardException {
-    public VCardNotSupportedException() {
-        super();
-    }
-    public VCardNotSupportedException(String message) {
-        super(message);
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/vcard/exception/VCardVersionException.java b/src/com/android/vcard/exception/VCardVersionException.java
deleted file mode 100644
index 047c580..0000000
--- a/src/com/android/vcard/exception/VCardVersionException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.vcard.exception;
-
-/**
- * VCardException used only when the version of the vCard is different. 
- */
-public class VCardVersionException extends VCardException {
-    public VCardVersionException() {
-        super();
-    }
-    public VCardVersionException(String message) {
-        super(message);
-    }
-}