am 9e807d7c: Merge change Iecf85b40 into eclair-mr2

Merge commit '9e807d7cc4e5deafc0744abd932e2b40e3f5e80b' into eclair-mr2-plus-aosp

* commit '9e807d7cc4e5deafc0744abd932e2b40e3f5e80b':
  Rename several files so that readers would not be confused.
This commit is contained in:
Daisuke Miyakawa
2009-11-16 14:36:17 -08:00
committed by Android Git Automerger
20 changed files with 969 additions and 713 deletions

View File

@@ -83,18 +83,6 @@ package android.pim.vcard;
public static final String PARAM_TYPE = "TYPE"; public static final String PARAM_TYPE = "TYPE";
// How more than one TYPE fields are expressed is different between vCard 2.1 and vCard 3.0
//
// e.g.
// 1) Probably valid in both vCard 2.1 and vCard 3.0: "ADR;TYPE=DOM;TYPE=HOME:..."
// 2) Valid in vCard 2.1 but not in vCard 3.0: "ADR;DOM;HOME:..."
// 3) Valid in vCard 3.0 but not in vCard 2.1: "ADR;TYPE=DOM,HOME:..."
//
// 2) has been the default of VCard exporter/importer in Android, but we can see the other
// formats in vCard data emitted by the other softwares/devices.
//
// So we are currently not sure which type is the best; probably we will have to change which
// type should be emitted depending on the device.
public static final String PARAM_TYPE_HOME = "HOME"; public static final String PARAM_TYPE_HOME = "HOME";
public static final String PARAM_TYPE_WORK = "WORK"; public static final String PARAM_TYPE_WORK = "WORK";
public static final String PARAM_TYPE_FAX = "FAX"; public static final String PARAM_TYPE_FAX = "FAX";
@@ -117,7 +105,6 @@ package android.pim.vcard;
public static final String PARAM_TYPE_TLX = "TLX"; // Telex public static final String PARAM_TYPE_TLX = "TLX"; // Telex
// Phone types existing in vCard 2.1 but not known to ContactsContract. // Phone types existing in vCard 2.1 but not known to ContactsContract.
// TODO: should make parser make these TYPE_CUSTOM.
public static final String PARAM_TYPE_MODEM = "MODEM"; public static final String PARAM_TYPE_MODEM = "MODEM";
public static final String PARAM_TYPE_MSG = "MSG"; public static final String PARAM_TYPE_MSG = "MSG";
public static final String PARAM_TYPE_BBS = "BBS"; public static final String PARAM_TYPE_BBS = "BBS";
@@ -156,9 +143,11 @@ package android.pim.vcard;
public static final String PROPERTY_X_GOOGLE_TALK_WITH_SPACE = "X-GOOGLE TALK"; public static final String PROPERTY_X_GOOGLE_TALK_WITH_SPACE = "X-GOOGLE TALK";
} }
// TODO: Should be in ContactsContract?
/* package */ static final int MAX_DATA_COLUMN = 15; /* package */ 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 Constants() { private Constants() {
} }
} }

View File

@@ -0,0 +1,380 @@
/*
* 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 android.pim.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 {
// There's no logical mapping rule in Unicode. Sigh.
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");
}
/**
* Return half-width version of that character if possible. Return null if not possible
* @param ch input character
* @return CharSequence object if the mapping for ch exists. Return null otherwise.
*/
public static CharSequence tryGetHalfWidthText(char ch) {
if (sHalfWidthMap.containsKey(ch)) {
return sHalfWidthMap.get(ch);
} else {
return null;
}
}
}

View File

@@ -196,7 +196,7 @@ public class VCardComposer {
* An useful example handler, which emits VCard String to outputstream one by one. * An useful example handler, which emits VCard String to outputstream one by one.
* </p> * </p>
* <p> * <p>
* The input OutputStream object is closed() on {{@link #onTerminate()}. * The input OutputStream object is closed() on {@link #onTerminate()}.
* Must not close the stream outside. * Must not close the stream outside.
* </p> * </p>
*/ */
@@ -353,7 +353,8 @@ public class VCardComposer {
/** /**
* Construct for supporting call log entry vCard composing. * Construct for supporting call log entry vCard composing.
*/ */
public VCardComposer(Context context, int vcardType, boolean careHandlerErrors) { public VCardComposer(final Context context, final int vcardType,
final boolean careHandlerErrors) {
mContext = context; mContext = context;
mVCardType = vcardType; mVCardType = vcardType;
mCareHandlerErrors = careHandlerErrors; mCareHandlerErrors = careHandlerErrors;
@@ -403,7 +404,7 @@ public class VCardComposer {
} }
/** /**
* Must call before {{@link #init()}. * Must be called before {@link #init()}.
*/ */
public void addHandler(OneEntryHandler handler) { public void addHandler(OneEntryHandler handler) {
if (handler != null) { if (handler != null) {
@@ -510,8 +511,7 @@ public class VCardComposer {
} catch (OutOfMemoryError error) { } catch (OutOfMemoryError error) {
// Maybe some data (e.g. photo) is too big to have in memory. But it // Maybe some data (e.g. photo) is too big to have in memory. But it
// should be rare. // should be rare.
Log.e(LOG_TAG, "OutOfMemoryError occured. Ignore the entry: " Log.e(LOG_TAG, "OutOfMemoryError occured. Ignore the entry: " + name);
+ name);
System.gc(); System.gc();
// TODO: should tell users what happened? // TODO: should tell users what happened?
return true; return true;
@@ -676,7 +676,7 @@ public class VCardComposer {
} }
} }
private boolean containsNonEmptyName(ContentValues contentValues) { private boolean containsNonEmptyName(final ContentValues contentValues) {
final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME); final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME);
final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME); final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME);
final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME); final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME);
@@ -715,7 +715,7 @@ public class VCardComposer {
} else if (primaryContentValues == null) { } else if (primaryContentValues == null) {
// We choose the first "primary" ContentValues // We choose the first "primary" ContentValues
// if "super primary" ContentValues does not exist. // if "super primary" ContentValues does not exist.
Integer isPrimary = contentValues.getAsInteger(StructuredName.IS_PRIMARY); final Integer isPrimary = contentValues.getAsInteger(StructuredName.IS_PRIMARY);
if (isPrimary != null && isPrimary > 0 && if (isPrimary != null && isPrimary > 0 &&
containsNonEmptyName(contentValues)) { containsNonEmptyName(contentValues)) {
primaryContentValues = contentValues; primaryContentValues = contentValues;
@@ -897,11 +897,11 @@ public class VCardComposer {
final String phoneticMiddleName; final String phoneticMiddleName;
final String phoneticGivenName; final String phoneticGivenName;
{ {
String tmpPhoneticFamilyName = final String tmpPhoneticFamilyName =
primaryContentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME); primaryContentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
String tmpPhoneticMiddleName = final String tmpPhoneticMiddleName =
primaryContentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME); primaryContentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
String tmpPhoneticGivenName = final String tmpPhoneticGivenName =
primaryContentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME); primaryContentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
if (mNeedsToConvertPhoneticString) { if (mNeedsToConvertPhoneticString) {
phoneticFamilyName = VCardUtils.toHalfWidthString(tmpPhoneticFamilyName); phoneticFamilyName = VCardUtils.toHalfWidthString(tmpPhoneticFamilyName);
@@ -913,10 +913,11 @@ public class VCardComposer {
phoneticGivenName = tmpPhoneticGivenName; phoneticGivenName = tmpPhoneticGivenName;
} }
} }
if (!(TextUtils.isEmpty(phoneticFamilyName) if (!(TextUtils.isEmpty(phoneticFamilyName)
&& TextUtils.isEmpty(phoneticMiddleName) && TextUtils.isEmpty(phoneticMiddleName)
&& TextUtils.isEmpty(phoneticGivenName))) { && TextUtils.isEmpty(phoneticGivenName))) {
// Try to emit the field(s) related to phonetic name.
if (mIsV30) { if (mIsV30) {
final String sortString = VCardUtils final String sortString = VCardUtils
.constructNameFromElements(mVCardType, .constructNameFromElements(mVCardType,
@@ -937,6 +938,12 @@ public class VCardComposer {
// since it is supported by // since it is supported by
// a lot of Japanese mobile phones. This is "X-" property, so // a lot of Japanese mobile phones. This is "X-" property, so
// any parser hopefully would not get confused with this. // any parser hopefully would not get confused with this.
//
// Also, DoCoMo's specification requires vCard composer to use just the first
// column.
// i.e.
// o SOUND;X-IRMC-N:Miyakawa Daisuke;;;;
// x SOUND;X-IRMC-N:Miyakawa;Daisuke;;;
builder.append(Constants.PROPERTY_SOUND); builder.append(Constants.PROPERTY_SOUND);
builder.append(VCARD_PARAM_SEPARATOR); builder.append(VCARD_PARAM_SEPARATOR);
builder.append(Constants.PARAM_TYPE_X_IRMC_N); builder.append(Constants.PARAM_TYPE_X_IRMC_N);
@@ -970,8 +977,6 @@ public class VCardComposer {
builder.append(mVCardCharsetParameter); builder.append(mVCardCharsetParameter);
} }
builder.append(VCARD_DATA_SEPARATOR); builder.append(VCARD_DATA_SEPARATOR);
// DoCoMo's specification requires vCard composer to use just the first
// column.
{ {
boolean first = true; boolean first = true;
if (!TextUtils.isEmpty(encodedPhoneticFamilyName)) { if (!TextUtils.isEmpty(encodedPhoneticFamilyName)) {
@@ -999,16 +1004,18 @@ public class VCardComposer {
builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_ITEM_SEPARATOR);
builder.append(VCARD_END_OF_LINE); builder.append(VCARD_END_OF_LINE);
} }
} else if (mIsDoCoMo) { } else { // If phonetic name fields are all empty
builder.append(Constants.PROPERTY_SOUND); if (mIsDoCoMo) {
builder.append(VCARD_PARAM_SEPARATOR); builder.append(Constants.PROPERTY_SOUND);
builder.append(Constants.PARAM_TYPE_X_IRMC_N); builder.append(VCARD_PARAM_SEPARATOR);
builder.append(VCARD_DATA_SEPARATOR); builder.append(Constants.PARAM_TYPE_X_IRMC_N);
builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_DATA_SEPARATOR);
builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_ITEM_SEPARATOR);
builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_ITEM_SEPARATOR);
builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_ITEM_SEPARATOR);
builder.append(VCARD_END_OF_LINE); builder.append(VCARD_ITEM_SEPARATOR);
builder.append(VCARD_END_OF_LINE);
}
} }
if (mUsesDefactProperty) { if (mUsesDefactProperty) {
@@ -1252,48 +1259,50 @@ public class VCardComposer {
} }
} }
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 * Tries to append just one line. If there's no appropriate address
* information, append an empty line. * information, append an empty line.
*/ */
private void appendPostalsForDoCoMo(final StringBuilder builder, private void appendPostalsForDoCoMo(final StringBuilder builder,
final List<ContentValues> contentValuesList) { final List<ContentValues> contentValuesList) {
// TODO: from old, inefficient code. fix this. int currentPriority = Integer.MAX_VALUE;
if (appendPostalsForDoCoMoInternal(builder, contentValuesList, int currentType = Integer.MAX_VALUE;
StructuredPostal.TYPE_HOME)) { ContentValues currentContentValues = null;
return;
}
if (appendPostalsForDoCoMoInternal(builder, contentValuesList,
StructuredPostal.TYPE_WORK)) {
return;
}
if (appendPostalsForDoCoMoInternal(builder, contentValuesList,
StructuredPostal.TYPE_OTHER)) {
return;
}
if (appendPostalsForDoCoMoInternal(builder, contentValuesList,
StructuredPostal.TYPE_CUSTOM)) {
return;
}
Log.w(LOG_TAG,
"Should not come here. Must have at least one postal data.");
}
private boolean appendPostalsForDoCoMoInternal(final StringBuilder builder,
final List<ContentValues> contentValuesList, Integer preferedType) {
for (ContentValues contentValues : contentValuesList) { for (ContentValues contentValues : contentValuesList) {
final Integer type = contentValues.getAsInteger(StructuredPostal.TYPE); if (contentValues == null) {
final String label = contentValues.getAsString(StructuredPostal.LABEL); continue;
if (type == preferedType) { }
// Note: Not sure why we need to emit "empty" line even when actual final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE);
// data does not exist. There may be some reason or may not. final Integer priorityAsInteger = sPostalTypePriorityMap.get(typeAsInteger);
// We keep safer side since the previous implementation did so. final int priority =
appendVCardPostalLine(builder, type, label, contentValues, true, true); (priorityAsInteger != null ? priorityAsInteger : Integer.MAX_VALUE);
return true; if (priority < currentPriority) {
currentPriority = priority;
currentType = typeAsInteger;
currentContentValues = contentValues;
if (priority == 0) {
break;
}
} }
} }
return false;
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);
appendVCardPostalLine(builder, currentType, label, currentContentValues, false, true);
} }
private void appendPostalsForGeneric(final StringBuilder builder, private void appendPostalsForGeneric(final StringBuilder builder,
@@ -1302,9 +1311,9 @@ public class VCardComposer {
if (contentValues == null) { if (contentValues == null) {
continue; continue;
} }
final Integer typeAsObject = contentValues.getAsInteger(StructuredPostal.TYPE); final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE);
final int type = (typeAsObject != null ? final int type = (typeAsInteger != null ?
typeAsObject : DEFAULT_POSTAL_TYPE); typeAsInteger : DEFAULT_POSTAL_TYPE);
final String label = contentValues.getAsString(StructuredPostal.LABEL); final String label = contentValues.getAsString(StructuredPostal.LABEL);
final Integer isPrimaryAsInteger = final Integer isPrimaryAsInteger =
contentValues.getAsInteger(StructuredPostal.IS_PRIMARY); contentValues.getAsInteger(StructuredPostal.IS_PRIMARY);
@@ -1525,9 +1534,9 @@ public class VCardComposer {
photoType = "GIF"; photoType = "GIF";
} else if (data.length >= 4 && data[0] == (byte) 0x89 } else if (data.length >= 4 && data[0] == (byte) 0x89
&& data[1] == 'P' && data[2] == 'N' && data[3] == 'G') { && data[1] == 'P' && data[2] == 'N' && data[3] == 'G') {
// Note: vCard 2.1 officially does not support PNG, but we may // Note: vCard 2.1 officially does not support PNG, but we may have it and
// have it and using X- word like "X-PNG" may not let importers // using X- word like "X-PNG" may not let importers know it is PNG.
// know it is PNG. So we use the String "PNG" as is... // So we use the String "PNG" as is...
photoType = "PNG"; photoType = "PNG";
} else if (data.length >= 2 && data[0] == (byte) 0xff } else if (data.length >= 2 && data[0] == (byte) 0xff
&& data[1] == (byte) 0xd8) { && data[1] == (byte) 0xd8) {
@@ -1851,7 +1860,7 @@ public class VCardComposer {
break; break;
} }
case StructuredPostal.TYPE_CUSTOM: { case StructuredPostal.TYPE_CUSTOM: {
if (mUsesAndroidProperty && !TextUtils.isEmpty(label) if (!TextUtils.isEmpty(label)
&& VCardUtils.containsOnlyAlphaDigitHyphen(label)) { && VCardUtils.containsOnlyAlphaDigitHyphen(label)) {
// We're not sure whether the label is valid in the spec // We're not sure whether the label is valid in the spec
// ("IANA-token" in the vCard 3.0 is unclear...) // ("IANA-token" in the vCard 3.0 is unclear...)
@@ -1871,17 +1880,14 @@ public class VCardComposer {
} }
// Actual data construction starts from here. // Actual data construction starts from here.
// TODO: add a new version of appendVCardLine() for this purpose.
builder.append(Constants.PROPERTY_ADR); builder.append(Constants.PROPERTY_ADR);
builder.append(VCARD_PARAM_SEPARATOR);
// Parameters // Parameters
{ {
boolean shouldAppendParamSeparator = false;
if (!parameterList.isEmpty()) { if (!parameterList.isEmpty()) {
builder.append(VCARD_PARAM_SEPARATOR);
appendTypeParameters(builder, parameterList); appendTypeParameters(builder, parameterList);
shouldAppendParamSeparator = true;
} }
if (appendCharset) { if (appendCharset) {
@@ -1889,19 +1895,13 @@ public class VCardComposer {
// but we will add it since the information should be useful for importers, // 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. // Assume no parser does not emit error with this parameter in vCard 3.0.
if (shouldAppendParamSeparator) { builder.append(VCARD_PARAM_SEPARATOR);
builder.append(VCARD_PARAM_SEPARATOR);
}
builder.append(mVCardCharsetParameter); builder.append(mVCardCharsetParameter);
shouldAppendParamSeparator = true;
} }
if (reallyUseQuotedPrintable) { if (reallyUseQuotedPrintable) {
if (shouldAppendParamSeparator) { builder.append(VCARD_PARAM_SEPARATOR);
builder.append(VCARD_PARAM_SEPARATOR);
}
builder.append(VCARD_PARAM_ENCODING_QP); builder.append(VCARD_PARAM_ENCODING_QP);
shouldAppendParamSeparator = true;
} }
} }
@@ -1916,13 +1916,9 @@ public class VCardComposer {
final String typeAsString; final String typeAsString;
switch (type) { switch (type) {
case Email.TYPE_CUSTOM: { case Email.TYPE_CUSTOM: {
// For backward compatibility. if (VCardUtils.isMobilePhoneLabel(label)) {
// 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.
if (android.provider.Contacts.ContactMethodsColumns.MOBILE_EMAIL_TYPE_NAME
.equals(label)) {
typeAsString = Constants.PARAM_TYPE_CELL; typeAsString = Constants.PARAM_TYPE_CELL;
} else if (mUsesAndroidProperty && !TextUtils.isEmpty(label) } else if (!TextUtils.isEmpty(label)
&& VCardUtils.containsOnlyAlphaDigitHyphen(label)) { && VCardUtils.containsOnlyAlphaDigitHyphen(label)) {
typeAsString = "X-" + label; typeAsString = "X-" + label;
} else { } else {
@@ -1966,102 +1962,126 @@ public class VCardComposer {
} }
private void appendVCardTelephoneLine(final StringBuilder builder, private void appendVCardTelephoneLine(final StringBuilder builder,
final Integer typeAsObject, final String label, final Integer typeAsInteger, final String label,
final String encodedData, boolean isPrimary) { final String encodedData, boolean isPrimary) {
builder.append(Constants.PROPERTY_TEL); builder.append(Constants.PROPERTY_TEL);
builder.append(VCARD_PARAM_SEPARATOR); builder.append(VCARD_PARAM_SEPARATOR);
final int typeAsPrimitive; final int type;
if (typeAsObject == null) { if (typeAsInteger == null) {
typeAsPrimitive = Phone.TYPE_OTHER; type = Phone.TYPE_OTHER;
} else { } else {
typeAsPrimitive = typeAsObject; type = typeAsInteger;
} }
ArrayList<String> parameterList = new ArrayList<String>(); ArrayList<String> parameterList = new ArrayList<String>();
switch (typeAsPrimitive) { switch (type) {
case Phone.TYPE_HOME: case Phone.TYPE_HOME: {
parameterList.addAll( parameterList.addAll(
Arrays.asList(Constants.PARAM_TYPE_HOME)); Arrays.asList(Constants.PARAM_TYPE_HOME));
break; break;
case Phone.TYPE_WORK:
parameterList.addAll(
Arrays.asList(Constants.PARAM_TYPE_WORK));
break;
case Phone.TYPE_FAX_HOME:
parameterList.addAll(
Arrays.asList(Constants.PARAM_TYPE_HOME, Constants.PARAM_TYPE_FAX));
break;
case Phone.TYPE_FAX_WORK:
parameterList.addAll(
Arrays.asList(Constants.PARAM_TYPE_WORK, Constants.PARAM_TYPE_FAX));
break;
case Phone.TYPE_MOBILE:
parameterList.add(Constants.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(Constants.PARAM_TYPE_VOICE);
} else {
parameterList.add(Constants.PARAM_TYPE_PAGER);
} }
break; case Phone.TYPE_WORK: {
case Phone.TYPE_OTHER: parameterList.addAll(
parameterList.add(Constants.PARAM_TYPE_VOICE); Arrays.asList(Constants.PARAM_TYPE_WORK));
break; break;
case Phone.TYPE_CAR:
parameterList.add(Constants.PARAM_TYPE_CAR);
break;
case Phone.TYPE_COMPANY_MAIN:
// There's no relevant field in vCard (at least 2.1).
parameterList.add(Constants.PARAM_TYPE_WORK);
isPrimary = true;
break;
case Phone.TYPE_ISDN:
parameterList.add(Constants.PARAM_TYPE_ISDN);
break;
case Phone.TYPE_MAIN:
isPrimary = true;
break;
case Phone.TYPE_OTHER_FAX:
parameterList.add(Constants.PARAM_TYPE_FAX);
break;
case Phone.TYPE_TELEX:
parameterList.add(Constants.PARAM_TYPE_TLX);
break;
case Phone.TYPE_WORK_MOBILE:
parameterList.addAll(
Arrays.asList(Constants.PARAM_TYPE_WORK, Constants.PARAM_TYPE_CELL));
break;
case Phone.TYPE_WORK_PAGER:
parameterList.add(Constants.PARAM_TYPE_WORK);
// See above.
if (mIsDoCoMo) {
parameterList.add(Constants.PARAM_TYPE_VOICE);
} else {
parameterList.add(Constants.PARAM_TYPE_PAGER);
} }
break; case Phone.TYPE_FAX_HOME: {
case Phone.TYPE_MMS: parameterList.addAll(
parameterList.add(Constants.PARAM_TYPE_MSG); Arrays.asList(Constants.PARAM_TYPE_HOME, Constants.PARAM_TYPE_FAX));
break; break;
case Phone.TYPE_CUSTOM: }
if (mUsesAndroidProperty && !TextUtils.isEmpty(label) case Phone.TYPE_FAX_WORK: {
&& VCardUtils.containsOnlyAlphaDigitHyphen(label)) { parameterList.addAll(
// Note: Strictly, vCard 2.1 does not allow "X-" parameter without Arrays.asList(Constants.PARAM_TYPE_WORK, Constants.PARAM_TYPE_FAX));
// "TYPE=" string. break;
parameterList.add("X-" + label); }
} else { case Phone.TYPE_MOBILE: {
// Just ignore the custom type. parameterList.add(Constants.PARAM_TYPE_CELL);
parameterList.add(Constants.PARAM_TYPE_VOICE); break;
}
case Phone.TYPE_PAGER: {
if (mIsDoCoMo) {
// Not sure about the reason, but previous implementation had
// used "VOICE" instead of "PAGER"
parameterList.add(Constants.PARAM_TYPE_VOICE);
} else {
parameterList.add(Constants.PARAM_TYPE_PAGER);
}
break;
}
case Phone.TYPE_OTHER: {
parameterList.add(Constants.PARAM_TYPE_VOICE);
break;
}
case Phone.TYPE_CAR: {
parameterList.add(Constants.PARAM_TYPE_CAR);
break;
}
case Phone.TYPE_COMPANY_MAIN: {
// There's no relevant field in vCard (at least 2.1).
parameterList.add(Constants.PARAM_TYPE_WORK);
isPrimary = true;
break;
}
case Phone.TYPE_ISDN: {
parameterList.add(Constants.PARAM_TYPE_ISDN);
break;
}
case Phone.TYPE_MAIN: {
isPrimary = true;
break;
}
case Phone.TYPE_OTHER_FAX: {
parameterList.add(Constants.PARAM_TYPE_FAX);
break;
}
case Phone.TYPE_TELEX: {
parameterList.add(Constants.PARAM_TYPE_TLX);
break;
}
case Phone.TYPE_WORK_MOBILE: {
parameterList.addAll(
Arrays.asList(Constants.PARAM_TYPE_WORK, Constants.PARAM_TYPE_CELL));
break;
}
case Phone.TYPE_WORK_PAGER: {
parameterList.add(Constants.PARAM_TYPE_WORK);
// See above.
if (mIsDoCoMo) {
parameterList.add(Constants.PARAM_TYPE_VOICE);
} else {
parameterList.add(Constants.PARAM_TYPE_PAGER);
}
break;
}
case Phone.TYPE_MMS: {
parameterList.add(Constants.PARAM_TYPE_MSG);
break;
}
case Phone.TYPE_CUSTOM: {
if (TextUtils.isEmpty(label)) {
// Just ignore the custom type.
parameterList.add(Constants.PARAM_TYPE_VOICE);
} else if (VCardUtils.isMobilePhoneLabel(label)) {
parameterList.add(Constants.PARAM_TYPE_CELL);
} 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;
} }
break;
case Phone.TYPE_RADIO:
case Phone.TYPE_TTY_TDD:
default:
break;
} }
if (isPrimary) { if (isPrimary) {
@@ -2069,7 +2089,7 @@ public class VCardComposer {
} }
if (parameterList.isEmpty()) { if (parameterList.isEmpty()) {
appendUncommonPhoneType(builder, typeAsPrimitive); appendUncommonPhoneType(builder, type);
} else { } else {
appendTypeParameters(builder, parameterList); appendTypeParameters(builder, parameterList);
} }
@@ -2203,7 +2223,7 @@ public class VCardComposer {
final String propertyName, final String propertyName,
final List<String> parameterList, final List<String> parameterList,
final List<String> rawDataList, final boolean needCharset, final List<String> rawDataList, final boolean needCharset,
boolean needQuotedPrintable) { final boolean needQuotedPrintable) {
builder.append(propertyName); builder.append(propertyName);
if (parameterList != null && parameterList.size() > 0) { if (parameterList != null && parameterList.size() > 0) {
builder.append(VCARD_PARAM_SEPARATOR); builder.append(VCARD_PARAM_SEPARATOR);
@@ -2223,8 +2243,10 @@ public class VCardComposer {
builder.append(VCARD_PARAM_ENCODING_QP); builder.append(VCARD_PARAM_ENCODING_QP);
encodedData = encodeQuotedPrintable(rawData); encodedData = encodeQuotedPrintable(rawData);
} else { } else {
// TODO: one line may be too huge, which may be invalid in vCard spec, though // TODO: one line may be too huge, which may be invalid in vCard 3.0
// several (even well-known) applications do not care this. // (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.
encodedData = escapeCharacters(rawData); encodedData = escapeCharacters(rawData);
} }
@@ -2305,7 +2327,7 @@ public class VCardComposer {
} }
{ {
// Replace "\n" and "\r" with "\r\n". // Replace "\n" and "\r" with "\r\n".
StringBuilder tmpBuilder = new StringBuilder(); final StringBuilder tmpBuilder = new StringBuilder();
int length = str.length(); int length = str.length();
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
char ch = str.charAt(i); char ch = str.charAt(i);

View File

@@ -159,17 +159,31 @@ public class VCardConfig {
/** /**
* <P> * <P>
* The flag indicating the vCard composer "for 2.1" emits "TYPE=" string every time * The flag indicating the vCard composer "for 2.1" emits "TYPE=" string toward TYPE params
* possible. The default behavior does not emit it and is valid, while adding "TYPE=" * every time possible. The default behavior does not emit it and is valid in the spec.
* is also valid. In vCrad 3.0, this flag is unnecessary, since "TYPE=" is MUST in * In vCrad 3.0, this flag is unnecessary, since "TYPE=" is MUST in vCard 3.0 specification.
* vCard 3.0 specification. * </P>
* * <P>
* If you are targeting to some importer which cannot accept type parameters * Detail:
* without "TYPE=" string (which should be rare though), please use this flag. * How more than one TYPE fields are expressed is different between vCard 2.1 and vCard 3.0.
* * </p>
* XXX: Really rare? * <P>
* * e.g.<BR />
* e.g. int vcardType = (VCARD_TYPE_V21_GENERIC | FLAG_APPEND_TYPE_PARAM); * 1) Probably valid in both vCard 2.1 and vCard 3.0: "ADR;TYPE=DOM;TYPE=HOME:..."<BR />
* 2) Valid in vCard 2.1 but not in vCard 3.0: "ADR;DOM;HOME:..."<BR />
* 3) Valid in vCard 3.0 but not in vCard 2.1: "ADR;TYPE=DOM,HOME:..."<BR />
* </P>
* <P>
* 2) had been the default of VCard exporter/importer in Android, but it is found that
* some external exporter is not able to parse the type format like 2) but only 3).
* </P>
* <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: int vcardType = (VCARD_TYPE_V21_GENERIC | FLAG_APPEND_TYPE_PARAM);
* </P>
*/ */
public static final int FLAG_APPEND_TYPE_PARAM = 0x04000000; public static final int FLAG_APPEND_TYPE_PARAM = 0x04000000;
@@ -177,13 +191,13 @@ public class VCardConfig {
/** /**
* <P> * <P>
* General vCard format with the version 2.1. Uses UTF-8 for the charset. * Generic vCard format with the vCard 2.1. Uses UTF-8 for the charset.
* When composing a vCard entry, the US convension will be used toward formatting * When composing a vCard entry, the US convension will be used toward formatting
* some values * some values.
* </P> * </P>
* <P> * <P>
* e.g. The order of the display name would be "Prefix Given Middle Family Suffix", * 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. * while it should be "Prefix Family Middle Given Suffix" in Japan for example.
* </P> * </P>
*/ */
public static final int VCARD_TYPE_V21_GENERIC_UTF8 = public static final int VCARD_TYPE_V21_GENERIC_UTF8 =
@@ -197,7 +211,7 @@ public class VCardConfig {
* General vCard format with the version 3.0. Uses UTF-8 for the charset. * General vCard format with the version 3.0. Uses UTF-8 for the charset.
* </P> * </P>
* <P> * <P>
* Not ready yet. Use with caution when you use this. * Not fully ready yet. Use with caution when you use this.
* </P> * </P>
*/ */
public static final int VCARD_TYPE_V30_GENERIC_UTF8 = public static final int VCARD_TYPE_V30_GENERIC_UTF8 =
@@ -220,7 +234,7 @@ public class VCardConfig {
/** /**
* <P> * <P>
* General vCard format with the version 3.0 with some Europe convension. Uses UTF-8 * General vCard format with the version 3.0 with some Europe convension. Uses UTF-8.
* </P> * </P>
* <P> * <P>
* Not ready yet. Use with caution when you use this. * Not ready yet. Use with caution when you use this.
@@ -407,6 +421,9 @@ public class VCardConfig {
* applied to creating "formatted" something like FORMATTED_ADDRESS. * applied to creating "formatted" something like FORMATTED_ADDRESS.
*/ */
public static boolean isJapaneseDevice(final int vcardType) { 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); return sJapaneseMobileTypeSet.contains(vcardType);
} }

View File

@@ -54,8 +54,11 @@ import java.util.Map;
/** /**
* This class bridges between data structure of Contact app and VCard data. * This class bridges between data structure of Contact app and VCard data.
*/ */
public class ContactStruct { public class VCardEntry {
private static final String LOG_TAG = "vcard.ContactStruct"; private static final String LOG_TAG = "VCardEntry";
private static final String ACCOUNT_TYPE_GOOGLE = "com.google";
private static final String GOOGLE_MY_CONTACTS_GROUP = "System Group: My Contacts";
// Key: the name shown in VCard. e.g. "X-AIM", "X-ICQ" // Key: the name shown in VCard. e.g. "X-AIM", "X-ICQ"
// Value: the result of {@link Contacts.ContactMethods#encodePredefinedImProtocol} // Value: the result of {@link Contacts.ContactMethods#encodePredefinedImProtocol}
@@ -448,15 +451,15 @@ public class ContactStruct {
private final int mVCardType; private final int mVCardType;
private final Account mAccount; private final Account mAccount;
public ContactStruct() { public VCardEntry() {
this(VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8); this(VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
} }
public ContactStruct(int vcardType) { public VCardEntry(int vcardType) {
this(vcardType, null); this(vcardType, null);
} }
public ContactStruct(int vcardType, Account account) { public VCardEntry(int vcardType, Account account) {
mVCardType = vcardType; mVCardType = vcardType;
mAccount = account; mAccount = account;
} }
@@ -921,16 +924,14 @@ public class ContactStruct {
} else if (propName.equals(Constants.PROPERTY_X_SKYPE_PSTNNUMBER)) { } else if (propName.equals(Constants.PROPERTY_X_SKYPE_PSTNNUMBER)) {
// The phone number available via Skype. // The phone number available via Skype.
Collection<String> typeCollection = paramMap.get(Constants.PARAM_TYPE); Collection<String> typeCollection = paramMap.get(Constants.PARAM_TYPE);
// XXX: should use TYPE_CUSTOM + the label "Skype"? (which may need localization) final int type = Phone.TYPE_OTHER;
int type = Phone.TYPE_OTHER;
final String label = null;
final boolean isPrimary; final boolean isPrimary;
if (typeCollection != null && typeCollection.contains(Constants.PARAM_TYPE_PREF)) { if (typeCollection != null && typeCollection.contains(Constants.PARAM_TYPE_PREF)) {
isPrimary = true; isPrimary = true;
} else { } else {
isPrimary = false; isPrimary = false;
} }
addPhone(type, propValue, label, isPrimary); addPhone(type, propValue, null, isPrimary);
} else if (sImMap.containsKey(propName)) { } else if (sImMap.containsKey(propName)) {
final int protocol = sImMap.get(propName); final int protocol = sImMap.get(propName);
boolean isPrimary = false; boolean isPrimary = false;
@@ -1045,10 +1046,6 @@ public class ContactStruct {
} }
} }
// From GoogleSource.java in Contacts app.
private static final String ACCOUNT_TYPE_GOOGLE = "com.google";
private static final String GOOGLE_MY_CONTACTS_GROUP = "System Group: My Contacts";
public void pushIntoContentResolver(ContentResolver resolver) { public void pushIntoContentResolver(ContentResolver resolver) {
ArrayList<ContentProviderOperation> operationList = ArrayList<ContentProviderOperation> operationList =
new ArrayList<ContentProviderOperation>(); new ArrayList<ContentProviderOperation>();
@@ -1060,7 +1057,6 @@ public class ContactStruct {
builder.withValue(RawContacts.ACCOUNT_TYPE, mAccount.type); builder.withValue(RawContacts.ACCOUNT_TYPE, mAccount.type);
// Assume that caller side creates this group if it does not exist. // Assume that caller side creates this group if it does not exist.
// TODO: refactor this code along with the change in GoogleSource.java
if (ACCOUNT_TYPE_GOOGLE.equals(mAccount.type)) { if (ACCOUNT_TYPE_GOOGLE.equals(mAccount.type)) {
final Cursor cursor = resolver.query(Groups.CONTENT_URI, new String[] { final Cursor cursor = resolver.query(Groups.CONTENT_URI, new String[] {
Groups.SOURCE_ID }, Groups.SOURCE_ID },
@@ -1293,11 +1289,11 @@ public class ContactStruct {
} }
} }
public static ContactStruct buildFromResolver(ContentResolver resolver) { public static VCardEntry buildFromResolver(ContentResolver resolver) {
return buildFromResolver(resolver, Contacts.CONTENT_URI); return buildFromResolver(resolver, Contacts.CONTENT_URI);
} }
public static ContactStruct buildFromResolver(ContentResolver resolver, Uri uri) { public static VCardEntry buildFromResolver(ContentResolver resolver, Uri uri) {
return null; return null;
} }

View File

@@ -19,28 +19,33 @@ import android.content.ContentResolver;
import android.util.Log; import android.util.Log;
/** /**
* EntryHandler implementation which commits the entry to Contacts Provider * EntryHandler implementation which commits the entry to ContentResolver.
*
* Note:
* 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.
*/ */
public class EntryCommitter implements EntryHandler { public class VCardEntryCommitter implements VCardEntryHandler {
public static String LOG_TAG = "vcard.EntryComitter"; public static String LOG_TAG = "vcard.EntryComitter";
private ContentResolver mContentResolver; private ContentResolver mContentResolver;
private long mTimeToCommit; private long mTimeToCommit;
public EntryCommitter(ContentResolver resolver) { public VCardEntryCommitter(ContentResolver resolver) {
mContentResolver = resolver; mContentResolver = resolver;
} }
public void onParsingStart() { public void onStart() {
} }
public void onParsingEnd() { public void onEnd() {
if (VCardConfig.showPerformanceLog()) { if (VCardConfig.showPerformanceLog()) {
Log.d(LOG_TAG, String.format("time to commit entries: %d ms", mTimeToCommit)); Log.d(LOG_TAG, String.format("time to commit entries: %d ms", mTimeToCommit));
} }
} }
public void onEntryCreated(final ContactStruct contactStruct) { public void onEntryCreated(final VCardEntry contactStruct) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
contactStruct.pushIntoContentResolver(mContentResolver); contactStruct.pushIntoContentResolver(mContentResolver);
mTimeToCommit += System.currentTimeMillis() - start; mTimeToCommit += System.currentTimeMillis() - start;

View File

@@ -30,14 +30,8 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
/** public class VCardEntryConstructor implements VCardInterpreter {
* VBuilder for VCard. VCard may contain big photo images encoded by BASE64, private static String LOG_TAG = "VCardEntryConstructor";
* If we store all VNode entries in memory like VDataBuilder.java,
* OutOfMemoryError may be thrown. Thus, this class push each VCard entry into
* ContentResolver immediately.
*/
public class VCardDataBuilder implements VCardBuilder {
static private String LOG_TAG = "VCardDataBuilder";
/** /**
* If there's no other information available, this class uses this charset for encoding * If there's no other information available, this class uses this charset for encoding
@@ -45,8 +39,8 @@ public class VCardDataBuilder implements VCardBuilder {
*/ */
static public String TARGET_CHARSET = "UTF-8"; static public String TARGET_CHARSET = "UTF-8";
private ContactStruct.Property mCurrentProperty = new ContactStruct.Property(); private VCardEntry.Property mCurrentProperty = new VCardEntry.Property();
private ContactStruct mCurrentContactStruct; private VCardEntry mCurrentContactStruct;
private String mParamType; private String mParamType;
/** /**
@@ -66,23 +60,20 @@ public class VCardDataBuilder implements VCardBuilder {
// Just for testing. // Just for testing.
private long mTimePushIntoContentResolver; private long mTimePushIntoContentResolver;
private List<EntryHandler> mEntryHandlers = new ArrayList<EntryHandler>(); private List<VCardEntryHandler> mEntryHandlers = new ArrayList<VCardEntryHandler>();
public VCardDataBuilder() { public VCardEntryConstructor() {
this(null, null, false, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8, null); this(null, null, false, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8, null);
} }
/** public VCardEntryConstructor(int vcardType) {
* @hide
*/
public VCardDataBuilder(int vcardType) {
this(null, null, false, vcardType, null); this(null, null, false, vcardType, null);
} }
/** /**
* @hide * @hide
*/ */
public VCardDataBuilder(String charset, public VCardEntryConstructor(String charset,
boolean strictLineBreakParsing, int vcardType, Account account) { boolean strictLineBreakParsing, int vcardType, Account account) {
this(null, charset, strictLineBreakParsing, vcardType, account); this(null, charset, strictLineBreakParsing, vcardType, account);
} }
@@ -90,7 +81,7 @@ public class VCardDataBuilder implements VCardBuilder {
/** /**
* @hide * @hide
*/ */
public VCardDataBuilder(String sourceCharset, public VCardEntryConstructor(String sourceCharset,
String targetCharset, String targetCharset,
boolean strictLineBreakParsing, boolean strictLineBreakParsing,
int vcardType, int vcardType,
@@ -110,19 +101,19 @@ public class VCardDataBuilder implements VCardBuilder {
mAccount = account; mAccount = account;
} }
public void addEntryHandler(EntryHandler entryHandler) { public void addEntryHandler(VCardEntryHandler entryHandler) {
mEntryHandlers.add(entryHandler); mEntryHandlers.add(entryHandler);
} }
public void start() { public void start() {
for (EntryHandler entryHandler : mEntryHandlers) { for (VCardEntryHandler entryHandler : mEntryHandlers) {
entryHandler.onParsingStart(); entryHandler.onStart();
} }
} }
public void end() { public void end() {
for (EntryHandler entryHandler : mEntryHandlers) { for (VCardEntryHandler entryHandler : mEntryHandlers) {
entryHandler.onParsingEnd(); entryHandler.onEnd();
} }
} }
@@ -135,7 +126,7 @@ public class VCardDataBuilder implements VCardBuilder {
*/ */
public void clear() { public void clear() {
mCurrentContactStruct = null; mCurrentContactStruct = null;
mCurrentProperty = new ContactStruct.Property(); mCurrentProperty = new VCardEntry.Property();
} }
/** /**
@@ -153,12 +144,12 @@ public class VCardDataBuilder implements VCardBuilder {
Log.e(LOG_TAG, "This is not VCARD!"); Log.e(LOG_TAG, "This is not VCARD!");
} }
mCurrentContactStruct = new ContactStruct(mVCardType, mAccount); mCurrentContactStruct = new VCardEntry(mVCardType, mAccount);
} }
public void endRecord() { public void endRecord() {
mCurrentContactStruct.consolidateFields(); mCurrentContactStruct.consolidateFields();
for (EntryHandler entryHandler : mEntryHandlers) { for (VCardEntryHandler entryHandler : mEntryHandlers) {
entryHandler.onEntryCreated(mCurrentContactStruct); entryHandler.onEntryCreated(mCurrentContactStruct);
} }
mCurrentContactStruct = null; mCurrentContactStruct = null;

View File

@@ -17,7 +17,7 @@ package android.pim.vcard;
import java.util.List; import java.util.List;
public class VCardEntryCounter implements VCardBuilder { public class VCardEntryCounter implements VCardInterpreter {
private int mCount; private int mCount;
public int getCount() { public int getCount() {

View File

@@ -15,24 +15,20 @@
*/ */
package android.pim.vcard; package android.pim.vcard;
/** public interface VCardEntryHandler {
* Unlike {@link VCardBuilder}, this (and {@link VCardDataBuilder}) assumes
* "each VCard entry should be correctly parsed and passed to each EntryHandler object",
*/
public interface EntryHandler {
/** /**
* Called when the parsing started. * Called when the parsing started.
*/ */
public void onParsingStart(); public void onStart();
/** /**
* The method called when one VCard entry is successfully created * The method called when one VCard entry is successfully created
*/ */
public void onEntryCreated(final ContactStruct entry); public void onEntryCreated(final VCardEntry entry);
/** /**
* Called when the parsing ended. * Called when the parsing ended.
* Able to be use this method for showing performance log, etc. * Able to be use this method for showing performance log, etc.
*/ */
public void onParsingEnd(); public void onEnd();
} }

View File

@@ -18,81 +18,81 @@ package android.pim.vcard;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
public class VCardBuilderCollection implements VCardBuilder { public class VCardInterPreterCollection implements VCardInterpreter {
private final Collection<VCardBuilder> mVCardBuilderCollection; private final Collection<VCardInterpreter> mVCardBuilderCollection;
public VCardBuilderCollection(Collection<VCardBuilder> vBuilderCollection) { public VCardInterPreterCollection(Collection<VCardInterpreter> vBuilderCollection) {
mVCardBuilderCollection = vBuilderCollection; mVCardBuilderCollection = vBuilderCollection;
} }
public Collection<VCardBuilder> getVCardBuilderBaseCollection() { public Collection<VCardInterpreter> getCollection() {
return mVCardBuilderCollection; return mVCardBuilderCollection;
} }
public void start() { public void start() {
for (VCardBuilder builder : mVCardBuilderCollection) { for (VCardInterpreter builder : mVCardBuilderCollection) {
builder.start(); builder.start();
} }
} }
public void end() { public void end() {
for (VCardBuilder builder : mVCardBuilderCollection) { for (VCardInterpreter builder : mVCardBuilderCollection) {
builder.end(); builder.end();
} }
} }
public void startRecord(String type) { public void startRecord(String type) {
for (VCardBuilder builder : mVCardBuilderCollection) { for (VCardInterpreter builder : mVCardBuilderCollection) {
builder.startRecord(type); builder.startRecord(type);
} }
} }
public void endRecord() { public void endRecord() {
for (VCardBuilder builder : mVCardBuilderCollection) { for (VCardInterpreter builder : mVCardBuilderCollection) {
builder.endRecord(); builder.endRecord();
} }
} }
public void startProperty() { public void startProperty() {
for (VCardBuilder builder : mVCardBuilderCollection) { for (VCardInterpreter builder : mVCardBuilderCollection) {
builder.startProperty(); builder.startProperty();
} }
} }
public void endProperty() { public void endProperty() {
for (VCardBuilder builder : mVCardBuilderCollection) { for (VCardInterpreter builder : mVCardBuilderCollection) {
builder.endProperty(); builder.endProperty();
} }
} }
public void propertyGroup(String group) { public void propertyGroup(String group) {
for (VCardBuilder builder : mVCardBuilderCollection) { for (VCardInterpreter builder : mVCardBuilderCollection) {
builder.propertyGroup(group); builder.propertyGroup(group);
} }
} }
public void propertyName(String name) { public void propertyName(String name) {
for (VCardBuilder builder : mVCardBuilderCollection) { for (VCardInterpreter builder : mVCardBuilderCollection) {
builder.propertyName(name); builder.propertyName(name);
} }
} }
public void propertyParamType(String type) { public void propertyParamType(String type) {
for (VCardBuilder builder : mVCardBuilderCollection) { for (VCardInterpreter builder : mVCardBuilderCollection) {
builder.propertyParamType(type); builder.propertyParamType(type);
} }
} }
public void propertyParamValue(String value) { public void propertyParamValue(String value) {
for (VCardBuilder builder : mVCardBuilderCollection) { for (VCardInterpreter builder : mVCardBuilderCollection) {
builder.propertyParamValue(value); builder.propertyParamValue(value);
} }
} }
public void propertyValues(List<String> values) { public void propertyValues(List<String> values) {
for (VCardBuilder builder : mVCardBuilderCollection) { for (VCardInterpreter builder : mVCardBuilderCollection) {
builder.propertyValues(values); builder.propertyValues(values);
} }
} }

View File

@@ -17,7 +17,7 @@ package android.pim.vcard;
import java.util.List; import java.util.List;
public interface VCardBuilder { public interface VCardInterpreter {
void start(); void start();
void end(); void end();
@@ -27,7 +27,7 @@ public interface VCardBuilder {
*/ */
void startRecord(String type); void startRecord(String type);
/** END:VXX */ /** END:VCARD */
void endRecord(); void endRecord();
void startProperty(); void startProperty();

View File

@@ -64,7 +64,7 @@ public abstract class VCardParser {
* @return Returns true for success. Otherwise returns false. * @return Returns true for success. Otherwise returns false.
* @throws IOException, VCardException * @throws IOException, VCardException
*/ */
public abstract boolean parse(InputStream is, VCardBuilder builder) public abstract boolean parse(InputStream is, VCardInterpreter builder)
throws IOException, VCardException; throws IOException, VCardException;
/** /**
@@ -82,7 +82,7 @@ public abstract class VCardParser {
* @return Returns true when successful. Otherwise returns false. * @return Returns true when successful. Otherwise returns false.
* @throws IOException, VCardException * @throws IOException, VCardException
*/ */
public abstract boolean parse(InputStream is, String charset, VCardBuilder builder) public abstract boolean parse(InputStream is, String charset, VCardInterpreter builder)
throws IOException, VCardException; throws IOException, VCardException;
/** /**
@@ -91,7 +91,7 @@ public abstract class VCardParser {
* @hide * @hide
*/ */
public abstract void parse(InputStream is, String charset, public abstract void parse(InputStream is, String charset,
VCardBuilder builder, boolean canceled) VCardInterpreter builder, boolean canceled)
throws IOException, VCardException; throws IOException, VCardException;
/** /**

View File

@@ -72,7 +72,7 @@ public class VCardParser_V21 extends VCardParser {
private String mPreviousLine; private String mPreviousLine;
/** The builder to build parsed data */ /** The builder to build parsed data */
protected VCardBuilder mBuilder = null; protected VCardInterpreter mBuilder = null;
/** /**
* The encoding type. "Encoding" in vCard is different from "Charset". * The encoding type. "Encoding" in vCard is different from "Charset".
@@ -876,13 +876,13 @@ public class VCardParser_V21 extends VCardParser {
} }
@Override @Override
public boolean parse(final InputStream is, final VCardBuilder builder) public boolean parse(final InputStream is, final VCardInterpreter builder)
throws IOException, VCardException { throws IOException, VCardException {
return parse(is, VCardConfig.DEFAULT_CHARSET, builder); return parse(is, VCardConfig.DEFAULT_CHARSET, builder);
} }
@Override @Override
public boolean parse(InputStream is, String charset, VCardBuilder builder) public boolean parse(InputStream is, String charset, VCardInterpreter builder)
throws IOException, VCardException { throws IOException, VCardException {
if (charset == null) { if (charset == null) {
charset = VCardConfig.DEFAULT_CHARSET; charset = VCardConfig.DEFAULT_CHARSET;
@@ -914,7 +914,7 @@ public class VCardParser_V21 extends VCardParser {
} }
@Override @Override
public void parse(InputStream is, String charset, VCardBuilder builder, boolean canceled) public void parse(InputStream is, String charset, VCardInterpreter builder, boolean canceled)
throws IOException, VCardException { throws IOException, VCardException {
mCanceled = canceled; mCanceled = canceled;
parse(is, charset, builder); parse(is, charset, builder);

View File

@@ -25,7 +25,7 @@ import java.util.Set;
* Currently this implementation is very premature. * Currently this implementation is very premature.
* @hide * @hide
*/ */
public class VCardSourceDetector implements VCardBuilder { public class VCardSourceDetector implements VCardInterpreter {
// Should only be used in package. // Should only be used in package.
static final int TYPE_UNKNOWN = 0; static final int TYPE_UNKNOWN = 0;
static final int TYPE_APPLE = 1; static final int TYPE_APPLE = 1;

View File

@@ -23,9 +23,9 @@ import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.telephony.PhoneNumberUtils; import android.telephony.PhoneNumberUtils;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@@ -37,19 +37,14 @@ import java.util.Set;
* Utilities for VCard handling codes. * Utilities for VCard handling codes.
*/ */
public class VCardUtils { public class VCardUtils {
/*
* TODO: some of methods in this class should be placed to the more appropriate place...
*/
// Note that not all types are included in this map/set, since, for example, TYPE_HOME_FAX is // 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 // converted to two parameter Strings. These only contain some minor fields valid in both
// vCard and current (as of 2009-08-07) Contacts structure. // vCard and current (as of 2009-08-07) Contacts structure.
private static final Map<Integer, String> sKnownPhoneTypesMap_ItoS; private static final Map<Integer, String> sKnownPhoneTypesMap_ItoS;
private static final Set<String> sPhoneTypesSetUnknownToContacts; private static final Set<String> sPhoneTypesUnknownToContactsSet;
private static final Map<String, Integer> sKnownPhoneTypeMap_StoI; private static final Map<String, Integer> sKnownPhoneTypeMap_StoI;
private static final Map<Integer, String> sKnownImPropNameMap_ItoS; private static final Map<Integer, String> sKnownImPropNameMap_ItoS;
private static final Set<String> sMobilePhoneLabelSet;
static { static {
sKnownPhoneTypesMap_ItoS = new HashMap<Integer, String>(); sKnownPhoneTypesMap_ItoS = new HashMap<Integer, String>();
@@ -75,10 +70,10 @@ public class VCardUtils {
sKnownPhoneTypeMap_StoI.put(Constants.PARAM_PHONE_EXTRA_TYPE_ASSISTANT, sKnownPhoneTypeMap_StoI.put(Constants.PARAM_PHONE_EXTRA_TYPE_ASSISTANT,
Phone.TYPE_ASSISTANT); Phone.TYPE_ASSISTANT);
sPhoneTypesSetUnknownToContacts = new HashSet<String>(); sPhoneTypesUnknownToContactsSet = new HashSet<String>();
sPhoneTypesSetUnknownToContacts.add(Constants.PARAM_TYPE_MODEM); sPhoneTypesUnknownToContactsSet.add(Constants.PARAM_TYPE_MODEM);
sPhoneTypesSetUnknownToContacts.add(Constants.PARAM_TYPE_BBS); sPhoneTypesUnknownToContactsSet.add(Constants.PARAM_TYPE_BBS);
sPhoneTypesSetUnknownToContacts.add(Constants.PARAM_TYPE_VIDEO); sPhoneTypesUnknownToContactsSet.add(Constants.PARAM_TYPE_VIDEO);
sKnownImPropNameMap_ItoS = new HashMap<Integer, String>(); sKnownImPropNameMap_ItoS = new HashMap<Integer, String>();
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_AIM, Constants.PROPERTY_X_AIM); sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_AIM, Constants.PROPERTY_X_AIM);
@@ -90,6 +85,14 @@ public class VCardUtils {
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_JABBER, Constants.PROPERTY_X_JABBER); sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_JABBER, Constants.PROPERTY_X_JABBER);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_QQ, Constants.PROPERTY_X_QQ); sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_QQ, Constants.PROPERTY_X_QQ);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_NETMEETING, Constants.PROPERTY_X_NETMEETING); sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_NETMEETING, Constants.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) { public static String getPhoneTypeString(Integer type) {
@@ -112,6 +115,9 @@ public class VCardUtils {
if (types != null) { if (types != null) {
for (String typeString : types) { for (String typeString : types) {
if (typeString == null) {
continue;
}
typeString = typeString.toUpperCase(); typeString = typeString.toUpperCase();
if (typeString.equals(Constants.PARAM_TYPE_PREF)) { if (typeString.equals(Constants.PARAM_TYPE_PREF)) {
hasPref = true; hasPref = true;
@@ -121,7 +127,10 @@ public class VCardUtils {
if (typeString.startsWith("X-") && type < 0) { if (typeString.startsWith("X-") && type < 0) {
typeString = typeString.substring(2); typeString = typeString.substring(2);
} }
Integer tmp = sKnownPhoneTypeMap_StoI.get(typeString); if (typeString.length() == 0) {
continue;
}
final Integer tmp = sKnownPhoneTypeMap_StoI.get(typeString);
if (tmp != null) { if (tmp != null) {
final int typeCandidate = tmp; final int typeCandidate = tmp;
// TYPE_PAGER is prefered when the number contains @ surronded by // TYPE_PAGER is prefered when the number contains @ surronded by
@@ -168,18 +177,21 @@ public class VCardUtils {
} }
} }
public static String getPropertyNameForIm(int protocol) { @SuppressWarnings("deprecation")
return sKnownImPropNameMap_ItoS.get(protocol); 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 (android.provider.Contacts.ContactMethodsColumns.MOBILE_EMAIL_TYPE_NAME.equals(label)
|| sMobilePhoneLabelSet.contains(label));
} }
public static boolean isValidPhoneType(String phoneType, int vcardType) { public static boolean isValidInV21ButUnknownToContactsPhoteType(final String label) {
// TODO: check the following. return sPhoneTypesUnknownToContactsSet.contains(label);
// - it may violate vCard spec }
// - it may contain non-ASCII characters
// public static String getPropertyNameForIm(final int protocol) {
// TODO: use vcardType return sKnownImPropNameMap_ItoS.get(protocol);
return (phoneType.startsWith("X-") || phoneType.startsWith("x-") ||
sPhoneTypesSetUnknownToContacts.contains(phoneType));
} }
public static String[] sortNameElements(final int vcardType, public static String[] sortNameElements(final int vcardType,
@@ -233,7 +245,7 @@ public class VCardUtils {
*/ */
public static void insertStructuredPostalDataUsingContactsStruct(int vcardType, public static void insertStructuredPostalDataUsingContactsStruct(int vcardType,
final ContentProviderOperation.Builder builder, final ContentProviderOperation.Builder builder,
final ContactStruct.PostalData postalData) { final VCardEntry.PostalData postalData) {
builder.withValueBackReference(StructuredPostal.RAW_CONTACT_ID, 0); builder.withValueBackReference(StructuredPostal.RAW_CONTACT_ID, 0);
builder.withValue(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE); builder.withValue(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
@@ -269,7 +281,7 @@ public class VCardUtils {
* So some conversion may be performed in this method. See also * So some conversion may be performed in this method. See also
* {{@link #insertStructuredPostalDataUsingContactsStruct(int, * {{@link #insertStructuredPostalDataUsingContactsStruct(int,
* android.content.ContentProviderOperation.Builder, * android.content.ContentProviderOperation.Builder,
* android.pim.vcard.ContactStruct.PostalData)} * android.pim.vcard.VCardEntry.PostalData)}
*/ */
public static String[] getVCardPostalElements(ContentValues contentValues) { public static String[] getVCardPostalElements(ContentValues contentValues) {
// adr-value = 0*6(text-value ";") text-value // adr-value = 0*6(text-value ";") text-value
@@ -517,364 +529,3 @@ public class VCardUtils {
private VCardUtils() { private VCardUtils() {
} }
} }
/**
* TextUtils especially for Japanese.
* TODO: make this in android.text in the future
*/
class JapaneseUtils {
static private final Map<Character, String> sHalfWidthMap =
new HashMap<Character, String>();
static {
// There's no logical mapping rule in Unicode. Sigh.
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");
}
/**
* Return half-width version of that character if possible. Return null if not possible
* @param ch input character
* @return CharSequence object if the mapping for ch exists. Return null otherwise.
*/
public static CharSequence tryGetHalfWidthText(char ch) {
if (sHalfWidthMap.containsKey(ch)) {
return sHalfWidthMap.get(ch);
} else {
return null;
}
}
}

View File

@@ -16,7 +16,8 @@
package com.android.unit_tests.vcard; package com.android.unit_tests.vcard;
import android.content.ContentValues; import android.content.ContentValues;
import android.pim.vcard.ContactStruct; import android.pim.vcard.VCardEntry;
import android.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -28,7 +29,7 @@ import java.util.Set;
* Previously used in main vCard handling code but now exists only for testing. * Previously used in main vCard handling code but now exists only for testing.
* *
* Especially useful for testing parser code (VCardParser), since all properties can be * Especially useful for testing parser code (VCardParser), since all properties can be
* checked via this class unlike {@link ContactStruct}, which only emits the result of * checked via this class unlike {@link VCardEntry}, which only emits the result of
* interpretation of the content of each vCard. We cannot know whether vCard parser or * interpretation of the content of each vCard. We cannot know whether vCard parser or
* ContactStruct is wrong withouth this class. * ContactStruct is wrong withouth this class.
*/ */
@@ -123,7 +124,10 @@ public class PropertyNode {
return false; return false;
} else if (!paramMap.equals(node.paramMap)) { } else if (!paramMap.equals(node.paramMap)) {
return false; return false;
} else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) { } else if (!(paramMap_TYPE.size() == node.paramMap_TYPE.size()) &&
!paramMap_TYPE.equals(node.paramMap_TYPE)) {
Log.d("@@@", "paramMap_Type: " + paramMap_TYPE.size() + ", "
+ node.paramMap_TYPE.size());
return false; return false;
} else if (!propGroupSet.equals(node.propGroupSet)) { } else if (!propGroupSet.equals(node.propGroupSet)) {
return false; return false;
@@ -154,10 +158,33 @@ public class PropertyNode {
builder.append(propName); builder.append(propName);
builder.append(", paramMap: "); builder.append(", paramMap: ");
builder.append(paramMap.toString()); builder.append(paramMap.toString());
builder.append(", propmMap_TYPE: "); builder.append(", paramMap_TYPE: [");
builder.append(paramMap_TYPE.toString()); boolean first = true;
builder.append(", propGroupSet: "); for (String elem : paramMap_TYPE) {
builder.append(propGroupSet.toString()); if (first) {
first = false;
} else {
builder.append(", ");
}
builder.append('"');
builder.append(elem);
builder.append('"');
}
builder.append("]");
if (!propGroupSet.isEmpty()) {
builder.append(", propGroupSet: [");
for (String elem : propGroupSet) {
if (first) {
first = false;
} else {
builder.append(", ");
}
builder.append('"');
builder.append(elem);
builder.append('"');
}
builder.append("]");
}
if (propValue_vector != null && propValue_vector.size() > 1) { if (propValue_vector != null && propValue_vector.size() > 1) {
builder.append(", propValue_vector size: "); builder.append(", propValue_vector size: ");
builder.append(propValue_vector.size()); builder.append(propValue_vector.size());

View File

@@ -419,6 +419,62 @@ public class VCardExporterTests extends VCardTestsBase {
testPhonePrefHandlingCommon(V30); testPhonePrefHandlingCommon(V30);
} }
private void testMiscPhoneTypeHandling(int vcardType) {
ExportTestResolver resolver = new ExportTestResolver();
ContactEntry entry = resolver.buildContactEntry();
entry.buildData(Phone.CONTENT_ITEM_TYPE)
.put(Phone.NUMBER, "1")
.put(Phone.TYPE, Phone.TYPE_CUSTOM)
.put(Phone.LABEL, "Modem");
entry.buildData(Phone.CONTENT_ITEM_TYPE)
.put(Phone.NUMBER, "2")
.put(Phone.TYPE, Phone.TYPE_CUSTOM)
.put(Phone.LABEL, "MSG");
entry.buildData(Phone.CONTENT_ITEM_TYPE)
.put(Phone.NUMBER, "3")
.put(Phone.TYPE, Phone.TYPE_CUSTOM)
.put(Phone.LABEL, "BBS");
entry.buildData(Phone.CONTENT_ITEM_TYPE)
.put(Phone.NUMBER, "4")
.put(Phone.TYPE, Phone.TYPE_CUSTOM)
.put(Phone.LABEL, "VIDEO");
entry.buildData(Phone.CONTENT_ITEM_TYPE)
.put(Phone.NUMBER, "5")
.put(Phone.TYPE, Phone.TYPE_CUSTOM);
entry.buildData(Phone.CONTENT_ITEM_TYPE)
.put(Phone.NUMBER, "6")
.put(Phone.TYPE, Phone.TYPE_CUSTOM)
.put(Phone.LABEL, "_AUTO_CELL"); // The old indicator for the type mobile.
entry.buildData(Phone.CONTENT_ITEM_TYPE)
.put(Phone.NUMBER, "7")
.put(Phone.TYPE, Phone.TYPE_CUSTOM)
.put(Phone.LABEL, "\u643A\u5E2F"); // Mobile phone in Japanese Kanji
entry.buildData(Phone.CONTENT_ITEM_TYPE)
.put(Phone.NUMBER, "8")
.put(Phone.TYPE, Phone.TYPE_CUSTOM)
.put(Phone.LABEL, "invalid");
VCardVerifier verifier = new VCardVerifier(resolver, vcardType);
PropertyNodesVerifierElem elem = verifier.addPropertyNodesVerifierElemWithEmptyName();
elem.addNodeWithoutOrder("TEL", "1", new TypeSet("MODEM"))
.addNodeWithoutOrder("TEL", "2", new TypeSet("MSG"))
.addNodeWithoutOrder("TEL", "3", new TypeSet("BBS"))
.addNodeWithoutOrder("TEL", "4", new TypeSet("VIDEO"))
.addNodeWithoutOrder("TEL", "5", new TypeSet("VOICE"))
.addNodeWithoutOrder("TEL", "6", new TypeSet("CELL"))
.addNodeWithoutOrder("TEL", "7", new TypeSet("CELL"))
.addNodeWithoutOrder("TEL", "8", new TypeSet("X-invalid"));
verifier.verify();
}
public void testPhoneTypeHandlingV21() {
testMiscPhoneTypeHandling(V21);
}
public void testPhoneTypeHandlingV30() {
testMiscPhoneTypeHandling(V30);
}
private void testEmailBasicCommon(int version) { private void testEmailBasicCommon(int version) {
ExportTestResolver resolver = new ExportTestResolver(); ExportTestResolver resolver = new ExportTestResolver();
resolver.buildContactEntry().buildData(Email.CONTENT_ITEM_TYPE) resolver.buildContactEntry().buildData(Email.CONTENT_ITEM_TYPE)

View File

@@ -19,6 +19,7 @@ package com.android.unit_tests.vcard;
import android.content.ContentValues; import android.content.ContentValues;
import android.pim.vcard.VCardConfig; import android.pim.vcard.VCardConfig;
import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import com.android.unit_tests.vcard.PropertyNodesVerifierElem.TypeSet; import com.android.unit_tests.vcard.PropertyNodesVerifierElem.TypeSet;
@@ -204,4 +205,125 @@ public class VCardJapanizationTests extends VCardTestsBase {
.put(StructuredName.DISPLAY_NAME, "\uFF94\uFF8F\uFF80\uFF9E \uFF80\uFF9B\uFF73"); .put(StructuredName.DISPLAY_NAME, "\uFF94\uFF8F\uFF80\uFF9E \uFF80\uFF9B\uFF73");
verifier.verify(); verifier.verify();
} }
/**
* Verifies that only one address field is emitted toward DoCoMo phones.
* Prefered type must (should?) be: HOME > WORK > OTHER > CUSTOM
*/
public void testAdrressFieldEmittionForDoCoMo_1() {
ExportTestResolver resolver = new ExportTestResolver();
ContactEntry entry = resolver.buildContactEntry();
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK)
.put(StructuredPostal.POBOX, "1");
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_OTHER)
.put(StructuredPostal.POBOX, "2");
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME)
.put(StructuredPostal.POBOX, "3");
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM)
.put(StructuredPostal.LABEL, "custom")
.put(StructuredPostal.POBOX, "4");
VCardVerifier verifier = new VCardVerifier(resolver, VCardConfig.VCARD_TYPE_DOCOMO);
verifier.addPropertyNodesVerifierElemWithEmptyName()
.addNodeWithoutOrder("TEL", "", new TypeSet("HOME"))
.addNodeWithoutOrder("EMAIL", "", new TypeSet("HOME"))
.addNodeWithoutOrder("X-CLASS", "PUBLIC")
.addNodeWithoutOrder("X-REDUCTION", "")
.addNodeWithoutOrder("X-NO", "")
.addNodeWithoutOrder("X-DCM-HMN-MODE", "")
.addNodeWithoutOrder("ADR",
Arrays.asList("3", "", "", "", "", "", ""), new TypeSet("HOME"));
verifier.verify();
}
public void testAdrressFieldEmittionForDoCoMo_2() {
ExportTestResolver resolver = new ExportTestResolver();
ContactEntry entry = resolver.buildContactEntry();
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_OTHER)
.put(StructuredPostal.POBOX, "1");
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK)
.put(StructuredPostal.POBOX, "2");
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM)
.put(StructuredPostal.LABEL, "custom")
.put(StructuredPostal.POBOX, "3");
VCardVerifier verifier = new VCardVerifier(resolver, VCardConfig.VCARD_TYPE_DOCOMO);
verifier.addPropertyNodesVerifierElemWithEmptyName()
.addNodeWithoutOrder("TEL", "", new TypeSet("HOME"))
.addNodeWithoutOrder("EMAIL", "", new TypeSet("HOME"))
.addNodeWithoutOrder("X-CLASS", "PUBLIC")
.addNodeWithoutOrder("X-REDUCTION", "")
.addNodeWithoutOrder("X-NO", "")
.addNodeWithoutOrder("X-DCM-HMN-MODE", "")
.addNodeWithoutOrder("ADR",
Arrays.asList("2", "", "", "", "", "", ""), new TypeSet("WORK"));
verifier.verify();
}
public void testAdrressFieldEmittionForDoCoMo_3() {
ExportTestResolver resolver = new ExportTestResolver();
ContactEntry entry = resolver.buildContactEntry();
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM)
.put(StructuredPostal.LABEL, "custom1")
.put(StructuredPostal.POBOX, "1");
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_OTHER)
.put(StructuredPostal.POBOX, "2");
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM)
.put(StructuredPostal.LABEL, "custom2")
.put(StructuredPostal.POBOX, "3");
VCardVerifier verifier = new VCardVerifier(resolver, VCardConfig.VCARD_TYPE_DOCOMO);
verifier.addPropertyNodesVerifierElemWithEmptyName()
.addNodeWithoutOrder("TEL", "", new TypeSet("HOME"))
.addNodeWithoutOrder("EMAIL", "", new TypeSet("HOME"))
.addNodeWithoutOrder("X-CLASS", "PUBLIC")
.addNodeWithoutOrder("X-REDUCTION", "")
.addNodeWithoutOrder("X-NO", "")
.addNodeWithoutOrder("X-DCM-HMN-MODE", "")
.addNodeWithoutOrder("ADR", Arrays.asList("2", "", "", "", "", "", ""));
verifier.verify();
}
/**
* Verifies the vCard exporter tolerates null TYPE.
*/
public void testAdrressFieldEmittionForDoCoMo_4() {
ExportTestResolver resolver = new ExportTestResolver();
ContactEntry entry = resolver.buildContactEntry();
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.POBOX, "1");
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_OTHER)
.put(StructuredPostal.POBOX, "2");
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME)
.put(StructuredPostal.POBOX, "3");
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK)
.put(StructuredPostal.POBOX, "4");
entry.buildData(StructuredPostal.CONTENT_ITEM_TYPE)
.put(StructuredPostal.POBOX, "5");
VCardVerifier verifier = new VCardVerifier(resolver, VCardConfig.VCARD_TYPE_DOCOMO);
verifier.addPropertyNodesVerifierElemWithEmptyName()
.addNodeWithoutOrder("TEL", "", new TypeSet("HOME"))
.addNodeWithoutOrder("EMAIL", "", new TypeSet("HOME"))
.addNodeWithoutOrder("X-CLASS", "PUBLIC")
.addNodeWithoutOrder("X-REDUCTION", "")
.addNodeWithoutOrder("X-NO", "")
.addNodeWithoutOrder("X-DCM-HMN-MODE", "")
.addNodeWithoutOrder("ADR",
Arrays.asList("3", "", "", "", "", "", ""), new TypeSet("HOME"));
verifier.verify();
}
} }

View File

@@ -33,14 +33,14 @@ import android.net.Uri;
import android.os.IBinder; import android.os.IBinder;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.RemoteException; import android.os.RemoteException;
import android.pim.vcard.ContactStruct; import android.pim.vcard.VCardEntry;
import android.pim.vcard.EntryCommitter; import android.pim.vcard.VCardEntryCommitter;
import android.pim.vcard.EntryHandler; import android.pim.vcard.VCardEntryHandler;
import android.pim.vcard.VCardBuilder; import android.pim.vcard.VCardInterpreter;
import android.pim.vcard.VCardBuilderCollection; import android.pim.vcard.VCardInterPreterCollection;
import android.pim.vcard.VCardComposer; import android.pim.vcard.VCardComposer;
import android.pim.vcard.VCardConfig; import android.pim.vcard.VCardConfig;
import android.pim.vcard.VCardDataBuilder; import android.pim.vcard.VCardEntryConstructor;
import android.pim.vcard.VCardParser; import android.pim.vcard.VCardParser;
import android.pim.vcard.VCardParser_V21; import android.pim.vcard.VCardParser_V21;
import android.pim.vcard.VCardParser_V30; import android.pim.vcard.VCardParser_V30;
@@ -385,11 +385,11 @@ class CustomMockContext extends MockContext {
class ImportVerifierElem { class ImportVerifierElem {
private final ImportTestResolver mResolver; private final ImportTestResolver mResolver;
private final EntryHandler mHandler; private final VCardEntryHandler mHandler;
public ImportVerifierElem() { public ImportVerifierElem() {
mResolver = new ImportTestResolver(); mResolver = new ImportTestResolver();
mHandler = new EntryCommitter(mResolver); mHandler = new VCardEntryCommitter(mResolver);
} }
public ContentValuesBuilder addExpected(String mimeType) { public ContentValuesBuilder addExpected(String mimeType) {
@@ -411,8 +411,8 @@ class CustomMockContext extends MockContext {
} else { } else {
vCardParser = new VCardParser_V21(); vCardParser = new VCardParser_V21();
} }
VCardDataBuilder builder = VCardEntryConstructor builder =
new VCardDataBuilder(null, null, false, vCardType, null); new VCardEntryConstructor(null, null, false, vCardType, null);
builder.addEntryHandler(mHandler); builder.addEntryHandler(mHandler);
try { try {
vCardParser.parse(is, builder); vCardParser.parse(is, builder);
@@ -432,19 +432,19 @@ class CustomMockContext extends MockContext {
} }
public void onParsingStart() { public void onParsingStart() {
mHandler.onParsingStart(); mHandler.onStart();
} }
public void onEntryCreated(ContactStruct entry) { public void onEntryCreated(VCardEntry entry) {
mHandler.onEntryCreated(entry); mHandler.onEntryCreated(entry);
} }
public void onParsingEnd() { public void onParsingEnd() {
mHandler.onParsingEnd(); mHandler.onEnd();
} }
} }
class ImportVerifier implements EntryHandler { class ImportVerifier implements VCardEntryHandler {
private List<ImportVerifierElem> mImportVerifierElemList = private List<ImportVerifierElem> mImportVerifierElemList =
new ArrayList<ImportVerifierElem>(); new ArrayList<ImportVerifierElem>();
private int mIndex; private int mIndex;
@@ -476,8 +476,8 @@ class CustomMockContext extends MockContext {
public void verify(InputStream is, int vCardType, final VCardParser vCardParser) public void verify(InputStream is, int vCardType, final VCardParser vCardParser)
throws IOException, VCardException { throws IOException, VCardException {
VCardDataBuilder builder = VCardEntryConstructor builder =
new VCardDataBuilder(null, null, false, vCardType, null); new VCardEntryConstructor(null, null, false, vCardType, null);
builder.addEntryHandler(this); builder.addEntryHandler(this);
try { try {
vCardParser.parse(is, builder); vCardParser.parse(is, builder);
@@ -491,19 +491,19 @@ class CustomMockContext extends MockContext {
} }
} }
public void onParsingStart() { public void onStart() {
for (ImportVerifierElem elem : mImportVerifierElemList) { for (ImportVerifierElem elem : mImportVerifierElemList) {
elem.onParsingStart(); elem.onParsingStart();
} }
} }
public void onEntryCreated(ContactStruct entry) { public void onEntryCreated(VCardEntry entry) {
assertTrue(mIndex < mImportVerifierElemList.size()); assertTrue(mIndex < mImportVerifierElemList.size());
mImportVerifierElemList.get(mIndex).onEntryCreated(entry); mImportVerifierElemList.get(mIndex).onEntryCreated(entry);
mIndex++; mIndex++;
} }
public void onParsingEnd() { public void onEnd() {
for (ImportVerifierElem elem : mImportVerifierElemList) { for (ImportVerifierElem elem : mImportVerifierElemList) {
elem.onParsingEnd(); elem.onParsingEnd();
elem.verifyResolver(); elem.verifyResolver();
@@ -802,6 +802,7 @@ class CustomMockContext extends MockContext {
private final ExportTestResolver mResolver; private final ExportTestResolver mResolver;
private final int mVCardType; private final int mVCardType;
private final boolean mIsV30; private final boolean mIsV30;
private final boolean mIsDoCoMo;
// To allow duplication, use list instead of set. // To allow duplication, use list instead of set.
// When null, we don't need to do the verification. // When null, we don't need to do the verification.
@@ -813,6 +814,7 @@ class CustomMockContext extends MockContext {
mVCardVerifierInternal = new VCardVerifierInternal(); mVCardVerifierInternal = new VCardVerifierInternal();
mResolver = resolver; mResolver = resolver;
mIsV30 = VCardConfig.isV30(vcardType); mIsV30 = VCardConfig.isV30(vcardType);
mIsDoCoMo = VCardConfig.isDoCoMo(vcardType);
mVCardType = vcardType; mVCardType = vcardType;
} }
@@ -831,6 +833,8 @@ class CustomMockContext extends MockContext {
PropertyNodesVerifierElem elem = addPropertyNodesVerifierElem(); PropertyNodesVerifierElem elem = addPropertyNodesVerifierElem();
if (mIsV30) { if (mIsV30) {
elem.addNodeWithOrder("N", "").addNodeWithOrder("FN", ""); elem.addNodeWithOrder("N", "").addNodeWithOrder("FN", "");
} else if (mIsDoCoMo) {
elem.addNodeWithOrder("N", "");
} }
return elem; return elem;
} }
@@ -852,14 +856,14 @@ class CustomMockContext extends MockContext {
private void verifyOneVCard(final String vcard) { private void verifyOneVCard(final String vcard) {
// Log.d("@@@", vcard); // Log.d("@@@", vcard);
final VCardBuilder builder; final VCardInterpreter builder;
if (mImportVerifier != null) { if (mImportVerifier != null) {
final VNodeBuilder vnodeBuilder = mPropertyNodesVerifier; final VNodeBuilder vnodeBuilder = mPropertyNodesVerifier;
final VCardDataBuilder vcardDataBuilder = final VCardEntryConstructor vcardDataBuilder =
new VCardDataBuilder(mVCardType); new VCardEntryConstructor(mVCardType);
vcardDataBuilder.addEntryHandler(mImportVerifier); vcardDataBuilder.addEntryHandler(mImportVerifier);
if (mPropertyNodesVerifier != null) { if (mPropertyNodesVerifier != null) {
builder = new VCardBuilderCollection(Arrays.asList( builder = new VCardInterPreterCollection(Arrays.asList(
mPropertyNodesVerifier, vcardDataBuilder)); mPropertyNodesVerifier, vcardDataBuilder));
} else { } else {
builder = vnodeBuilder; builder = vnodeBuilder;

View File

@@ -16,7 +16,7 @@
package com.android.unit_tests.vcard; package com.android.unit_tests.vcard;
import android.content.ContentValues; import android.content.ContentValues;
import android.pim.vcard.VCardBuilder; import android.pim.vcard.VCardInterpreter;
import android.pim.vcard.VCardConfig; import android.pim.vcard.VCardConfig;
import android.util.CharsetUtils; import android.util.CharsetUtils;
import android.util.Log; import android.util.Log;
@@ -39,8 +39,8 @@ import java.util.List;
* *
* Previously used in main vCard handling code but now exists only for testing. * Previously used in main vCard handling code but now exists only for testing.
*/ */
public class VNodeBuilder implements VCardBuilder { public class VNodeBuilder implements VCardInterpreter {
static private String LOG_TAG = "VDATABuilder"; static private String LOG_TAG = "VNodeBuilder";
/** /**
* If there's no other information available, this class uses this charset for encoding * If there's no other information available, this class uses this charset for encoding