diff options
author | Daisuke Miyakawa <dmiyakawa@google.com> | 2010-05-14 11:17:46 -0700 |
---|---|---|
committer | Daisuke Miyakawa <dmiyakawa@google.com> | 2010-05-20 11:25:37 -0700 |
commit | 64545a8ced5aa350e917ab1824a1c06a14a96532 (patch) | |
tree | 54d911229c87a45f815c0a350a8a093eff877034 /core | |
parent | ee714613e8f7743d21de164dfb4cd9bea4ae85f1 (diff) | |
download | frameworks_base-64545a8ced5aa350e917ab1824a1c06a14a96532.zip frameworks_base-64545a8ced5aa350e917ab1824a1c06a14a96532.tar.gz frameworks_base-64545a8ced5aa350e917ab1824a1c06a14a96532.tar.bz2 |
Make vCard code a separated static library.
- Move the library to a separate directory in framewokr/base, and rename its package from
android.pim.vcard to com.android.vcard.
- Move all tests for the library under the directory.
- Confirm all tests for vCard are successful.
It would be better for us to have this directory somewhere else (like external/).
But I'll submit this here now and move it to the right place as soon as possible.
From the view of build mechanism, we can do that immediately.
BUG: 2689523
Change-Id: I435e10571b7160bfcc029bed7c37aaac1c6fd69a
Diffstat (limited to 'core')
64 files changed, 0 insertions, 13393 deletions
diff --git a/core/java/android/pim/vcard/JapaneseUtils.java b/core/java/android/pim/vcard/JapaneseUtils.java deleted file mode 100644 index dcfe980..0000000 --- a/core/java/android/pim/vcard/JapaneseUtils.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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 { - sHalfWidthMap.put('\u3001', "\uFF64"); - sHalfWidthMap.put('\u3002', "\uFF61"); - sHalfWidthMap.put('\u300C', "\uFF62"); - sHalfWidthMap.put('\u300D', "\uFF63"); - sHalfWidthMap.put('\u301C', "~"); - sHalfWidthMap.put('\u3041', "\uFF67"); - sHalfWidthMap.put('\u3042', "\uFF71"); - sHalfWidthMap.put('\u3043', "\uFF68"); - sHalfWidthMap.put('\u3044', "\uFF72"); - sHalfWidthMap.put('\u3045', "\uFF69"); - sHalfWidthMap.put('\u3046', "\uFF73"); - sHalfWidthMap.put('\u3047', "\uFF6A"); - sHalfWidthMap.put('\u3048', "\uFF74"); - sHalfWidthMap.put('\u3049', "\uFF6B"); - sHalfWidthMap.put('\u304A', "\uFF75"); - sHalfWidthMap.put('\u304B', "\uFF76"); - sHalfWidthMap.put('\u304C', "\uFF76\uFF9E"); - sHalfWidthMap.put('\u304D', "\uFF77"); - sHalfWidthMap.put('\u304E', "\uFF77\uFF9E"); - sHalfWidthMap.put('\u304F', "\uFF78"); - sHalfWidthMap.put('\u3050', "\uFF78\uFF9E"); - sHalfWidthMap.put('\u3051', "\uFF79"); - sHalfWidthMap.put('\u3052', "\uFF79\uFF9E"); - sHalfWidthMap.put('\u3053', "\uFF7A"); - sHalfWidthMap.put('\u3054', "\uFF7A\uFF9E"); - sHalfWidthMap.put('\u3055', "\uFF7B"); - sHalfWidthMap.put('\u3056', "\uFF7B\uFF9E"); - sHalfWidthMap.put('\u3057', "\uFF7C"); - sHalfWidthMap.put('\u3058', "\uFF7C\uFF9E"); - sHalfWidthMap.put('\u3059', "\uFF7D"); - sHalfWidthMap.put('\u305A', "\uFF7D\uFF9E"); - sHalfWidthMap.put('\u305B', "\uFF7E"); - sHalfWidthMap.put('\u305C', "\uFF7E\uFF9E"); - sHalfWidthMap.put('\u305D', "\uFF7F"); - sHalfWidthMap.put('\u305E', "\uFF7F\uFF9E"); - sHalfWidthMap.put('\u305F', "\uFF80"); - sHalfWidthMap.put('\u3060', "\uFF80\uFF9E"); - sHalfWidthMap.put('\u3061', "\uFF81"); - sHalfWidthMap.put('\u3062', "\uFF81\uFF9E"); - sHalfWidthMap.put('\u3063', "\uFF6F"); - sHalfWidthMap.put('\u3064', "\uFF82"); - sHalfWidthMap.put('\u3065', "\uFF82\uFF9E"); - sHalfWidthMap.put('\u3066', "\uFF83"); - sHalfWidthMap.put('\u3067', "\uFF83\uFF9E"); - sHalfWidthMap.put('\u3068', "\uFF84"); - sHalfWidthMap.put('\u3069', "\uFF84\uFF9E"); - sHalfWidthMap.put('\u306A', "\uFF85"); - sHalfWidthMap.put('\u306B', "\uFF86"); - sHalfWidthMap.put('\u306C', "\uFF87"); - sHalfWidthMap.put('\u306D', "\uFF88"); - sHalfWidthMap.put('\u306E', "\uFF89"); - sHalfWidthMap.put('\u306F', "\uFF8A"); - sHalfWidthMap.put('\u3070', "\uFF8A\uFF9E"); - sHalfWidthMap.put('\u3071', "\uFF8A\uFF9F"); - sHalfWidthMap.put('\u3072', "\uFF8B"); - sHalfWidthMap.put('\u3073', "\uFF8B\uFF9E"); - sHalfWidthMap.put('\u3074', "\uFF8B\uFF9F"); - sHalfWidthMap.put('\u3075', "\uFF8C"); - sHalfWidthMap.put('\u3076', "\uFF8C\uFF9E"); - sHalfWidthMap.put('\u3077', "\uFF8C\uFF9F"); - sHalfWidthMap.put('\u3078', "\uFF8D"); - sHalfWidthMap.put('\u3079', "\uFF8D\uFF9E"); - sHalfWidthMap.put('\u307A', "\uFF8D\uFF9F"); - sHalfWidthMap.put('\u307B', "\uFF8E"); - sHalfWidthMap.put('\u307C', "\uFF8E\uFF9E"); - sHalfWidthMap.put('\u307D', "\uFF8E\uFF9F"); - sHalfWidthMap.put('\u307E', "\uFF8F"); - sHalfWidthMap.put('\u307F', "\uFF90"); - sHalfWidthMap.put('\u3080', "\uFF91"); - sHalfWidthMap.put('\u3081', "\uFF92"); - sHalfWidthMap.put('\u3082', "\uFF93"); - sHalfWidthMap.put('\u3083', "\uFF6C"); - sHalfWidthMap.put('\u3084', "\uFF94"); - sHalfWidthMap.put('\u3085', "\uFF6D"); - sHalfWidthMap.put('\u3086', "\uFF95"); - sHalfWidthMap.put('\u3087', "\uFF6E"); - sHalfWidthMap.put('\u3088', "\uFF96"); - sHalfWidthMap.put('\u3089', "\uFF97"); - sHalfWidthMap.put('\u308A', "\uFF98"); - sHalfWidthMap.put('\u308B', "\uFF99"); - sHalfWidthMap.put('\u308C', "\uFF9A"); - sHalfWidthMap.put('\u308D', "\uFF9B"); - sHalfWidthMap.put('\u308E', "\uFF9C"); - sHalfWidthMap.put('\u308F', "\uFF9C"); - sHalfWidthMap.put('\u3090', "\uFF72"); - sHalfWidthMap.put('\u3091', "\uFF74"); - sHalfWidthMap.put('\u3092', "\uFF66"); - sHalfWidthMap.put('\u3093', "\uFF9D"); - sHalfWidthMap.put('\u309B', "\uFF9E"); - sHalfWidthMap.put('\u309C', "\uFF9F"); - sHalfWidthMap.put('\u30A1', "\uFF67"); - sHalfWidthMap.put('\u30A2', "\uFF71"); - sHalfWidthMap.put('\u30A3', "\uFF68"); - sHalfWidthMap.put('\u30A4', "\uFF72"); - sHalfWidthMap.put('\u30A5', "\uFF69"); - sHalfWidthMap.put('\u30A6', "\uFF73"); - sHalfWidthMap.put('\u30A7', "\uFF6A"); - sHalfWidthMap.put('\u30A8', "\uFF74"); - sHalfWidthMap.put('\u30A9', "\uFF6B"); - sHalfWidthMap.put('\u30AA', "\uFF75"); - sHalfWidthMap.put('\u30AB', "\uFF76"); - sHalfWidthMap.put('\u30AC', "\uFF76\uFF9E"); - sHalfWidthMap.put('\u30AD', "\uFF77"); - sHalfWidthMap.put('\u30AE', "\uFF77\uFF9E"); - sHalfWidthMap.put('\u30AF', "\uFF78"); - sHalfWidthMap.put('\u30B0', "\uFF78\uFF9E"); - sHalfWidthMap.put('\u30B1', "\uFF79"); - sHalfWidthMap.put('\u30B2', "\uFF79\uFF9E"); - sHalfWidthMap.put('\u30B3', "\uFF7A"); - sHalfWidthMap.put('\u30B4', "\uFF7A\uFF9E"); - sHalfWidthMap.put('\u30B5', "\uFF7B"); - sHalfWidthMap.put('\u30B6', "\uFF7B\uFF9E"); - sHalfWidthMap.put('\u30B7', "\uFF7C"); - sHalfWidthMap.put('\u30B8', "\uFF7C\uFF9E"); - sHalfWidthMap.put('\u30B9', "\uFF7D"); - sHalfWidthMap.put('\u30BA', "\uFF7D\uFF9E"); - sHalfWidthMap.put('\u30BB', "\uFF7E"); - sHalfWidthMap.put('\u30BC', "\uFF7E\uFF9E"); - sHalfWidthMap.put('\u30BD', "\uFF7F"); - sHalfWidthMap.put('\u30BE', "\uFF7F\uFF9E"); - sHalfWidthMap.put('\u30BF', "\uFF80"); - sHalfWidthMap.put('\u30C0', "\uFF80\uFF9E"); - sHalfWidthMap.put('\u30C1', "\uFF81"); - sHalfWidthMap.put('\u30C2', "\uFF81\uFF9E"); - sHalfWidthMap.put('\u30C3', "\uFF6F"); - sHalfWidthMap.put('\u30C4', "\uFF82"); - sHalfWidthMap.put('\u30C5', "\uFF82\uFF9E"); - sHalfWidthMap.put('\u30C6', "\uFF83"); - sHalfWidthMap.put('\u30C7', "\uFF83\uFF9E"); - sHalfWidthMap.put('\u30C8', "\uFF84"); - sHalfWidthMap.put('\u30C9', "\uFF84\uFF9E"); - sHalfWidthMap.put('\u30CA', "\uFF85"); - sHalfWidthMap.put('\u30CB', "\uFF86"); - sHalfWidthMap.put('\u30CC', "\uFF87"); - sHalfWidthMap.put('\u30CD', "\uFF88"); - sHalfWidthMap.put('\u30CE', "\uFF89"); - sHalfWidthMap.put('\u30CF', "\uFF8A"); - sHalfWidthMap.put('\u30D0', "\uFF8A\uFF9E"); - sHalfWidthMap.put('\u30D1', "\uFF8A\uFF9F"); - sHalfWidthMap.put('\u30D2', "\uFF8B"); - sHalfWidthMap.put('\u30D3', "\uFF8B\uFF9E"); - sHalfWidthMap.put('\u30D4', "\uFF8B\uFF9F"); - sHalfWidthMap.put('\u30D5', "\uFF8C"); - sHalfWidthMap.put('\u30D6', "\uFF8C\uFF9E"); - sHalfWidthMap.put('\u30D7', "\uFF8C\uFF9F"); - sHalfWidthMap.put('\u30D8', "\uFF8D"); - sHalfWidthMap.put('\u30D9', "\uFF8D\uFF9E"); - sHalfWidthMap.put('\u30DA', "\uFF8D\uFF9F"); - sHalfWidthMap.put('\u30DB', "\uFF8E"); - sHalfWidthMap.put('\u30DC', "\uFF8E\uFF9E"); - sHalfWidthMap.put('\u30DD', "\uFF8E\uFF9F"); - sHalfWidthMap.put('\u30DE', "\uFF8F"); - sHalfWidthMap.put('\u30DF', "\uFF90"); - sHalfWidthMap.put('\u30E0', "\uFF91"); - sHalfWidthMap.put('\u30E1', "\uFF92"); - sHalfWidthMap.put('\u30E2', "\uFF93"); - sHalfWidthMap.put('\u30E3', "\uFF6C"); - sHalfWidthMap.put('\u30E4', "\uFF94"); - sHalfWidthMap.put('\u30E5', "\uFF6D"); - sHalfWidthMap.put('\u30E6', "\uFF95"); - sHalfWidthMap.put('\u30E7', "\uFF6E"); - sHalfWidthMap.put('\u30E8', "\uFF96"); - sHalfWidthMap.put('\u30E9', "\uFF97"); - sHalfWidthMap.put('\u30EA', "\uFF98"); - sHalfWidthMap.put('\u30EB', "\uFF99"); - sHalfWidthMap.put('\u30EC', "\uFF9A"); - sHalfWidthMap.put('\u30ED', "\uFF9B"); - sHalfWidthMap.put('\u30EE', "\uFF9C"); - sHalfWidthMap.put('\u30EF', "\uFF9C"); - sHalfWidthMap.put('\u30F0', "\uFF72"); - sHalfWidthMap.put('\u30F1', "\uFF74"); - sHalfWidthMap.put('\u30F2', "\uFF66"); - sHalfWidthMap.put('\u30F3', "\uFF9D"); - sHalfWidthMap.put('\u30F4', "\uFF73\uFF9E"); - sHalfWidthMap.put('\u30F5', "\uFF76"); - sHalfWidthMap.put('\u30F6', "\uFF79"); - sHalfWidthMap.put('\u30FB', "\uFF65"); - sHalfWidthMap.put('\u30FC', "\uFF70"); - sHalfWidthMap.put('\uFF01', "!"); - sHalfWidthMap.put('\uFF02', "\""); - sHalfWidthMap.put('\uFF03', "#"); - sHalfWidthMap.put('\uFF04', "$"); - sHalfWidthMap.put('\uFF05', "%"); - sHalfWidthMap.put('\uFF06', "&"); - sHalfWidthMap.put('\uFF07', "'"); - sHalfWidthMap.put('\uFF08', "("); - sHalfWidthMap.put('\uFF09', ")"); - sHalfWidthMap.put('\uFF0A', "*"); - sHalfWidthMap.put('\uFF0B', "+"); - sHalfWidthMap.put('\uFF0C', ","); - sHalfWidthMap.put('\uFF0D', "-"); - sHalfWidthMap.put('\uFF0E', "."); - sHalfWidthMap.put('\uFF0F', "/"); - sHalfWidthMap.put('\uFF10', "0"); - sHalfWidthMap.put('\uFF11', "1"); - sHalfWidthMap.put('\uFF12', "2"); - sHalfWidthMap.put('\uFF13', "3"); - sHalfWidthMap.put('\uFF14', "4"); - sHalfWidthMap.put('\uFF15', "5"); - sHalfWidthMap.put('\uFF16', "6"); - sHalfWidthMap.put('\uFF17', "7"); - sHalfWidthMap.put('\uFF18', "8"); - sHalfWidthMap.put('\uFF19', "9"); - sHalfWidthMap.put('\uFF1A', ":"); - sHalfWidthMap.put('\uFF1B', ";"); - sHalfWidthMap.put('\uFF1C', "<"); - sHalfWidthMap.put('\uFF1D', "="); - sHalfWidthMap.put('\uFF1E', ">"); - sHalfWidthMap.put('\uFF1F', "?"); - sHalfWidthMap.put('\uFF20', "@"); - sHalfWidthMap.put('\uFF21', "A"); - sHalfWidthMap.put('\uFF22', "B"); - sHalfWidthMap.put('\uFF23', "C"); - sHalfWidthMap.put('\uFF24', "D"); - sHalfWidthMap.put('\uFF25', "E"); - sHalfWidthMap.put('\uFF26', "F"); - sHalfWidthMap.put('\uFF27', "G"); - sHalfWidthMap.put('\uFF28', "H"); - sHalfWidthMap.put('\uFF29', "I"); - sHalfWidthMap.put('\uFF2A', "J"); - sHalfWidthMap.put('\uFF2B', "K"); - sHalfWidthMap.put('\uFF2C', "L"); - sHalfWidthMap.put('\uFF2D', "M"); - sHalfWidthMap.put('\uFF2E', "N"); - sHalfWidthMap.put('\uFF2F', "O"); - sHalfWidthMap.put('\uFF30', "P"); - sHalfWidthMap.put('\uFF31', "Q"); - sHalfWidthMap.put('\uFF32', "R"); - sHalfWidthMap.put('\uFF33', "S"); - sHalfWidthMap.put('\uFF34', "T"); - sHalfWidthMap.put('\uFF35', "U"); - sHalfWidthMap.put('\uFF36', "V"); - sHalfWidthMap.put('\uFF37', "W"); - sHalfWidthMap.put('\uFF38', "X"); - sHalfWidthMap.put('\uFF39', "Y"); - sHalfWidthMap.put('\uFF3A', "Z"); - sHalfWidthMap.put('\uFF3B', "["); - sHalfWidthMap.put('\uFF3C', "\\"); - sHalfWidthMap.put('\uFF3D', "]"); - sHalfWidthMap.put('\uFF3E', "^"); - sHalfWidthMap.put('\uFF3F', "_"); - sHalfWidthMap.put('\uFF41', "a"); - sHalfWidthMap.put('\uFF42', "b"); - sHalfWidthMap.put('\uFF43', "c"); - sHalfWidthMap.put('\uFF44', "d"); - sHalfWidthMap.put('\uFF45', "e"); - sHalfWidthMap.put('\uFF46', "f"); - sHalfWidthMap.put('\uFF47', "g"); - sHalfWidthMap.put('\uFF48', "h"); - sHalfWidthMap.put('\uFF49', "i"); - sHalfWidthMap.put('\uFF4A', "j"); - sHalfWidthMap.put('\uFF4B', "k"); - sHalfWidthMap.put('\uFF4C', "l"); - sHalfWidthMap.put('\uFF4D', "m"); - sHalfWidthMap.put('\uFF4E', "n"); - sHalfWidthMap.put('\uFF4F', "o"); - sHalfWidthMap.put('\uFF50', "p"); - sHalfWidthMap.put('\uFF51', "q"); - sHalfWidthMap.put('\uFF52', "r"); - sHalfWidthMap.put('\uFF53', "s"); - sHalfWidthMap.put('\uFF54', "t"); - sHalfWidthMap.put('\uFF55', "u"); - sHalfWidthMap.put('\uFF56', "v"); - sHalfWidthMap.put('\uFF57', "w"); - sHalfWidthMap.put('\uFF58', "x"); - sHalfWidthMap.put('\uFF59', "y"); - sHalfWidthMap.put('\uFF5A', "z"); - sHalfWidthMap.put('\uFF5B', "{"); - sHalfWidthMap.put('\uFF5C', "|"); - sHalfWidthMap.put('\uFF5D', "}"); - sHalfWidthMap.put('\uFF5E', "~"); - sHalfWidthMap.put('\uFF61', "\uFF61"); - sHalfWidthMap.put('\uFF62', "\uFF62"); - sHalfWidthMap.put('\uFF63', "\uFF63"); - sHalfWidthMap.put('\uFF64', "\uFF64"); - sHalfWidthMap.put('\uFF65', "\uFF65"); - sHalfWidthMap.put('\uFF66', "\uFF66"); - sHalfWidthMap.put('\uFF67', "\uFF67"); - sHalfWidthMap.put('\uFF68', "\uFF68"); - sHalfWidthMap.put('\uFF69', "\uFF69"); - sHalfWidthMap.put('\uFF6A', "\uFF6A"); - sHalfWidthMap.put('\uFF6B', "\uFF6B"); - sHalfWidthMap.put('\uFF6C', "\uFF6C"); - sHalfWidthMap.put('\uFF6D', "\uFF6D"); - sHalfWidthMap.put('\uFF6E', "\uFF6E"); - sHalfWidthMap.put('\uFF6F', "\uFF6F"); - sHalfWidthMap.put('\uFF70', "\uFF70"); - sHalfWidthMap.put('\uFF71', "\uFF71"); - sHalfWidthMap.put('\uFF72', "\uFF72"); - sHalfWidthMap.put('\uFF73', "\uFF73"); - sHalfWidthMap.put('\uFF74', "\uFF74"); - sHalfWidthMap.put('\uFF75', "\uFF75"); - sHalfWidthMap.put('\uFF76', "\uFF76"); - sHalfWidthMap.put('\uFF77', "\uFF77"); - sHalfWidthMap.put('\uFF78', "\uFF78"); - sHalfWidthMap.put('\uFF79', "\uFF79"); - sHalfWidthMap.put('\uFF7A', "\uFF7A"); - sHalfWidthMap.put('\uFF7B', "\uFF7B"); - sHalfWidthMap.put('\uFF7C', "\uFF7C"); - sHalfWidthMap.put('\uFF7D', "\uFF7D"); - sHalfWidthMap.put('\uFF7E', "\uFF7E"); - sHalfWidthMap.put('\uFF7F', "\uFF7F"); - sHalfWidthMap.put('\uFF80', "\uFF80"); - sHalfWidthMap.put('\uFF81', "\uFF81"); - sHalfWidthMap.put('\uFF82', "\uFF82"); - sHalfWidthMap.put('\uFF83', "\uFF83"); - sHalfWidthMap.put('\uFF84', "\uFF84"); - sHalfWidthMap.put('\uFF85', "\uFF85"); - sHalfWidthMap.put('\uFF86', "\uFF86"); - sHalfWidthMap.put('\uFF87', "\uFF87"); - sHalfWidthMap.put('\uFF88', "\uFF88"); - sHalfWidthMap.put('\uFF89', "\uFF89"); - sHalfWidthMap.put('\uFF8A', "\uFF8A"); - sHalfWidthMap.put('\uFF8B', "\uFF8B"); - sHalfWidthMap.put('\uFF8C', "\uFF8C"); - sHalfWidthMap.put('\uFF8D', "\uFF8D"); - sHalfWidthMap.put('\uFF8E', "\uFF8E"); - sHalfWidthMap.put('\uFF8F', "\uFF8F"); - sHalfWidthMap.put('\uFF90', "\uFF90"); - sHalfWidthMap.put('\uFF91', "\uFF91"); - sHalfWidthMap.put('\uFF92', "\uFF92"); - sHalfWidthMap.put('\uFF93', "\uFF93"); - sHalfWidthMap.put('\uFF94', "\uFF94"); - sHalfWidthMap.put('\uFF95', "\uFF95"); - sHalfWidthMap.put('\uFF96', "\uFF96"); - sHalfWidthMap.put('\uFF97', "\uFF97"); - sHalfWidthMap.put('\uFF98', "\uFF98"); - sHalfWidthMap.put('\uFF99', "\uFF99"); - sHalfWidthMap.put('\uFF9A', "\uFF9A"); - sHalfWidthMap.put('\uFF9B', "\uFF9B"); - sHalfWidthMap.put('\uFF9C', "\uFF9C"); - sHalfWidthMap.put('\uFF9D', "\uFF9D"); - sHalfWidthMap.put('\uFF9E', "\uFF9E"); - sHalfWidthMap.put('\uFF9F', "\uFF9F"); - sHalfWidthMap.put('\uFFE5', "\u005C\u005C"); - } - - /** - * Returns half-width version of that character if possible. Returns null if not possible - * @param ch input character - * @return CharSequence object if the mapping for ch exists. Return null otherwise. - */ - public static String tryGetHalfWidthText(final char ch) { - if (sHalfWidthMap.containsKey(ch)) { - return sHalfWidthMap.get(ch); - } else { - return null; - } - } -} diff --git a/core/java/android/pim/vcard/VCardBuilder.java b/core/java/android/pim/vcard/VCardBuilder.java deleted file mode 100644 index 789b5f8..0000000 --- a/core/java/android/pim/vcard/VCardBuilder.java +++ /dev/null @@ -1,1996 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android.pim.vcard; - -import android.content.ContentValues; -import android.provider.ContactsContract.CommonDataKinds.Email; -import android.provider.ContactsContract.CommonDataKinds.Event; -import android.provider.ContactsContract.CommonDataKinds.Im; -import android.provider.ContactsContract.CommonDataKinds.Nickname; -import android.provider.ContactsContract.CommonDataKinds.Note; -import android.provider.ContactsContract.CommonDataKinds.Organization; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.Photo; -import android.provider.ContactsContract.CommonDataKinds.Relation; -import android.provider.ContactsContract.CommonDataKinds.StructuredName; -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; -import android.provider.ContactsContract.CommonDataKinds.Website; -import android.telephony.PhoneNumberUtils; -import android.text.TextUtils; -import android.util.CharsetUtils; -import android.util.Log; - -import org.apache.commons.codec.binary.Base64; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.UnsupportedCharsetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * <p> - * The class which lets users create their own vCard String. Typical usage is as follows: - * </p> - * <pre class="prettyprint">final VCardBuilder builder = new VCardBuilder(vcardType); - * builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE)) - * .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE)) - * .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE)) - * .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE)) - * .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE)) - * .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE)) - * .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE)) - * .appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE)) - * .appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE)) - * .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE)) - * .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE)) - * .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE)); - * return builder.toString();</pre> - */ -public class VCardBuilder { - private static final String LOG_TAG = "VCardBuilder"; - - // If you add the other element, please check all the columns are able to be - // converted to String. - // - // e.g. BLOB is not what we can handle here now. - private static final Set<String> sAllowedAndroidPropertySet = - Collections.unmodifiableSet(new HashSet<String>(Arrays.asList( - Nickname.CONTENT_ITEM_TYPE, Event.CONTENT_ITEM_TYPE, - Relation.CONTENT_ITEM_TYPE))); - - public static final int DEFAULT_PHONE_TYPE = Phone.TYPE_HOME; - public static final int DEFAULT_POSTAL_TYPE = StructuredPostal.TYPE_HOME; - public static final int DEFAULT_EMAIL_TYPE = Email.TYPE_OTHER; - - private static final String VCARD_DATA_VCARD = "VCARD"; - private static final String VCARD_DATA_PUBLIC = "PUBLIC"; - - private static final String VCARD_PARAM_SEPARATOR = ";"; - private static final String VCARD_END_OF_LINE = "\r\n"; - private static final String VCARD_DATA_SEPARATOR = ":"; - private static final String VCARD_ITEM_SEPARATOR = ";"; - private static final String VCARD_WS = " "; - private static final String VCARD_PARAM_EQUAL = "="; - - private static final String VCARD_PARAM_ENCODING_QP = - "ENCODING=" + VCardConstants.PARAM_ENCODING_QP; - private static final String VCARD_PARAM_ENCODING_BASE64_V21 = - "ENCODING=" + VCardConstants.PARAM_ENCODING_BASE64; - private static final String VCARD_PARAM_ENCODING_BASE64_V30 = - "ENCODING=" + VCardConstants.PARAM_ENCODING_B; - - private static final String SHIFT_JIS = "SHIFT_JIS"; - - private final int mVCardType; - - private final boolean mIsV30; - private final boolean mIsJapaneseMobilePhone; - private final boolean mOnlyOneNoteFieldIsAvailable; - private final boolean mIsDoCoMo; - private final boolean mShouldUseQuotedPrintable; - private final boolean mUsesAndroidProperty; - private final boolean mUsesDefactProperty; - private final boolean mAppendTypeParamName; - private final boolean mRefrainsQPToNameProperties; - private final boolean mNeedsToConvertPhoneticString; - - private final boolean mShouldAppendCharsetParam; - - private final String mCharset; - private final String mVCardCharsetParameter; - - private StringBuilder mBuilder; - private boolean mEndAppended; - - public VCardBuilder(final int vcardType) { - // Default charset should be used - this(vcardType, null); - } - - /** - * @param vcardType - * @param charset If null, we use default charset for export. - */ - public VCardBuilder(final int vcardType, String charset) { - mVCardType = vcardType; - - mIsV30 = VCardConfig.isV30(vcardType); - mShouldUseQuotedPrintable = VCardConfig.shouldUseQuotedPrintable(vcardType); - mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); - mIsJapaneseMobilePhone = VCardConfig.needsToConvertPhoneticString(vcardType); - mOnlyOneNoteFieldIsAvailable = VCardConfig.onlyOneNoteFieldIsAvailable(vcardType); - mUsesAndroidProperty = VCardConfig.usesAndroidSpecificProperty(vcardType); - mUsesDefactProperty = VCardConfig.usesDefactProperty(vcardType); - mRefrainsQPToNameProperties = VCardConfig.shouldRefrainQPToNameProperties(vcardType); - mAppendTypeParamName = VCardConfig.appendTypeParamName(vcardType); - mNeedsToConvertPhoneticString = VCardConfig.needsToConvertPhoneticString(vcardType); - - // vCard 2.1 requires charset. - // vCard 3.0 does not allow it but we found some devices use it to determine - // the exact charset. - // We currently append it only when charset other than UTF_8 is used. - mShouldAppendCharsetParam = !(mIsV30 && "UTF-8".equalsIgnoreCase(charset)); - - if (VCardConfig.isDoCoMo(vcardType)) { - if (!SHIFT_JIS.equalsIgnoreCase(charset)) { - Log.w(LOG_TAG, - "The charset \"" + charset + "\" is used while " - + SHIFT_JIS + " is needed to be used."); - if (TextUtils.isEmpty(charset)) { - mCharset = SHIFT_JIS; - } else { - try { - charset = CharsetUtils.charsetForVendor(charset).name(); - } catch (UnsupportedCharsetException e) { - Log.i(LOG_TAG, - "Career-specific \"" + charset + "\" was not found (as usual). " - + "Use it as is."); - } - mCharset = charset; - } - } else { - if (mIsDoCoMo) { - try { - charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); - } catch (UnsupportedCharsetException e) { - Log.e(LOG_TAG, - "DoCoMo-specific SHIFT_JIS was not found. " - + "Use SHIFT_JIS as is."); - charset = SHIFT_JIS; - } - } else { - try { - charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); - } catch (UnsupportedCharsetException e) { - Log.e(LOG_TAG, - "Career-specific SHIFT_JIS was not found. " - + "Use SHIFT_JIS as is."); - charset = SHIFT_JIS; - } - } - mCharset = charset; - } - mVCardCharsetParameter = "CHARSET=" + SHIFT_JIS; - } else { - if (TextUtils.isEmpty(charset)) { - Log.i(LOG_TAG, - "Use the charset \"" + VCardConfig.DEFAULT_EXPORT_CHARSET - + "\" for export."); - mCharset = VCardConfig.DEFAULT_EXPORT_CHARSET; - mVCardCharsetParameter = "CHARSET=" + VCardConfig.DEFAULT_EXPORT_CHARSET; - } else { - try { - charset = CharsetUtils.charsetForVendor(charset).name(); - } catch (UnsupportedCharsetException e) { - Log.i(LOG_TAG, - "Career-specific \"" + charset + "\" was not found (as usual). " - + "Use it as is."); - } - mCharset = charset; - mVCardCharsetParameter = "CHARSET=" + charset; - } - } - clear(); - } - - public void clear() { - mBuilder = new StringBuilder(); - mEndAppended = false; - appendLine(VCardConstants.PROPERTY_BEGIN, VCARD_DATA_VCARD); - if (mIsV30) { - appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V30); - } else { - appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V21); - } - } - - private boolean containsNonEmptyName(final ContentValues contentValues) { - final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME); - final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME); - final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME); - final String prefix = contentValues.getAsString(StructuredName.PREFIX); - final String suffix = contentValues.getAsString(StructuredName.SUFFIX); - final String phoneticFamilyName = - contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME); - final String phoneticMiddleName = - contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME); - final String phoneticGivenName = - contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME); - final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME); - return !(TextUtils.isEmpty(familyName) && TextUtils.isEmpty(middleName) && - TextUtils.isEmpty(givenName) && TextUtils.isEmpty(prefix) && - TextUtils.isEmpty(suffix) && TextUtils.isEmpty(phoneticFamilyName) && - TextUtils.isEmpty(phoneticMiddleName) && TextUtils.isEmpty(phoneticGivenName) && - TextUtils.isEmpty(displayName)); - } - - private ContentValues getPrimaryContentValue(final List<ContentValues> contentValuesList) { - ContentValues primaryContentValues = null; - ContentValues subprimaryContentValues = null; - for (ContentValues contentValues : contentValuesList) { - if (contentValues == null){ - continue; - } - Integer isSuperPrimary = contentValues.getAsInteger(StructuredName.IS_SUPER_PRIMARY); - if (isSuperPrimary != null && isSuperPrimary > 0) { - // We choose "super primary" ContentValues. - primaryContentValues = contentValues; - break; - } else if (primaryContentValues == null) { - // We choose the first "primary" ContentValues - // if "super primary" ContentValues does not exist. - final Integer isPrimary = contentValues.getAsInteger(StructuredName.IS_PRIMARY); - if (isPrimary != null && isPrimary > 0 && - containsNonEmptyName(contentValues)) { - primaryContentValues = contentValues; - // Do not break, since there may be ContentValues with "super primary" - // afterword. - } else if (subprimaryContentValues == null && - containsNonEmptyName(contentValues)) { - subprimaryContentValues = contentValues; - } - } - } - - if (primaryContentValues == null) { - if (subprimaryContentValues != null) { - // We choose the first ContentValues if any "primary" ContentValues does not exist. - primaryContentValues = subprimaryContentValues; - } else { - Log.e(LOG_TAG, "All ContentValues given from database is empty."); - primaryContentValues = new ContentValues(); - } - } - - return primaryContentValues; - } - - /** - * For safety, we'll emit just one value around StructuredName, as external importers - * may get confused with multiple "N", "FN", etc. properties, though it is valid in - * vCard spec. - */ - public VCardBuilder appendNameProperties(final List<ContentValues> contentValuesList) { - if (contentValuesList == null || contentValuesList.isEmpty()) { - if (mIsDoCoMo) { - appendLine(VCardConstants.PROPERTY_N, ""); - } else if (mIsV30) { - // vCard 3.0 requires "N" and "FN" properties. - appendLine(VCardConstants.PROPERTY_N, ""); - appendLine(VCardConstants.PROPERTY_FN, ""); - } - return this; - } - - final ContentValues contentValues = getPrimaryContentValue(contentValuesList); - final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME); - final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME); - final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME); - final String prefix = contentValues.getAsString(StructuredName.PREFIX); - final String suffix = contentValues.getAsString(StructuredName.SUFFIX); - final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME); - - if (!TextUtils.isEmpty(familyName) || !TextUtils.isEmpty(givenName)) { - final boolean reallyAppendCharsetParameterToName = - shouldAppendCharsetParam(familyName, givenName, middleName, prefix, suffix); - final boolean reallyUseQuotedPrintableToName = - (!mRefrainsQPToNameProperties && - !(VCardUtils.containsOnlyNonCrLfPrintableAscii(familyName) && - VCardUtils.containsOnlyNonCrLfPrintableAscii(givenName) && - VCardUtils.containsOnlyNonCrLfPrintableAscii(middleName) && - VCardUtils.containsOnlyNonCrLfPrintableAscii(prefix) && - VCardUtils.containsOnlyNonCrLfPrintableAscii(suffix))); - - final String formattedName; - if (!TextUtils.isEmpty(displayName)) { - formattedName = displayName; - } else { - formattedName = VCardUtils.constructNameFromElements( - VCardConfig.getNameOrderType(mVCardType), - familyName, middleName, givenName, prefix, suffix); - } - final boolean reallyAppendCharsetParameterToFN = - shouldAppendCharsetParam(formattedName); - final boolean reallyUseQuotedPrintableToFN = - !mRefrainsQPToNameProperties && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(formattedName); - - final String encodedFamily; - final String encodedGiven; - final String encodedMiddle; - final String encodedPrefix; - final String encodedSuffix; - if (reallyUseQuotedPrintableToName) { - encodedFamily = encodeQuotedPrintable(familyName); - encodedGiven = encodeQuotedPrintable(givenName); - encodedMiddle = encodeQuotedPrintable(middleName); - encodedPrefix = encodeQuotedPrintable(prefix); - encodedSuffix = encodeQuotedPrintable(suffix); - } else { - encodedFamily = escapeCharacters(familyName); - encodedGiven = escapeCharacters(givenName); - encodedMiddle = escapeCharacters(middleName); - encodedPrefix = escapeCharacters(prefix); - encodedSuffix = escapeCharacters(suffix); - } - - final String encodedFormattedname = - (reallyUseQuotedPrintableToFN ? - encodeQuotedPrintable(formattedName) : escapeCharacters(formattedName)); - - mBuilder.append(VCardConstants.PROPERTY_N); - if (mIsDoCoMo) { - if (reallyAppendCharsetParameterToName) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - if (reallyUseQuotedPrintableToName) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCARD_PARAM_ENCODING_QP); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - // DoCoMo phones require that all the elements in the "family name" field. - mBuilder.append(formattedName); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - } else { - if (reallyAppendCharsetParameterToName) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - if (reallyUseQuotedPrintableToName) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCARD_PARAM_ENCODING_QP); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(encodedFamily); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(encodedGiven); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(encodedMiddle); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(encodedPrefix); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(encodedSuffix); - } - mBuilder.append(VCARD_END_OF_LINE); - - // FN property - mBuilder.append(VCardConstants.PROPERTY_FN); - if (reallyAppendCharsetParameterToFN) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - if (reallyUseQuotedPrintableToFN) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCARD_PARAM_ENCODING_QP); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(encodedFormattedname); - mBuilder.append(VCARD_END_OF_LINE); - } else if (!TextUtils.isEmpty(displayName)) { - final boolean reallyUseQuotedPrintableToDisplayName = - (!mRefrainsQPToNameProperties && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(displayName)); - final String encodedDisplayName = - reallyUseQuotedPrintableToDisplayName ? - encodeQuotedPrintable(displayName) : - escapeCharacters(displayName); - - mBuilder.append(VCardConstants.PROPERTY_N); - if (shouldAppendCharsetParam(displayName)) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - if (reallyUseQuotedPrintableToDisplayName) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCARD_PARAM_ENCODING_QP); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(encodedDisplayName); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_END_OF_LINE); - mBuilder.append(VCardConstants.PROPERTY_FN); - - // Note: "CHARSET" param is not allowed in vCard 3.0, but we may add it - // when it would be useful or necessary for external importers, - // assuming the external importer allows this vioration of the spec. - if (shouldAppendCharsetParam(displayName)) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(encodedDisplayName); - mBuilder.append(VCARD_END_OF_LINE); - } else if (mIsV30) { - // vCard 3.0 specification requires these fields. - appendLine(VCardConstants.PROPERTY_N, ""); - appendLine(VCardConstants.PROPERTY_FN, ""); - } else if (mIsDoCoMo) { - appendLine(VCardConstants.PROPERTY_N, ""); - } - - appendPhoneticNameFields(contentValues); - return this; - } - - private void appendPhoneticNameFields(final ContentValues contentValues) { - final String phoneticFamilyName; - final String phoneticMiddleName; - final String phoneticGivenName; - { - final String tmpPhoneticFamilyName = - contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME); - final String tmpPhoneticMiddleName = - contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME); - final String tmpPhoneticGivenName = - contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME); - if (mNeedsToConvertPhoneticString) { - phoneticFamilyName = VCardUtils.toHalfWidthString(tmpPhoneticFamilyName); - phoneticMiddleName = VCardUtils.toHalfWidthString(tmpPhoneticMiddleName); - phoneticGivenName = VCardUtils.toHalfWidthString(tmpPhoneticGivenName); - } else { - phoneticFamilyName = tmpPhoneticFamilyName; - phoneticMiddleName = tmpPhoneticMiddleName; - phoneticGivenName = tmpPhoneticGivenName; - } - } - - if (TextUtils.isEmpty(phoneticFamilyName) - && TextUtils.isEmpty(phoneticMiddleName) - && TextUtils.isEmpty(phoneticGivenName)) { - if (mIsDoCoMo) { - mBuilder.append(VCardConstants.PROPERTY_SOUND); - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCardConstants.PARAM_TYPE_X_IRMC_N); - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_END_OF_LINE); - } - return; - } - - // Try to emit the field(s) related to phonetic name. - if (mIsV30) { - final String sortString = VCardUtils - .constructNameFromElements(mVCardType, - phoneticFamilyName, phoneticMiddleName, phoneticGivenName); - mBuilder.append(VCardConstants.PROPERTY_SORT_STRING); - if (shouldAppendCharsetParam(sortString)) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(escapeCharacters(sortString)); - mBuilder.append(VCARD_END_OF_LINE); - } else if (mIsJapaneseMobilePhone) { - // Note: There is no appropriate property for expressing - // phonetic name (Yomigana in Japanese) in vCard 2.1, while there is in - // vCard 3.0 (SORT-STRING). - // We use DoCoMo's way when the device is Japanese one since it is already - // supported by a lot of Japanese mobile phones. - // This is "X-" property, so any parser hopefully would not get - // confused with this. - // - // Also, DoCoMo's specification requires vCard composer to use just the first - // column. - // i.e. - // good: SOUND;X-IRMC-N:Miyakawa Daisuke;;;; - // bad : SOUND;X-IRMC-N:Miyakawa;Daisuke;;; - mBuilder.append(VCardConstants.PROPERTY_SOUND); - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCardConstants.PARAM_TYPE_X_IRMC_N); - - boolean reallyUseQuotedPrintable = - (!mRefrainsQPToNameProperties - && !(VCardUtils.containsOnlyNonCrLfPrintableAscii( - phoneticFamilyName) - && VCardUtils.containsOnlyNonCrLfPrintableAscii( - phoneticMiddleName) - && VCardUtils.containsOnlyNonCrLfPrintableAscii( - phoneticGivenName))); - - final String encodedPhoneticFamilyName; - final String encodedPhoneticMiddleName; - final String encodedPhoneticGivenName; - if (reallyUseQuotedPrintable) { - encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName); - encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName); - encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName); - } else { - encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName); - encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName); - encodedPhoneticGivenName = escapeCharacters(phoneticGivenName); - } - - if (shouldAppendCharsetParam(encodedPhoneticFamilyName, - encodedPhoneticMiddleName, encodedPhoneticGivenName)) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - { - boolean first = true; - if (!TextUtils.isEmpty(encodedPhoneticFamilyName)) { - mBuilder.append(encodedPhoneticFamilyName); - first = false; - } - if (!TextUtils.isEmpty(encodedPhoneticMiddleName)) { - if (first) { - first = false; - } else { - mBuilder.append(' '); - } - mBuilder.append(encodedPhoneticMiddleName); - } - if (!TextUtils.isEmpty(encodedPhoneticGivenName)) { - if (!first) { - mBuilder.append(' '); - } - mBuilder.append(encodedPhoneticGivenName); - } - } - mBuilder.append(VCARD_ITEM_SEPARATOR); // family;given - mBuilder.append(VCARD_ITEM_SEPARATOR); // given;middle - mBuilder.append(VCARD_ITEM_SEPARATOR); // middle;prefix - mBuilder.append(VCARD_ITEM_SEPARATOR); // prefix;suffix - mBuilder.append(VCARD_END_OF_LINE); - } - - if (mUsesDefactProperty) { - if (!TextUtils.isEmpty(phoneticGivenName)) { - final boolean reallyUseQuotedPrintable = - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName)); - final String encodedPhoneticGivenName; - if (reallyUseQuotedPrintable) { - encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName); - } else { - encodedPhoneticGivenName = escapeCharacters(phoneticGivenName); - } - mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_FIRST_NAME); - if (shouldAppendCharsetParam(phoneticGivenName)) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - if (reallyUseQuotedPrintable) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCARD_PARAM_ENCODING_QP); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(encodedPhoneticGivenName); - mBuilder.append(VCARD_END_OF_LINE); - } // if (!TextUtils.isEmpty(phoneticGivenName)) - if (!TextUtils.isEmpty(phoneticMiddleName)) { - final boolean reallyUseQuotedPrintable = - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName)); - final String encodedPhoneticMiddleName; - if (reallyUseQuotedPrintable) { - encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName); - } else { - encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName); - } - mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_MIDDLE_NAME); - if (shouldAppendCharsetParam(phoneticMiddleName)) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - if (reallyUseQuotedPrintable) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCARD_PARAM_ENCODING_QP); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(encodedPhoneticMiddleName); - mBuilder.append(VCARD_END_OF_LINE); - } // if (!TextUtils.isEmpty(phoneticGivenName)) - if (!TextUtils.isEmpty(phoneticFamilyName)) { - final boolean reallyUseQuotedPrintable = - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName)); - final String encodedPhoneticFamilyName; - if (reallyUseQuotedPrintable) { - encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName); - } else { - encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName); - } - mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_LAST_NAME); - if (shouldAppendCharsetParam(phoneticFamilyName)) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - if (reallyUseQuotedPrintable) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCARD_PARAM_ENCODING_QP); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(encodedPhoneticFamilyName); - mBuilder.append(VCARD_END_OF_LINE); - } // if (!TextUtils.isEmpty(phoneticFamilyName)) - } - } - - public VCardBuilder appendNickNames(final List<ContentValues> contentValuesList) { - final boolean useAndroidProperty; - if (mIsV30) { - useAndroidProperty = false; - } else if (mUsesAndroidProperty) { - useAndroidProperty = true; - } else { - // There's no way to add this field. - return this; - } - if (contentValuesList != null) { - for (ContentValues contentValues : contentValuesList) { - final String nickname = contentValues.getAsString(Nickname.NAME); - if (TextUtils.isEmpty(nickname)) { - continue; - } - if (useAndroidProperty) { - appendAndroidSpecificProperty(Nickname.CONTENT_ITEM_TYPE, contentValues); - } else { - appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_NICKNAME, nickname); - } - } - } - return this; - } - - public VCardBuilder appendPhones(final List<ContentValues> contentValuesList) { - boolean phoneLineExists = false; - if (contentValuesList != null) { - Set<String> phoneSet = new HashSet<String>(); - for (ContentValues contentValues : contentValuesList) { - final Integer typeAsObject = contentValues.getAsInteger(Phone.TYPE); - final String label = contentValues.getAsString(Phone.LABEL); - final Integer isPrimaryAsInteger = contentValues.getAsInteger(Phone.IS_PRIMARY); - final boolean isPrimary = (isPrimaryAsInteger != null ? - (isPrimaryAsInteger > 0) : false); - String phoneNumber = contentValues.getAsString(Phone.NUMBER); - if (phoneNumber != null) { - phoneNumber = phoneNumber.trim(); - } - if (TextUtils.isEmpty(phoneNumber)) { - continue; - } - - // PAGER number needs unformatted "phone number". - final int type = (typeAsObject != null ? typeAsObject : DEFAULT_PHONE_TYPE); - if (type == Phone.TYPE_PAGER || - VCardConfig.refrainPhoneNumberFormatting(mVCardType)) { - phoneLineExists = true; - if (!phoneSet.contains(phoneNumber)) { - phoneSet.add(phoneNumber); - appendTelLine(type, label, phoneNumber, isPrimary); - } - } else { - final List<String> phoneNumberList = splitAndTrimPhoneNumbers(phoneNumber); - if (phoneNumberList.isEmpty()) { - continue; - } - phoneLineExists = true; - for (String actualPhoneNumber : phoneNumberList) { - if (!phoneSet.contains(actualPhoneNumber)) { - final int format = VCardUtils.getPhoneNumberFormat(mVCardType); - final String formattedPhoneNumber = - PhoneNumberUtils.formatNumber(actualPhoneNumber, format); - phoneSet.add(actualPhoneNumber); - appendTelLine(type, label, formattedPhoneNumber, isPrimary); - } - } // for (String actualPhoneNumber : phoneNumberList) { - } - } - } - - if (!phoneLineExists && mIsDoCoMo) { - appendTelLine(Phone.TYPE_HOME, "", "", false); - } - - return this; - } - - /** - * <p> - * Splits a given string expressing phone numbers into several strings, and remove - * unnecessary characters inside them. The size of a returned list becomes 1 when - * no split is needed. - * </p> - * <p> - * The given number "may" have several phone numbers when the contact entry is corrupted - * because of its original source. - * e.g. "111-222-3333 (Miami)\n444-555-6666 (Broward; 305-653-6796 (Miami)" - * </p> - * <p> - * This kind of "phone numbers" will not be created with Android vCard implementation, - * but we may encounter them if the source of the input data has already corrupted - * implementation. - * </p> - * <p> - * To handle this case, this method first splits its input into multiple parts - * (e.g. "111-222-3333 (Miami)", "444-555-6666 (Broward", and 305653-6796 (Miami)") and - * removes unnecessary strings like "(Miami)". - * </p> - * <p> - * Do not call this method when trimming is inappropriate for its receivers. - * </p> - */ - private List<String> splitAndTrimPhoneNumbers(final String phoneNumber) { - final List<String> phoneList = new ArrayList<String>(); - - StringBuilder builder = new StringBuilder(); - final int length = phoneNumber.length(); - for (int i = 0; i < length; i++) { - final char ch = phoneNumber.charAt(i); - if (Character.isDigit(ch) || ch == '+') { - builder.append(ch); - } else if ((ch == ';' || ch == '\n') && builder.length() > 0) { - phoneList.add(builder.toString()); - builder = new StringBuilder(); - } - } - if (builder.length() > 0) { - phoneList.add(builder.toString()); - } - - return phoneList; - } - - public VCardBuilder appendEmails(final List<ContentValues> contentValuesList) { - boolean emailAddressExists = false; - if (contentValuesList != null) { - final Set<String> addressSet = new HashSet<String>(); - for (ContentValues contentValues : contentValuesList) { - String emailAddress = contentValues.getAsString(Email.DATA); - if (emailAddress != null) { - emailAddress = emailAddress.trim(); - } - if (TextUtils.isEmpty(emailAddress)) { - continue; - } - Integer typeAsObject = contentValues.getAsInteger(Email.TYPE); - final int type = (typeAsObject != null ? - typeAsObject : DEFAULT_EMAIL_TYPE); - final String label = contentValues.getAsString(Email.LABEL); - Integer isPrimaryAsInteger = contentValues.getAsInteger(Email.IS_PRIMARY); - final boolean isPrimary = (isPrimaryAsInteger != null ? - (isPrimaryAsInteger > 0) : false); - emailAddressExists = true; - if (!addressSet.contains(emailAddress)) { - addressSet.add(emailAddress); - appendEmailLine(type, label, emailAddress, isPrimary); - } - } - } - - if (!emailAddressExists && mIsDoCoMo) { - appendEmailLine(Email.TYPE_HOME, "", "", false); - } - - return this; - } - - public VCardBuilder appendPostals(final List<ContentValues> contentValuesList) { - if (contentValuesList == null || contentValuesList.isEmpty()) { - if (mIsDoCoMo) { - mBuilder.append(VCardConstants.PROPERTY_ADR); - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCardConstants.PARAM_TYPE_HOME); - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(VCARD_END_OF_LINE); - } - } else { - if (mIsDoCoMo) { - appendPostalsForDoCoMo(contentValuesList); - } else { - appendPostalsForGeneric(contentValuesList); - } - } - - return this; - } - - private static final Map<Integer, Integer> sPostalTypePriorityMap; - - static { - sPostalTypePriorityMap = new HashMap<Integer, Integer>(); - sPostalTypePriorityMap.put(StructuredPostal.TYPE_HOME, 0); - sPostalTypePriorityMap.put(StructuredPostal.TYPE_WORK, 1); - sPostalTypePriorityMap.put(StructuredPostal.TYPE_OTHER, 2); - sPostalTypePriorityMap.put(StructuredPostal.TYPE_CUSTOM, 3); - } - - /** - * Tries to append just one line. If there's no appropriate address - * information, append an empty line. - */ - private void appendPostalsForDoCoMo(final List<ContentValues> contentValuesList) { - int currentPriority = Integer.MAX_VALUE; - int currentType = Integer.MAX_VALUE; - ContentValues currentContentValues = null; - for (final ContentValues contentValues : contentValuesList) { - if (contentValues == null) { - continue; - } - final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE); - final Integer priorityAsInteger = sPostalTypePriorityMap.get(typeAsInteger); - final int priority = - (priorityAsInteger != null ? priorityAsInteger : Integer.MAX_VALUE); - if (priority < currentPriority) { - currentPriority = priority; - currentType = typeAsInteger; - currentContentValues = contentValues; - if (priority == 0) { - break; - } - } - } - - if (currentContentValues == null) { - Log.w(LOG_TAG, "Should not come here. Must have at least one postal data."); - return; - } - - final String label = currentContentValues.getAsString(StructuredPostal.LABEL); - appendPostalLine(currentType, label, currentContentValues, false, true); - } - - private void appendPostalsForGeneric(final List<ContentValues> contentValuesList) { - for (final ContentValues contentValues : contentValuesList) { - if (contentValues == null) { - continue; - } - final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE); - final int type = (typeAsInteger != null ? - typeAsInteger : DEFAULT_POSTAL_TYPE); - final String label = contentValues.getAsString(StructuredPostal.LABEL); - final Integer isPrimaryAsInteger = - contentValues.getAsInteger(StructuredPostal.IS_PRIMARY); - final boolean isPrimary = (isPrimaryAsInteger != null ? - (isPrimaryAsInteger > 0) : false); - appendPostalLine(type, label, contentValues, isPrimary, false); - } - } - - private static class PostalStruct { - final boolean reallyUseQuotedPrintable; - final boolean appendCharset; - final String addressData; - public PostalStruct(final boolean reallyUseQuotedPrintable, - final boolean appendCharset, final String addressData) { - this.reallyUseQuotedPrintable = reallyUseQuotedPrintable; - this.appendCharset = appendCharset; - this.addressData = addressData; - } - } - - /** - * @return null when there's no information available to construct the data. - */ - private PostalStruct tryConstructPostalStruct(ContentValues contentValues) { - // adr-value = 0*6(text-value ";") text-value - // ; PO Box, Extended Address, Street, Locality, Region, Postal - // ; Code, Country Name - final String rawPoBox = contentValues.getAsString(StructuredPostal.POBOX); - final String rawNeighborhood = contentValues.getAsString(StructuredPostal.NEIGHBORHOOD); - final String rawStreet = contentValues.getAsString(StructuredPostal.STREET); - final String rawLocality = contentValues.getAsString(StructuredPostal.CITY); - final String rawRegion = contentValues.getAsString(StructuredPostal.REGION); - final String rawPostalCode = contentValues.getAsString(StructuredPostal.POSTCODE); - final String rawCountry = contentValues.getAsString(StructuredPostal.COUNTRY); - final String[] rawAddressArray = new String[]{ - rawPoBox, rawNeighborhood, rawStreet, rawLocality, - rawRegion, rawPostalCode, rawCountry}; - if (!VCardUtils.areAllEmpty(rawAddressArray)) { - final boolean reallyUseQuotedPrintable = - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawAddressArray)); - final boolean appendCharset = - !VCardUtils.containsOnlyPrintableAscii(rawAddressArray); - final String encodedPoBox; - final String encodedStreet; - final String encodedLocality; - final String encodedRegion; - final String encodedPostalCode; - final String encodedCountry; - final String encodedNeighborhood; - - final String rawLocality2; - // This looks inefficient since we encode rawLocality and rawNeighborhood twice, - // but this is intentional. - // - // QP encoding may add line feeds when needed and the result of - // - encodeQuotedPrintable(rawLocality + " " + rawNeighborhood) - // may be different from - // - encodedLocality + " " + encodedNeighborhood. - // - // We use safer way. - if (TextUtils.isEmpty(rawLocality)) { - if (TextUtils.isEmpty(rawNeighborhood)) { - rawLocality2 = ""; - } else { - rawLocality2 = rawNeighborhood; - } - } else { - if (TextUtils.isEmpty(rawNeighborhood)) { - rawLocality2 = rawLocality; - } else { - rawLocality2 = rawLocality + " " + rawNeighborhood; - } - } - if (reallyUseQuotedPrintable) { - encodedPoBox = encodeQuotedPrintable(rawPoBox); - encodedStreet = encodeQuotedPrintable(rawStreet); - encodedLocality = encodeQuotedPrintable(rawLocality2); - encodedRegion = encodeQuotedPrintable(rawRegion); - encodedPostalCode = encodeQuotedPrintable(rawPostalCode); - encodedCountry = encodeQuotedPrintable(rawCountry); - } else { - encodedPoBox = escapeCharacters(rawPoBox); - encodedStreet = escapeCharacters(rawStreet); - encodedLocality = escapeCharacters(rawLocality2); - encodedRegion = escapeCharacters(rawRegion); - encodedPostalCode = escapeCharacters(rawPostalCode); - encodedCountry = escapeCharacters(rawCountry); - encodedNeighborhood = escapeCharacters(rawNeighborhood); - } - final StringBuilder addressBuilder = new StringBuilder(); - addressBuilder.append(encodedPoBox); - addressBuilder.append(VCARD_ITEM_SEPARATOR); // PO BOX ; Extended Address - addressBuilder.append(VCARD_ITEM_SEPARATOR); // Extended Address : Street - addressBuilder.append(encodedStreet); - addressBuilder.append(VCARD_ITEM_SEPARATOR); // Street : Locality - addressBuilder.append(encodedLocality); - addressBuilder.append(VCARD_ITEM_SEPARATOR); // Locality : Region - addressBuilder.append(encodedRegion); - addressBuilder.append(VCARD_ITEM_SEPARATOR); // Region : Postal Code - addressBuilder.append(encodedPostalCode); - addressBuilder.append(VCARD_ITEM_SEPARATOR); // Postal Code : Country - addressBuilder.append(encodedCountry); - return new PostalStruct( - reallyUseQuotedPrintable, appendCharset, addressBuilder.toString()); - } else { // VCardUtils.areAllEmpty(rawAddressArray) == true - // Try to use FORMATTED_ADDRESS instead. - final String rawFormattedAddress = - contentValues.getAsString(StructuredPostal.FORMATTED_ADDRESS); - if (TextUtils.isEmpty(rawFormattedAddress)) { - return null; - } - final boolean reallyUseQuotedPrintable = - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawFormattedAddress)); - final boolean appendCharset = - !VCardUtils.containsOnlyPrintableAscii(rawFormattedAddress); - final String encodedFormattedAddress; - if (reallyUseQuotedPrintable) { - encodedFormattedAddress = encodeQuotedPrintable(rawFormattedAddress); - } else { - encodedFormattedAddress = escapeCharacters(rawFormattedAddress); - } - - // We use the second value ("Extended Address") just because Japanese mobile phones - // do so. If the other importer expects the value be in the other field, some flag may - // be needed. - final StringBuilder addressBuilder = new StringBuilder(); - addressBuilder.append(VCARD_ITEM_SEPARATOR); // PO BOX ; Extended Address - addressBuilder.append(encodedFormattedAddress); - addressBuilder.append(VCARD_ITEM_SEPARATOR); // Extended Address : Street - addressBuilder.append(VCARD_ITEM_SEPARATOR); // Street : Locality - addressBuilder.append(VCARD_ITEM_SEPARATOR); // Locality : Region - addressBuilder.append(VCARD_ITEM_SEPARATOR); // Region : Postal Code - addressBuilder.append(VCARD_ITEM_SEPARATOR); // Postal Code : Country - return new PostalStruct( - reallyUseQuotedPrintable, appendCharset, addressBuilder.toString()); - } - } - - public VCardBuilder appendIms(final List<ContentValues> contentValuesList) { - if (contentValuesList != null) { - for (ContentValues contentValues : contentValuesList) { - final Integer protocolAsObject = contentValues.getAsInteger(Im.PROTOCOL); - if (protocolAsObject == null) { - continue; - } - final String propertyName = VCardUtils.getPropertyNameForIm(protocolAsObject); - if (propertyName == null) { - continue; - } - String data = contentValues.getAsString(Im.DATA); - if (data != null) { - data = data.trim(); - } - if (TextUtils.isEmpty(data)) { - continue; - } - final String typeAsString; - { - final Integer typeAsInteger = contentValues.getAsInteger(Im.TYPE); - switch (typeAsInteger != null ? typeAsInteger : Im.TYPE_OTHER) { - case Im.TYPE_HOME: { - typeAsString = VCardConstants.PARAM_TYPE_HOME; - break; - } - case Im.TYPE_WORK: { - typeAsString = VCardConstants.PARAM_TYPE_WORK; - break; - } - case Im.TYPE_CUSTOM: { - final String label = contentValues.getAsString(Im.LABEL); - typeAsString = (label != null ? "X-" + label : null); - break; - } - case Im.TYPE_OTHER: // Ignore - default: { - typeAsString = null; - break; - } - } - } - - final List<String> parameterList = new ArrayList<String>(); - if (!TextUtils.isEmpty(typeAsString)) { - parameterList.add(typeAsString); - } - final Integer isPrimaryAsInteger = contentValues.getAsInteger(Im.IS_PRIMARY); - final boolean isPrimary = (isPrimaryAsInteger != null ? - (isPrimaryAsInteger > 0) : false); - if (isPrimary) { - parameterList.add(VCardConstants.PARAM_TYPE_PREF); - } - - appendLineWithCharsetAndQPDetection(propertyName, parameterList, data); - } - } - return this; - } - - public VCardBuilder appendWebsites(final List<ContentValues> contentValuesList) { - if (contentValuesList != null) { - for (ContentValues contentValues : contentValuesList) { - String website = contentValues.getAsString(Website.URL); - if (website != null) { - website = website.trim(); - } - - // Note: vCard 3.0 does not allow any parameter addition toward "URL" - // property, while there's no document in vCard 2.1. - if (!TextUtils.isEmpty(website)) { - appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_URL, website); - } - } - } - return this; - } - - public VCardBuilder appendOrganizations(final List<ContentValues> contentValuesList) { - if (contentValuesList != null) { - for (ContentValues contentValues : contentValuesList) { - String company = contentValues.getAsString(Organization.COMPANY); - if (company != null) { - company = company.trim(); - } - String department = contentValues.getAsString(Organization.DEPARTMENT); - if (department != null) { - department = department.trim(); - } - String title = contentValues.getAsString(Organization.TITLE); - if (title != null) { - title = title.trim(); - } - - StringBuilder orgBuilder = new StringBuilder(); - if (!TextUtils.isEmpty(company)) { - orgBuilder.append(company); - } - if (!TextUtils.isEmpty(department)) { - if (orgBuilder.length() > 0) { - orgBuilder.append(';'); - } - orgBuilder.append(department); - } - final String orgline = orgBuilder.toString(); - appendLine(VCardConstants.PROPERTY_ORG, orgline, - !VCardUtils.containsOnlyPrintableAscii(orgline), - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(orgline))); - - if (!TextUtils.isEmpty(title)) { - appendLine(VCardConstants.PROPERTY_TITLE, title, - !VCardUtils.containsOnlyPrintableAscii(title), - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(title))); - } - } - } - return this; - } - - public VCardBuilder appendPhotos(final List<ContentValues> contentValuesList) { - if (contentValuesList != null) { - for (ContentValues contentValues : contentValuesList) { - if (contentValues == null) { - continue; - } - byte[] data = contentValues.getAsByteArray(Photo.PHOTO); - if (data == null) { - continue; - } - final String photoType = VCardUtils.guessImageType(data); - if (photoType == null) { - Log.d(LOG_TAG, "Unknown photo type. Ignored."); - continue; - } - final String photoString = new String(Base64.encodeBase64(data)); - if (!TextUtils.isEmpty(photoString)) { - appendPhotoLine(photoString, photoType); - } - } - } - return this; - } - - public VCardBuilder appendNotes(final List<ContentValues> contentValuesList) { - if (contentValuesList != null) { - if (mOnlyOneNoteFieldIsAvailable) { - final StringBuilder noteBuilder = new StringBuilder(); - boolean first = true; - for (final ContentValues contentValues : contentValuesList) { - String note = contentValues.getAsString(Note.NOTE); - if (note == null) { - note = ""; - } - if (note.length() > 0) { - if (first) { - first = false; - } else { - noteBuilder.append('\n'); - } - noteBuilder.append(note); - } - } - final String noteStr = noteBuilder.toString(); - // This means we scan noteStr completely twice, which is redundant. - // But for now, we assume this is not so time-consuming.. - final boolean shouldAppendCharsetInfo = - !VCardUtils.containsOnlyPrintableAscii(noteStr); - final boolean reallyUseQuotedPrintable = - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr)); - appendLine(VCardConstants.PROPERTY_NOTE, noteStr, - shouldAppendCharsetInfo, reallyUseQuotedPrintable); - } else { - for (ContentValues contentValues : contentValuesList) { - final String noteStr = contentValues.getAsString(Note.NOTE); - if (!TextUtils.isEmpty(noteStr)) { - final boolean shouldAppendCharsetInfo = - !VCardUtils.containsOnlyPrintableAscii(noteStr); - final boolean reallyUseQuotedPrintable = - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr)); - appendLine(VCardConstants.PROPERTY_NOTE, noteStr, - shouldAppendCharsetInfo, reallyUseQuotedPrintable); - } - } - } - } - return this; - } - - public VCardBuilder appendEvents(final List<ContentValues> contentValuesList) { - // There's possibility where a given object may have more than one birthday, which - // is inappropriate. We just build one birthday. - if (contentValuesList != null) { - String primaryBirthday = null; - String secondaryBirthday = null; - for (final ContentValues contentValues : contentValuesList) { - if (contentValues == null) { - continue; - } - final Integer eventTypeAsInteger = contentValues.getAsInteger(Event.TYPE); - final int eventType; - if (eventTypeAsInteger != null) { - eventType = eventTypeAsInteger; - } else { - eventType = Event.TYPE_OTHER; - } - if (eventType == Event.TYPE_BIRTHDAY) { - final String birthdayCandidate = contentValues.getAsString(Event.START_DATE); - if (birthdayCandidate == null) { - continue; - } - final Integer isSuperPrimaryAsInteger = - contentValues.getAsInteger(Event.IS_SUPER_PRIMARY); - final boolean isSuperPrimary = (isSuperPrimaryAsInteger != null ? - (isSuperPrimaryAsInteger > 0) : false); - if (isSuperPrimary) { - // "super primary" birthday should the prefered one. - primaryBirthday = birthdayCandidate; - break; - } - final Integer isPrimaryAsInteger = - contentValues.getAsInteger(Event.IS_PRIMARY); - final boolean isPrimary = (isPrimaryAsInteger != null ? - (isPrimaryAsInteger > 0) : false); - if (isPrimary) { - // We don't break here since "super primary" birthday may exist later. - primaryBirthday = birthdayCandidate; - } else if (secondaryBirthday == null) { - // First entry is set to the "secondary" candidate. - secondaryBirthday = birthdayCandidate; - } - } else if (mUsesAndroidProperty) { - // Event types other than Birthday is not supported by vCard. - appendAndroidSpecificProperty(Event.CONTENT_ITEM_TYPE, contentValues); - } - } - if (primaryBirthday != null) { - appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_BDAY, - primaryBirthday.trim()); - } else if (secondaryBirthday != null){ - appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_BDAY, - secondaryBirthday.trim()); - } - } - return this; - } - - public VCardBuilder appendRelation(final List<ContentValues> contentValuesList) { - if (mUsesAndroidProperty && contentValuesList != null) { - for (final ContentValues contentValues : contentValuesList) { - if (contentValues == null) { - continue; - } - appendAndroidSpecificProperty(Relation.CONTENT_ITEM_TYPE, contentValues); - } - } - return this; - } - - /** - * @param emitEveryTime If true, builder builds the line even when there's no entry. - */ - public void appendPostalLine(final int type, final String label, - final ContentValues contentValues, - final boolean isPrimary, final boolean emitEveryTime) { - final boolean reallyUseQuotedPrintable; - final boolean appendCharset; - final String addressValue; - { - PostalStruct postalStruct = tryConstructPostalStruct(contentValues); - if (postalStruct == null) { - if (emitEveryTime) { - reallyUseQuotedPrintable = false; - appendCharset = false; - addressValue = ""; - } else { - return; - } - } else { - reallyUseQuotedPrintable = postalStruct.reallyUseQuotedPrintable; - appendCharset = postalStruct.appendCharset; - addressValue = postalStruct.addressData; - } - } - - List<String> parameterList = new ArrayList<String>(); - if (isPrimary) { - parameterList.add(VCardConstants.PARAM_TYPE_PREF); - } - switch (type) { - case StructuredPostal.TYPE_HOME: { - parameterList.add(VCardConstants.PARAM_TYPE_HOME); - break; - } - case StructuredPostal.TYPE_WORK: { - parameterList.add(VCardConstants.PARAM_TYPE_WORK); - break; - } - case StructuredPostal.TYPE_CUSTOM: { - if (!TextUtils.isEmpty(label) - && VCardUtils.containsOnlyAlphaDigitHyphen(label)) { - // We're not sure whether the label is valid in the spec - // ("IANA-token" in the vCard 3.0 is unclear...) - // Just for safety, we add "X-" at the beggining of each label. - // Also checks the label obeys with vCard 3.0 spec. - parameterList.add("X-" + label); - } - break; - } - case StructuredPostal.TYPE_OTHER: { - break; - } - default: { - Log.e(LOG_TAG, "Unknown StructuredPostal type: " + type); - break; - } - } - - mBuilder.append(VCardConstants.PROPERTY_ADR); - if (!parameterList.isEmpty()) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - appendTypeParameters(parameterList); - } - if (appendCharset) { - // Strictly, vCard 3.0 does not allow exporters to emit charset information, - // but we will add it since the information should be useful for importers, - // - // Assume no parser does not emit error with this parameter in vCard 3.0. - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - if (reallyUseQuotedPrintable) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCARD_PARAM_ENCODING_QP); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(addressValue); - mBuilder.append(VCARD_END_OF_LINE); - } - - public void appendEmailLine(final int type, final String label, - final String rawValue, final boolean isPrimary) { - final String typeAsString; - switch (type) { - case Email.TYPE_CUSTOM: { - if (VCardUtils.isMobilePhoneLabel(label)) { - typeAsString = VCardConstants.PARAM_TYPE_CELL; - } else if (!TextUtils.isEmpty(label) - && VCardUtils.containsOnlyAlphaDigitHyphen(label)) { - typeAsString = "X-" + label; - } else { - typeAsString = null; - } - break; - } - case Email.TYPE_HOME: { - typeAsString = VCardConstants.PARAM_TYPE_HOME; - break; - } - case Email.TYPE_WORK: { - typeAsString = VCardConstants.PARAM_TYPE_WORK; - break; - } - case Email.TYPE_OTHER: { - typeAsString = null; - break; - } - case Email.TYPE_MOBILE: { - typeAsString = VCardConstants.PARAM_TYPE_CELL; - break; - } - default: { - Log.e(LOG_TAG, "Unknown Email type: " + type); - typeAsString = null; - break; - } - } - - final List<String> parameterList = new ArrayList<String>(); - if (isPrimary) { - parameterList.add(VCardConstants.PARAM_TYPE_PREF); - } - if (!TextUtils.isEmpty(typeAsString)) { - parameterList.add(typeAsString); - } - - appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_EMAIL, parameterList, - rawValue); - } - - public void appendTelLine(final Integer typeAsInteger, final String label, - final String encodedValue, boolean isPrimary) { - mBuilder.append(VCardConstants.PROPERTY_TEL); - mBuilder.append(VCARD_PARAM_SEPARATOR); - - final int type; - if (typeAsInteger == null) { - type = Phone.TYPE_OTHER; - } else { - type = typeAsInteger; - } - - ArrayList<String> parameterList = new ArrayList<String>(); - switch (type) { - case Phone.TYPE_HOME: { - parameterList.addAll( - Arrays.asList(VCardConstants.PARAM_TYPE_HOME)); - break; - } - case Phone.TYPE_WORK: { - parameterList.addAll( - Arrays.asList(VCardConstants.PARAM_TYPE_WORK)); - break; - } - case Phone.TYPE_FAX_HOME: { - parameterList.addAll( - Arrays.asList(VCardConstants.PARAM_TYPE_HOME, VCardConstants.PARAM_TYPE_FAX)); - break; - } - case Phone.TYPE_FAX_WORK: { - parameterList.addAll( - Arrays.asList(VCardConstants.PARAM_TYPE_WORK, VCardConstants.PARAM_TYPE_FAX)); - break; - } - case Phone.TYPE_MOBILE: { - parameterList.add(VCardConstants.PARAM_TYPE_CELL); - break; - } - case Phone.TYPE_PAGER: { - if (mIsDoCoMo) { - // Not sure about the reason, but previous implementation had - // used "VOICE" instead of "PAGER" - parameterList.add(VCardConstants.PARAM_TYPE_VOICE); - } else { - parameterList.add(VCardConstants.PARAM_TYPE_PAGER); - } - break; - } - case Phone.TYPE_OTHER: { - parameterList.add(VCardConstants.PARAM_TYPE_VOICE); - break; - } - case Phone.TYPE_CAR: { - parameterList.add(VCardConstants.PARAM_TYPE_CAR); - break; - } - case Phone.TYPE_COMPANY_MAIN: { - // There's no relevant field in vCard (at least 2.1). - parameterList.add(VCardConstants.PARAM_TYPE_WORK); - isPrimary = true; - break; - } - case Phone.TYPE_ISDN: { - parameterList.add(VCardConstants.PARAM_TYPE_ISDN); - break; - } - case Phone.TYPE_MAIN: { - isPrimary = true; - break; - } - case Phone.TYPE_OTHER_FAX: { - parameterList.add(VCardConstants.PARAM_TYPE_FAX); - break; - } - case Phone.TYPE_TELEX: { - parameterList.add(VCardConstants.PARAM_TYPE_TLX); - break; - } - case Phone.TYPE_WORK_MOBILE: { - parameterList.addAll( - Arrays.asList(VCardConstants.PARAM_TYPE_WORK, VCardConstants.PARAM_TYPE_CELL)); - break; - } - case Phone.TYPE_WORK_PAGER: { - parameterList.add(VCardConstants.PARAM_TYPE_WORK); - // See above. - if (mIsDoCoMo) { - parameterList.add(VCardConstants.PARAM_TYPE_VOICE); - } else { - parameterList.add(VCardConstants.PARAM_TYPE_PAGER); - } - break; - } - case Phone.TYPE_MMS: { - parameterList.add(VCardConstants.PARAM_TYPE_MSG); - break; - } - case Phone.TYPE_CUSTOM: { - if (TextUtils.isEmpty(label)) { - // Just ignore the custom type. - parameterList.add(VCardConstants.PARAM_TYPE_VOICE); - } else if (VCardUtils.isMobilePhoneLabel(label)) { - parameterList.add(VCardConstants.PARAM_TYPE_CELL); - } else { - final String upperLabel = label.toUpperCase(); - if (VCardUtils.isValidInV21ButUnknownToContactsPhoteType(upperLabel)) { - parameterList.add(upperLabel); - } else if (VCardUtils.containsOnlyAlphaDigitHyphen(label)) { - // Note: Strictly, vCard 2.1 does not allow "X-" parameter without - // "TYPE=" string. - parameterList.add("X-" + label); - } - } - break; - } - case Phone.TYPE_RADIO: - case Phone.TYPE_TTY_TDD: - default: { - break; - } - } - - if (isPrimary) { - parameterList.add(VCardConstants.PARAM_TYPE_PREF); - } - - if (parameterList.isEmpty()) { - appendUncommonPhoneType(mBuilder, type); - } else { - appendTypeParameters(parameterList); - } - - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(encodedValue); - mBuilder.append(VCARD_END_OF_LINE); - } - - /** - * Appends phone type string which may not be available in some devices. - */ - private void appendUncommonPhoneType(final StringBuilder builder, final Integer type) { - if (mIsDoCoMo) { - // The previous implementation for DoCoMo had been conservative - // about miscellaneous types. - builder.append(VCardConstants.PARAM_TYPE_VOICE); - } else { - String phoneType = VCardUtils.getPhoneTypeString(type); - if (phoneType != null) { - appendTypeParameter(phoneType); - } else { - Log.e(LOG_TAG, "Unknown or unsupported (by vCard) Phone type: " + type); - } - } - } - - /** - * @param encodedValue Must be encoded by BASE64 - * @param photoType - */ - public void appendPhotoLine(final String encodedValue, final String photoType) { - StringBuilder tmpBuilder = new StringBuilder(); - tmpBuilder.append(VCardConstants.PROPERTY_PHOTO); - tmpBuilder.append(VCARD_PARAM_SEPARATOR); - if (mIsV30) { - tmpBuilder.append(VCARD_PARAM_ENCODING_BASE64_V30); - } else { - tmpBuilder.append(VCARD_PARAM_ENCODING_BASE64_V21); - } - tmpBuilder.append(VCARD_PARAM_SEPARATOR); - appendTypeParameter(tmpBuilder, photoType); - tmpBuilder.append(VCARD_DATA_SEPARATOR); - tmpBuilder.append(encodedValue); - - final String tmpStr = tmpBuilder.toString(); - tmpBuilder = new StringBuilder(); - int lineCount = 0; - final int length = tmpStr.length(); - final int maxNumForFirstLine = VCardConstants.MAX_CHARACTER_NUMS_BASE64_V30 - - VCARD_END_OF_LINE.length(); - final int maxNumInGeneral = maxNumForFirstLine - VCARD_WS.length(); - int maxNum = maxNumForFirstLine; - for (int i = 0; i < length; i++) { - tmpBuilder.append(tmpStr.charAt(i)); - lineCount++; - if (lineCount > maxNum) { - tmpBuilder.append(VCARD_END_OF_LINE); - tmpBuilder.append(VCARD_WS); - maxNum = maxNumInGeneral; - lineCount = 0; - } - } - mBuilder.append(tmpBuilder.toString()); - mBuilder.append(VCARD_END_OF_LINE); - mBuilder.append(VCARD_END_OF_LINE); - } - - public void appendAndroidSpecificProperty( - final String mimeType, ContentValues contentValues) { - if (!sAllowedAndroidPropertySet.contains(mimeType)) { - return; - } - final List<String> rawValueList = new ArrayList<String>(); - for (int i = 1; i <= VCardConstants.MAX_DATA_COLUMN; i++) { - String value = contentValues.getAsString("data" + i); - if (value == null) { - value = ""; - } - rawValueList.add(value); - } - - boolean needCharset = - (mShouldAppendCharsetParam && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); - boolean reallyUseQuotedPrintable = - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); - mBuilder.append(VCardConstants.PROPERTY_X_ANDROID_CUSTOM); - if (needCharset) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - if (reallyUseQuotedPrintable) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCARD_PARAM_ENCODING_QP); - } - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(mimeType); // Should not be encoded. - for (String rawValue : rawValueList) { - final String encodedValue; - if (reallyUseQuotedPrintable) { - encodedValue = encodeQuotedPrintable(rawValue); - } else { - // TODO: one line may be too huge, which may be invalid in vCard 3.0 - // (which says "When generating a content line, lines longer than - // 75 characters SHOULD be folded"), though several - // (even well-known) applications do not care this. - encodedValue = escapeCharacters(rawValue); - } - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(encodedValue); - } - mBuilder.append(VCARD_END_OF_LINE); - } - - public void appendLineWithCharsetAndQPDetection(final String propertyName, - final String rawValue) { - appendLineWithCharsetAndQPDetection(propertyName, null, rawValue); - } - - public void appendLineWithCharsetAndQPDetection( - final String propertyName, final List<String> rawValueList) { - appendLineWithCharsetAndQPDetection(propertyName, null, rawValueList); - } - - public void appendLineWithCharsetAndQPDetection(final String propertyName, - final List<String> parameterList, final String rawValue) { - final boolean needCharset = - !VCardUtils.containsOnlyPrintableAscii(rawValue); - final boolean reallyUseQuotedPrintable = - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValue)); - appendLine(propertyName, parameterList, - rawValue, needCharset, reallyUseQuotedPrintable); - } - - public void appendLineWithCharsetAndQPDetection(final String propertyName, - final List<String> parameterList, final List<String> rawValueList) { - boolean needCharset = - (mShouldAppendCharsetParam && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); - boolean reallyUseQuotedPrintable = - (mShouldUseQuotedPrintable && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList)); - appendLine(propertyName, parameterList, rawValueList, - needCharset, reallyUseQuotedPrintable); - } - - /** - * Appends one line with a given property name and value. - */ - public void appendLine(final String propertyName, final String rawValue) { - appendLine(propertyName, rawValue, false, false); - } - - public void appendLine(final String propertyName, final List<String> rawValueList) { - appendLine(propertyName, rawValueList, false, false); - } - - public void appendLine(final String propertyName, - final String rawValue, final boolean needCharset, - boolean reallyUseQuotedPrintable) { - appendLine(propertyName, null, rawValue, needCharset, reallyUseQuotedPrintable); - } - - public void appendLine(final String propertyName, final List<String> parameterList, - final String rawValue) { - appendLine(propertyName, parameterList, rawValue, false, false); - } - - public void appendLine(final String propertyName, final List<String> parameterList, - final String rawValue, final boolean needCharset, - boolean reallyUseQuotedPrintable) { - mBuilder.append(propertyName); - if (parameterList != null && parameterList.size() > 0) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - appendTypeParameters(parameterList); - } - if (needCharset) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - - final String encodedValue; - if (reallyUseQuotedPrintable) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCARD_PARAM_ENCODING_QP); - encodedValue = encodeQuotedPrintable(rawValue); - } else { - // TODO: one line may be too huge, which may be invalid in vCard spec, though - // several (even well-known) applications do not care that violation. - encodedValue = escapeCharacters(rawValue); - } - - mBuilder.append(VCARD_DATA_SEPARATOR); - mBuilder.append(encodedValue); - mBuilder.append(VCARD_END_OF_LINE); - } - - public void appendLine(final String propertyName, final List<String> rawValueList, - final boolean needCharset, boolean needQuotedPrintable) { - appendLine(propertyName, null, rawValueList, needCharset, needQuotedPrintable); - } - - public void appendLine(final String propertyName, final List<String> parameterList, - final List<String> rawValueList, final boolean needCharset, - final boolean needQuotedPrintable) { - mBuilder.append(propertyName); - if (parameterList != null && parameterList.size() > 0) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - appendTypeParameters(parameterList); - } - if (needCharset) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(mVCardCharsetParameter); - } - if (needQuotedPrintable) { - mBuilder.append(VCARD_PARAM_SEPARATOR); - mBuilder.append(VCARD_PARAM_ENCODING_QP); - } - - mBuilder.append(VCARD_DATA_SEPARATOR); - boolean first = true; - for (String rawValue : rawValueList) { - final String encodedValue; - if (needQuotedPrintable) { - encodedValue = encodeQuotedPrintable(rawValue); - } else { - // TODO: one line may be too huge, which may be invalid in vCard 3.0 - // (which says "When generating a content line, lines longer than - // 75 characters SHOULD be folded"), though several - // (even well-known) applications do not care this. - encodedValue = escapeCharacters(rawValue); - } - - if (first) { - first = false; - } else { - mBuilder.append(VCARD_ITEM_SEPARATOR); - } - mBuilder.append(encodedValue); - } - mBuilder.append(VCARD_END_OF_LINE); - } - - /** - * VCARD_PARAM_SEPARATOR must be appended before this method being called. - */ - private void appendTypeParameters(final List<String> types) { - // We may have to make this comma separated form like "TYPE=DOM,WORK" in the future, - // which would be recommended way in vcard 3.0 though not valid in vCard 2.1. - boolean first = true; - for (final String typeValue : types) { - // Note: vCard 3.0 specifies the different type of acceptable type Strings, but - // we don't emit that kind of vCard 3.0 specific type since there should be - // high probabilyty in which external importers cannot understand them. - // - // e.g. TYPE="\u578B\u306B\u3087" (vCard 3.0 allows non-Ascii characters if they - // are quoted.) - if (!VCardUtils.isV21Word(typeValue)) { - continue; - } - if (first) { - first = false; - } else { - mBuilder.append(VCARD_PARAM_SEPARATOR); - } - appendTypeParameter(typeValue); - } - } - - /** - * VCARD_PARAM_SEPARATOR must be appended before this method being called. - */ - private void appendTypeParameter(final String type) { - appendTypeParameter(mBuilder, type); - } - - private void appendTypeParameter(final StringBuilder builder, final String type) { - // Refrain from using appendType() so that "TYPE=" is not be appended when the - // device is DoCoMo's (just for safety). - // - // Note: In vCard 3.0, Type strings also can be like this: "TYPE=HOME,PREF" - if ((mIsV30 || mAppendTypeParamName) && !mIsDoCoMo) { - builder.append(VCardConstants.PARAM_TYPE).append(VCARD_PARAM_EQUAL); - } - builder.append(type); - } - - /** - * Returns true when the property line should contain charset parameter - * information. This method may return true even when vCard version is 3.0. - * - * Strictly, adding charset information is invalid in VCard 3.0. - * However we'll add the info only when charset we use is not UTF-8 - * in vCard 3.0 format, since parser side may be able to use the charset - * via this field, though we may encounter another problem by adding it. - * - * e.g. Japanese mobile phones use Shift_Jis while RFC 2426 - * recommends UTF-8. By adding this field, parsers may be able - * to know this text is NOT UTF-8 but Shift_Jis. - */ - private boolean shouldAppendCharsetParam(String...propertyValueList) { - if (!mShouldAppendCharsetParam) { - return false; - } - for (String propertyValue : propertyValueList) { - if (!VCardUtils.containsOnlyPrintableAscii(propertyValue)) { - return true; - } - } - return false; - } - - private String encodeQuotedPrintable(final String str) { - if (TextUtils.isEmpty(str)) { - return ""; - } - - final StringBuilder builder = new StringBuilder(); - int index = 0; - int lineCount = 0; - byte[] strArray = null; - - try { - strArray = str.getBytes(mCharset); - } catch (UnsupportedEncodingException e) { - Log.e(LOG_TAG, "Charset " + mCharset + " cannot be used. " - + "Try default charset"); - strArray = str.getBytes(); - } - while (index < strArray.length) { - builder.append(String.format("=%02X", strArray[index])); - index += 1; - lineCount += 3; - - if (lineCount >= 67) { - // Specification requires CRLF must be inserted before the - // length of the line - // becomes more than 76. - // Assuming that the next character is a multi-byte character, - // it will become - // 6 bytes. - // 76 - 6 - 3 = 67 - builder.append("=\r\n"); - lineCount = 0; - } - } - - return builder.toString(); - } - - /** - * Append '\' to the characters which should be escaped. The character set is different - * not only between vCard 2.1 and vCard 3.0 but also among each device. - * - * Note that Quoted-Printable string must not be input here. - */ - @SuppressWarnings("fallthrough") - private String escapeCharacters(final String unescaped) { - if (TextUtils.isEmpty(unescaped)) { - return ""; - } - - final StringBuilder tmpBuilder = new StringBuilder(); - final int length = unescaped.length(); - for (int i = 0; i < length; i++) { - final char ch = unescaped.charAt(i); - switch (ch) { - case ';': { - tmpBuilder.append('\\'); - tmpBuilder.append(';'); - break; - } - case '\r': { - if (i + 1 < length) { - char nextChar = unescaped.charAt(i); - if (nextChar == '\n') { - break; - } else { - // fall through - } - } else { - // fall through - } - } - case '\n': { - // In vCard 2.1, there's no specification about this, while - // vCard 3.0 explicitly requires this should be encoded to "\n". - tmpBuilder.append("\\n"); - break; - } - case '\\': { - if (mIsV30) { - tmpBuilder.append("\\\\"); - break; - } else { - // fall through - } - } - case '<': - case '>': { - if (mIsDoCoMo) { - tmpBuilder.append('\\'); - tmpBuilder.append(ch); - } else { - tmpBuilder.append(ch); - } - break; - } - case ',': { - if (mIsV30) { - tmpBuilder.append("\\,"); - } else { - tmpBuilder.append(ch); - } - break; - } - default: { - tmpBuilder.append(ch); - break; - } - } - } - return tmpBuilder.toString(); - } - - @Override - public String toString() { - if (!mEndAppended) { - if (mIsDoCoMo) { - appendLine(VCardConstants.PROPERTY_X_CLASS, VCARD_DATA_PUBLIC); - appendLine(VCardConstants.PROPERTY_X_REDUCTION, ""); - appendLine(VCardConstants.PROPERTY_X_NO, ""); - appendLine(VCardConstants.PROPERTY_X_DCM_HMN_MODE, ""); - } - appendLine(VCardConstants.PROPERTY_END, VCARD_DATA_VCARD); - mEndAppended = true; - } - return mBuilder.toString(); - } -} diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java deleted file mode 100644 index 170d6fa..0000000 --- a/core/java/android/pim/vcard/VCardComposer.java +++ /dev/null @@ -1,675 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android.pim.vcard; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.Entity; -import android.content.EntityIterator; -import android.content.Entity.NamedContentValues; -import android.database.Cursor; -import android.database.sqlite.SQLiteException; -import android.net.Uri; -import android.pim.vcard.exception.VCardException; -import android.provider.ContactsContract.Contacts; -import android.provider.ContactsContract.Data; -import android.provider.ContactsContract.RawContacts; -import android.provider.ContactsContract.RawContactsEntity; -import android.provider.ContactsContract.CommonDataKinds.Email; -import android.provider.ContactsContract.CommonDataKinds.Event; -import android.provider.ContactsContract.CommonDataKinds.Im; -import android.provider.ContactsContract.CommonDataKinds.Nickname; -import android.provider.ContactsContract.CommonDataKinds.Note; -import android.provider.ContactsContract.CommonDataKinds.Organization; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.Photo; -import android.provider.ContactsContract.CommonDataKinds.Relation; -import android.provider.ContactsContract.CommonDataKinds.StructuredName; -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; -import android.provider.ContactsContract.CommonDataKinds.Website; -import android.text.TextUtils; -import android.util.CharsetUtils; -import android.util.Log; - -import java.io.BufferedWriter; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.charset.UnsupportedCharsetException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * <p> - * The class for composing vCard from Contacts information. - * </p> - * <p> - * Usually, this class should be used like this. - * </p> - * <pre class="prettyprint">VCardComposer composer = null; - * try { - * composer = new VCardComposer(context); - * composer.addHandler( - * composer.new HandlerForOutputStream(outputStream)); - * if (!composer.init()) { - * // Do something handling the situation. - * return; - * } - * while (!composer.isAfterLast()) { - * if (mCanceled) { - * // Assume a user may cancel this operation during the export. - * return; - * } - * if (!composer.createOneEntry()) { - * // Do something handling the error situation. - * return; - * } - * } - * } finally { - * if (composer != null) { - * composer.terminate(); - * } - * }</pre> - * <p> - * Users have to manually take care of memory efficiency. Even one vCard may contain - * image of non-trivial size for mobile devices. - * </p> - * <p> - * {@link VCardBuilder} is used to build each vCard. - * </p> - */ -public class VCardComposer { - private static final String LOG_TAG = "VCardComposer"; - - public static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO = - "Failed to get database information"; - - public static final String FAILURE_REASON_NO_ENTRY = - "There's no exportable in the database"; - - public static final String FAILURE_REASON_NOT_INITIALIZED = - "The vCard composer object is not correctly initialized"; - - /** Should be visible only from developers... (no need to translate, hopefully) */ - public static final String FAILURE_REASON_UNSUPPORTED_URI = - "The Uri vCard composer received is not supported by the composer."; - - public static final String NO_ERROR = "No error"; - - public static final String VCARD_TYPE_STRING_DOCOMO = "docomo"; - - // Strictly speaking, "Shift_JIS" is the most appropriate, but we use upper version here, - // since usual vCard devices for Japanese devices already use it. - private static final String SHIFT_JIS = "SHIFT_JIS"; - private static final String UTF_8 = "UTF-8"; - - /** - * Special URI for testing. - */ - public static final String VCARD_TEST_AUTHORITY = "com.android.unit_tests.vcard"; - public static final Uri VCARD_TEST_AUTHORITY_URI = - Uri.parse("content://" + VCARD_TEST_AUTHORITY); - public static final Uri CONTACTS_TEST_CONTENT_URI = - Uri.withAppendedPath(VCARD_TEST_AUTHORITY_URI, "contacts"); - - private static final Map<Integer, String> sImMap; - - static { - sImMap = new HashMap<Integer, String>(); - sImMap.put(Im.PROTOCOL_AIM, VCardConstants.PROPERTY_X_AIM); - sImMap.put(Im.PROTOCOL_MSN, VCardConstants.PROPERTY_X_MSN); - sImMap.put(Im.PROTOCOL_YAHOO, VCardConstants.PROPERTY_X_YAHOO); - sImMap.put(Im.PROTOCOL_ICQ, VCardConstants.PROPERTY_X_ICQ); - sImMap.put(Im.PROTOCOL_JABBER, VCardConstants.PROPERTY_X_JABBER); - sImMap.put(Im.PROTOCOL_SKYPE, VCardConstants.PROPERTY_X_SKYPE_USERNAME); - // We don't add Google talk here since it has to be handled separately. - } - - public static interface OneEntryHandler { - public boolean onInit(Context context); - public boolean onEntryCreated(String vcard); - public void onTerminate(); - } - - /** - * <p> - * An useful handler for emitting vCard String to an OutputStream object one by one. - * </p> - * <p> - * The input OutputStream object is closed() on {@link #onTerminate()}. - * Must not close the stream outside this class. - * </p> - */ - public final class HandlerForOutputStream implements OneEntryHandler { - @SuppressWarnings("hiding") - private static final String LOG_TAG = "VCardComposer.HandlerForOutputStream"; - - private boolean mOnTerminateIsCalled = false; - - private final OutputStream mOutputStream; // mWriter will close this. - private Writer mWriter; - - /** - * Input stream will be closed on the detruction of this object. - */ - public HandlerForOutputStream(final OutputStream outputStream) { - mOutputStream = outputStream; - } - - public boolean onInit(final Context context) { - try { - mWriter = new BufferedWriter(new OutputStreamWriter( - mOutputStream, mCharset)); - } catch (UnsupportedEncodingException e1) { - Log.e(LOG_TAG, "Unsupported charset: " + mCharset); - mErrorReason = "Encoding is not supported (usually this does not happen!): " - + mCharset; - return false; - } - - if (mIsDoCoMo) { - try { - // Create one empty entry. - mWriter.write(createOneEntryInternal("-1", null)); - } catch (VCardException e) { - Log.e(LOG_TAG, "VCardException has been thrown during on Init(): " + - e.getMessage()); - return false; - } catch (IOException e) { - Log.e(LOG_TAG, - "IOException occurred during exportOneContactData: " - + e.getMessage()); - mErrorReason = "IOException occurred: " + e.getMessage(); - return false; - } - } - return true; - } - - public boolean onEntryCreated(String vcard) { - try { - mWriter.write(vcard); - } catch (IOException e) { - Log.e(LOG_TAG, - "IOException occurred during exportOneContactData: " - + e.getMessage()); - mErrorReason = "IOException occurred: " + e.getMessage(); - return false; - } - return true; - } - - public void onTerminate() { - mOnTerminateIsCalled = true; - if (mWriter != null) { - try { - // Flush and sync the data so that a user is able to pull - // the SDCard just after - // the export. - mWriter.flush(); - if (mOutputStream != null - && mOutputStream instanceof FileOutputStream) { - ((FileOutputStream) mOutputStream).getFD().sync(); - } - } catch (IOException e) { - Log.d(LOG_TAG, - "IOException during closing the output stream: " - + e.getMessage()); - } finally { - closeOutputStream(); - } - } - } - - public void closeOutputStream() { - try { - mWriter.close(); - } catch (IOException e) { - Log.w(LOG_TAG, "IOException is thrown during close(). Ignoring."); - } - } - - @Override - public void finalize() { - if (!mOnTerminateIsCalled) { - onTerminate(); - } - } - } - - private final Context mContext; - private final int mVCardType; - private final boolean mCareHandlerErrors; - private final ContentResolver mContentResolver; - - private final boolean mIsDoCoMo; - private Cursor mCursor; - private int mIdColumn; - - private final String mCharset; - private boolean mTerminateIsCalled; - private final List<OneEntryHandler> mHandlerList; - - private String mErrorReason = NO_ERROR; - - private static final String[] sContactsProjection = new String[] { - Contacts._ID, - }; - - public VCardComposer(Context context) { - this(context, VCardConfig.VCARD_TYPE_DEFAULT, null, true); - } - - /** - * The variant which sets charset to null and sets careHandlerErrors to true. - */ - public VCardComposer(Context context, int vcardType) { - this(context, vcardType, null, true); - } - - public VCardComposer(Context context, int vcardType, String charset) { - this(context, vcardType, charset, true); - } - - /** - * The variant which sets charset to null. - */ - public VCardComposer(final Context context, final int vcardType, - final boolean careHandlerErrors) { - this(context, vcardType, null, careHandlerErrors); - } - - /** - * Construct for supporting call log entry vCard composing. - * - * @param context Context to be used during the composition. - * @param vcardType The type of vCard, typically available via {@link VCardConfig}. - * @param charset The charset to be used. Use null when you don't need the charset. - * @param careHandlerErrors If true, This object returns false everytime - * a Handler object given via {{@link #addHandler(OneEntryHandler)} returns false. - * If false, this ignores those errors. - */ - public VCardComposer(final Context context, final int vcardType, String charset, - final boolean careHandlerErrors) { - mContext = context; - mVCardType = vcardType; - mCareHandlerErrors = careHandlerErrors; - mContentResolver = context.getContentResolver(); - - mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); - mHandlerList = new ArrayList<OneEntryHandler>(); - - charset = (TextUtils.isEmpty(charset) ? VCardConfig.DEFAULT_EXPORT_CHARSET : charset); - final boolean shouldAppendCharsetParam = !( - VCardConfig.isV30(vcardType) && UTF_8.equalsIgnoreCase(charset)); - - if (mIsDoCoMo || shouldAppendCharsetParam) { - if (SHIFT_JIS.equalsIgnoreCase(charset)) { - if (mIsDoCoMo) { - try { - charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); - } catch (UnsupportedCharsetException e) { - Log.e(LOG_TAG, - "DoCoMo-specific SHIFT_JIS was not found. " - + "Use SHIFT_JIS as is."); - charset = SHIFT_JIS; - } - } else { - try { - charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); - } catch (UnsupportedCharsetException e) { - Log.e(LOG_TAG, - "Career-specific SHIFT_JIS was not found. " - + "Use SHIFT_JIS as is."); - charset = SHIFT_JIS; - } - } - mCharset = charset; - } else { - Log.w(LOG_TAG, - "The charset \"" + charset + "\" is used while " - + SHIFT_JIS + " is needed to be used."); - if (TextUtils.isEmpty(charset)) { - mCharset = SHIFT_JIS; - } else { - try { - charset = CharsetUtils.charsetForVendor(charset).name(); - } catch (UnsupportedCharsetException e) { - Log.i(LOG_TAG, - "Career-specific \"" + charset + "\" was not found (as usual). " - + "Use it as is."); - } - mCharset = charset; - } - } - } else { - if (TextUtils.isEmpty(charset)) { - mCharset = UTF_8; - } else { - try { - charset = CharsetUtils.charsetForVendor(charset).name(); - } catch (UnsupportedCharsetException e) { - Log.i(LOG_TAG, - "Career-specific \"" + charset + "\" was not found (as usual). " - + "Use it as is."); - } - mCharset = charset; - } - } - - Log.d(LOG_TAG, "Use the charset \"" + mCharset + "\""); - } - - /** - * Must be called before {@link #init()}. - */ - public void addHandler(OneEntryHandler handler) { - if (handler != null) { - mHandlerList.add(handler); - } - } - - /** - * @return Returns true when initialization is successful and all the other - * methods are available. Returns false otherwise. - */ - public boolean init() { - return init(null, null); - } - - public boolean init(final String selection, final String[] selectionArgs) { - return init(Contacts.CONTENT_URI, selection, selectionArgs, null); - } - - /** - * Note that this is unstable interface, may be deleted in the future. - */ - public boolean init(final Uri contentUri, final String selection, - final String[] selectionArgs, final String sortOrder) { - if (contentUri == null) { - return false; - } - - if (mCareHandlerErrors) { - final List<OneEntryHandler> finishedList = new ArrayList<OneEntryHandler>( - mHandlerList.size()); - for (OneEntryHandler handler : mHandlerList) { - if (!handler.onInit(mContext)) { - for (OneEntryHandler finished : finishedList) { - finished.onTerminate(); - } - return false; - } - } - } else { - // Just ignore the false returned from onInit(). - for (OneEntryHandler handler : mHandlerList) { - handler.onInit(mContext); - } - } - - final String[] projection; - if (Contacts.CONTENT_URI.equals(contentUri) || - CONTACTS_TEST_CONTENT_URI.equals(contentUri)) { - projection = sContactsProjection; - } else { - mErrorReason = FAILURE_REASON_UNSUPPORTED_URI; - return false; - } - mCursor = mContentResolver.query( - contentUri, projection, selection, selectionArgs, sortOrder); - - if (mCursor == null) { - mErrorReason = FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO; - return false; - } - - if (getCount() == 0 || !mCursor.moveToFirst()) { - try { - mCursor.close(); - } catch (SQLiteException e) { - Log.e(LOG_TAG, "SQLiteException on Cursor#close(): " + e.getMessage()); - } finally { - mCursor = null; - mErrorReason = FAILURE_REASON_NO_ENTRY; - } - return false; - } - - mIdColumn = mCursor.getColumnIndex(Contacts._ID); - - return true; - } - - public boolean createOneEntry() { - return createOneEntry(null); - } - - /** - * @param getEntityIteratorMethod For Dependency Injection. - * @hide just for testing. - */ - public boolean createOneEntry(Method getEntityIteratorMethod) { - if (mCursor == null || mCursor.isAfterLast()) { - mErrorReason = FAILURE_REASON_NOT_INITIALIZED; - return false; - } - final String vcard; - try { - if (mIdColumn >= 0) { - vcard = createOneEntryInternal(mCursor.getString(mIdColumn), - getEntityIteratorMethod); - } else { - Log.e(LOG_TAG, "Incorrect mIdColumn: " + mIdColumn); - return true; - } - } catch (VCardException e) { - Log.e(LOG_TAG, "VCardException has been thrown: " + e.getMessage()); - return false; - } catch (OutOfMemoryError error) { - // Maybe some data (e.g. photo) is too big to have in memory. But it - // should be rare. - Log.e(LOG_TAG, "OutOfMemoryError occured. Ignore the entry."); - System.gc(); - // TODO: should tell users what happened? - return true; - } finally { - mCursor.moveToNext(); - } - - // This function does not care the OutOfMemoryError on the handler side :-P - if (mCareHandlerErrors) { - List<OneEntryHandler> finishedList = new ArrayList<OneEntryHandler>( - mHandlerList.size()); - for (OneEntryHandler handler : mHandlerList) { - if (!handler.onEntryCreated(vcard)) { - return false; - } - } - } else { - for (OneEntryHandler handler : mHandlerList) { - handler.onEntryCreated(vcard); - } - } - - return true; - } - - private String createOneEntryInternal(final String contactId, - final Method getEntityIteratorMethod) throws VCardException { - final Map<String, List<ContentValues>> contentValuesListMap = - new HashMap<String, List<ContentValues>>(); - // The resolver may return the entity iterator with no data. It is possible. - // e.g. If all the data in the contact of the given contact id are not exportable ones, - // they are hidden from the view of this method, though contact id itself exists. - EntityIterator entityIterator = null; - try { - final Uri uri = RawContactsEntity.CONTENT_URI.buildUpon() - .appendQueryParameter(Data.FOR_EXPORT_ONLY, "1") - .build(); - final String selection = Data.CONTACT_ID + "=?"; - final String[] selectionArgs = new String[] {contactId}; - if (getEntityIteratorMethod != null) { - // Please note that this branch is executed by unit tests only - try { - entityIterator = (EntityIterator)getEntityIteratorMethod.invoke(null, - mContentResolver, uri, selection, selectionArgs, null); - } catch (IllegalArgumentException e) { - Log.e(LOG_TAG, "IllegalArgumentException has been thrown: " + - e.getMessage()); - } catch (IllegalAccessException e) { - Log.e(LOG_TAG, "IllegalAccessException has been thrown: " + - e.getMessage()); - } catch (InvocationTargetException e) { - Log.e(LOG_TAG, "InvocationTargetException has been thrown: "); - StackTraceElement[] stackTraceElements = e.getCause().getStackTrace(); - for (StackTraceElement element : stackTraceElements) { - Log.e(LOG_TAG, " at " + element.toString()); - } - throw new VCardException("InvocationTargetException has been thrown: " + - e.getCause().getMessage()); - } - } else { - entityIterator = RawContacts.newEntityIterator(mContentResolver.query( - uri, null, selection, selectionArgs, null)); - } - - if (entityIterator == null) { - Log.e(LOG_TAG, "EntityIterator is null"); - return ""; - } - - if (!entityIterator.hasNext()) { - Log.w(LOG_TAG, "Data does not exist. contactId: " + contactId); - return ""; - } - - while (entityIterator.hasNext()) { - Entity entity = entityIterator.next(); - for (NamedContentValues namedContentValues : entity.getSubValues()) { - ContentValues contentValues = namedContentValues.values; - String key = contentValues.getAsString(Data.MIMETYPE); - if (key != null) { - List<ContentValues> contentValuesList = - contentValuesListMap.get(key); - if (contentValuesList == null) { - contentValuesList = new ArrayList<ContentValues>(); - contentValuesListMap.put(key, contentValuesList); - } - contentValuesList.add(contentValues); - } - } - } - } finally { - if (entityIterator != null) { - entityIterator.close(); - } - } - - return buildVCard(contentValuesListMap); - } - - /** - * Builds and returns vCard using given map, whose key is CONTENT_ITEM_TYPE defined in - * {ContactsContract}. Developers can override this method to customize the output. - */ - public String buildVCard(final Map<String, List<ContentValues>> contentValuesListMap) { - if (contentValuesListMap == null) { - Log.e(LOG_TAG, "The given map is null. Ignore and return empty String"); - return ""; - } else { - final VCardBuilder builder = new VCardBuilder(mVCardType, mCharset); - builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE)) - .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE)) - .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE)) - .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE)) - .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE)) - .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE)) - .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE)) - .appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE)) - .appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE)) - .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE)) - .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE)) - .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE)); - return builder.toString(); - } - } - - public void terminate() { - for (OneEntryHandler handler : mHandlerList) { - handler.onTerminate(); - } - - if (mCursor != null) { - try { - mCursor.close(); - } catch (SQLiteException e) { - Log.e(LOG_TAG, "SQLiteException on Cursor#close(): " + e.getMessage()); - } - mCursor = null; - } - - mTerminateIsCalled = true; - } - - @Override - public void finalize() { - if (!mTerminateIsCalled) { - Log.w(LOG_TAG, "terminate() is not called yet. We call it in finalize() step."); - terminate(); - } - } - - /** - * @return returns the number of available entities. The return value is undefined - * when this object is not ready yet (typically when {{@link #init()} is not called - * or when {@link #terminate()} is already called). - */ - public int getCount() { - if (mCursor == null) { - Log.w(LOG_TAG, "This object is not ready yet."); - return 0; - } - return mCursor.getCount(); - } - - /** - * @return true when there's no entity to be built. The return value is undefined - * when this object is not ready yet. - */ - public boolean isAfterLast() { - if (mCursor == null) { - Log.w(LOG_TAG, "This object is not ready yet."); - return false; - } - return mCursor.isAfterLast(); - } - - /** - * @return Returns the error reason. - */ - public String getErrorReason() { - return mErrorReason; - } -} diff --git a/core/java/android/pim/vcard/VCardConfig.java b/core/java/android/pim/vcard/VCardConfig.java deleted file mode 100644 index 80709f3..0000000 --- a/core/java/android/pim/vcard/VCardConfig.java +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import android.telephony.PhoneNumberUtils; -import android.util.Log; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * The class representing VCard related configurations. Useful static methods are not in this class - * but in VCardUtils. - */ -public class VCardConfig { - private static final String LOG_TAG = "VCardConfig"; - - /* package */ static final int LOG_LEVEL_NONE = 0; - /* package */ static final int LOG_LEVEL_PERFORMANCE_MEASUREMENT = 0x1; - /* package */ static final int LOG_LEVEL_SHOW_WARNING = 0x2; - /* package */ static final int LOG_LEVEL_VERBOSE = - LOG_LEVEL_PERFORMANCE_MEASUREMENT | LOG_LEVEL_SHOW_WARNING; - - /* package */ static final int LOG_LEVEL = LOG_LEVEL_NONE; - - /** - * <p> - * The charset used during import. - * </p> - * <p> - * We cannot determine which charset should be used to interpret a given vCard file - * at first, while we have to decode sime encoded data (e.g. BASE64) to binary. - * In order to avoid "misinterpretation" of charset as much as possible, - * "ISO-8859-1" (a.k.a Latin-1) is first used for reading a stream. - * When charset is specified in a property (with "CHARSET=..." parameter), - * the string is decoded to raw bytes and encoded into the specific charset, - * assuming "ISO-8859-1" is able to map "all" 8bit characters to some unicode, - * and it has 1 to 1 mapping in all 8bit characters. - * If the assumption is not correct, this setting will cause some bug. - * </p> - * @hide made public just for unit test - */ - public static final String DEFAULT_INTERMEDIATE_CHARSET = "ISO-8859-1"; - - /** - * The charset used when there's no information affbout what charset should be used to - * encode the binary given from vCard. - */ - public static final String DEFAULT_IMPORT_CHARSET = "UTF-8"; - public static final String DEFAULT_EXPORT_CHARSET = "UTF-8"; - - public static final int FLAG_V21 = 0; - public static final int FLAG_V30 = 1; - - // 0x2 is reserved for the future use ... - - public static final int NAME_ORDER_DEFAULT = 0; - public static final int NAME_ORDER_EUROPE = 0x4; - public static final int NAME_ORDER_JAPANESE = 0x8; - private static final int NAME_ORDER_MASK = 0xC; - - // 0x10 is reserved for safety - - /** - * <p> - * The flag indicating the vCard composer will add some "X-" properties used only in Android - * when the formal vCard specification does not have appropriate fields for that data. - * </p> - * <p> - * For example, Android accepts nickname information while vCard 2.1 does not. - * When this flag is on, vCard composer emits alternative "X-" property (like "X-NICKNAME") - * instead of just dropping it. - * </p> - * <p> - * vCard parser code automatically parses the field emitted even when this flag is off. - * </p> - */ - private static final int FLAG_USE_ANDROID_PROPERTY = 0x80000000; - - /** - * <p> - * The flag indicating the vCard composer will add some "X-" properties seen in the - * vCard data emitted by the other softwares/devices when the formal vCard specification - * does not have appropriate field(s) for that data. - * </p> - * <p> - * One example is X-PHONETIC-FIRST-NAME/X-PHONETIC-MIDDLE-NAME/X-PHONETIC-LAST-NAME, which are - * for phonetic name (how the name is pronounced), seen in the vCard emitted by some other - * non-Android devices/softwares. We chose to enable the vCard composer to use those - * defact properties since they are also useful for Android devices. - * </p> - * <p> - * Note for developers: only "X-" properties should be added with this flag. vCard 2.1/3.0 - * allows any kind of "X-" properties but does not allow non-"X-" properties (except IANA tokens - * in vCard 3.0). Some external parsers may get confused with non-valid, non-"X-" properties. - * </p> - */ - private static final int FLAG_USE_DEFACT_PROPERTY = 0x40000000; - - /** - * <p> - * The flag indicating some specific dialect seen in vCard of DoCoMo (one of Japanese - * mobile careers) should be used. This flag does not include any other information like - * that "the vCard is for Japanese". So it is "possible" that "the vCard should have DoCoMo's - * dialect but the name order should be European", but it is not recommended. - * </p> - */ - private static final int FLAG_DOCOMO = 0x20000000; - - /** - * <p> - * The flag indicating the vCard composer does "NOT" use Quoted-Printable toward "primary" - * properties even though it is required by vCard 2.1 (QP is prohibited in vCard 3.0). - * </p> - * <p> - * We actually cannot define what is the "primary" property. Note that this is NOT defined - * in vCard specification either. Also be aware that it is NOT related to "primary" notion - * used in {@link android.provider.ContactsContract}. - * This notion is just for vCard composition in Android. - * </p> - * <p> - * We added this Android-specific notion since some (incomplete) vCard exporters for vCard 2.1 - * do NOT use Quoted-Printable encoding toward some properties related names like "N", "FN", etc. - * even when their values contain non-ascii or/and CR/LF, while they use the encoding in the - * other properties like "ADR", "ORG", etc. - * <p> - * We are afraid of the case where some vCard importer also forget handling QP presuming QP is - * not used in such fields. - * </p> - * <p> - * This flag is useful when some target importer you are going to focus on does not accept - * such properties with Quoted-Printable encoding. - * </p> - * <p> - * Again, we should not use this flag at all for complying vCard 2.1 spec. - * </p> - * <p> - * In vCard 3.0, Quoted-Printable is explicitly "prohibitted", so we don't need to care this - * kind of problem (hopefully). - * </p> - * @hide - */ - public static final int FLAG_REFRAIN_QP_TO_NAME_PROPERTIES = 0x10000000; - - /** - * <p> - * The flag indicating that phonetic name related fields must be converted to - * appropriate form. Note that "appropriate" is not defined in any vCard specification. - * This is Android-specific. - * </p> - * <p> - * One typical (and currently sole) example where we need this flag is the time when - * we need to emit Japanese phonetic names into vCard entries. The property values - * should be encoded into half-width katakana when the target importer is Japanese mobile - * phones', which are probably not able to parse full-width hiragana/katakana for - * historical reasons, while the vCard importers embedded to softwares for PC should be - * able to parse them as we expect. - * </p> - */ - public static final int FLAG_CONVERT_PHONETIC_NAME_STRINGS = 0x08000000; - - /** - * <p> - * The flag indicating the vCard composer "for 2.1" emits "TYPE=" string toward TYPE params - * every time possible. The default behavior does not emit it and is valid in the spec. - * In vCrad 3.0, this flag is unnecessary, since "TYPE=" is MUST in vCard 3.0 specification. - * </p> - * <p> - * Detail: - * How more than one TYPE fields are expressed is different between vCard 2.1 and vCard 3.0. - * </p> - * <p> - * e.g. - * </p> - * <ol> - * <li>Probably valid in both vCard 2.1 and vCard 3.0: "ADR;TYPE=DOM;TYPE=HOME:..."</li> - * <li>Valid in vCard 2.1 but not in vCard 3.0: "ADR;DOM;HOME:..."</li> - * <li>Valid in vCard 3.0 but not in vCard 2.1: "ADR;TYPE=DOM,HOME:..."</li> - * </ol> - * <p> - * If you are targeting to the importer which cannot accept TYPE params without "TYPE=" - * strings (which should be rare though), please use this flag. - * </p> - * <p> - * Example usage: - * <pre class="prettyprint">int type = (VCARD_TYPE_V21_GENERIC | FLAG_APPEND_TYPE_PARAM);</pre> - * </p> - */ - public static final int FLAG_APPEND_TYPE_PARAM = 0x04000000; - - /** - * <p> - * The flag indicating the vCard composer does touch nothing toward phone number Strings - * but leave it as is. - * </p> - * <p> - * The vCard specifications mention nothing toward phone numbers, while some devices - * do (wrongly, but with innevitable reasons). - * For example, there's a possibility Japanese mobile phones are expected to have - * just numbers, hypens, plus, etc. but not usual alphabets, while US mobile phones - * should get such characters. To make exported vCard simple for external parsers, - * we have used {@link PhoneNumberUtils#formatNumber(String)} during export, and - * removed unnecessary characters inside the number (e.g. "111-222-3333 (Miami)" - * becomes "111-222-3333"). - * Unfortunate side effect of that use was some control characters used in the other - * areas may be badly affected by the formatting. - * </p> - * <p> - * This flag disables that formatting, affecting both importer and exporter. - * If the user is aware of some side effects due to the implicit formatting, use this flag. - * </p> - */ - public static final int FLAG_REFRAIN_PHONE_NUMBER_FORMATTING = 0x02000000; - - /** - * <p> - * For importer only. Ignored in exporter. - * </p> - * <p> - * The flag indicating the parser should handle a nested vCard, in which vCard clause starts - * in another vCard clause. Here's a typical example. - * </p> - * <pre class="prettyprint">BEGIN:VCARD - * BEGIN:VCARD - * VERSION:2.1 - * ... - * END:VCARD - * END:VCARD</pre> - * <p> - * The vCard 2.1 specification allows the nest, but also let parsers ignore nested entries, - * while some mobile devices emit nested ones as primary data to be imported. - * </p> - * <p> - * This flag forces a vCard parser to torelate such a nest and understand its content. - * </p> - */ - public static final int FLAG_TORELATE_NEST = 0x01000000; - - //// The followings are VCard types available from importer/exporter. //// - - /** - * <p> - * The type indicating nothing. Used by {@link VCardSourceDetector} when it - * was not able to guess the exact vCard type. - * </p> - */ - public static final int VCARD_TYPE_UNKNOWN = 0; - - /** - * <p> - * Generic vCard format with the vCard 2.1. When composing a vCard entry, - * the US convension will be used toward formatting some values. - * </p> - * <p> - * e.g. The order of the display name would be "Prefix Given Middle Family Suffix", - * while it should be "Prefix Family Middle Given Suffix" in Japan for example. - * </p> - * <p> - * Uses UTF-8 for the charset as a charset for exporting. Note that old vCard importer - * outside Android cannot accept it since vCard 2.1 specifically does not allow - * that charset, while we need to use it to support various languages around the world. - * </p> - * <p> - * If you want to use alternative charset, you should notify the charset to the other - * compontent to be used. - * </p> - */ - public static final int VCARD_TYPE_V21_GENERIC = - (FLAG_V21 | NAME_ORDER_DEFAULT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); - - /* package */ static String VCARD_TYPE_V21_GENERIC_STR = "v21_generic"; - - /** - * <p> - * General vCard format with the version 3.0. Uses UTF-8 for the charset. - * </p> - * <p> - * Not fully ready yet. Use with caution when you use this. - * </p> - */ - public static final int VCARD_TYPE_V30_GENERIC = - (FLAG_V30 | NAME_ORDER_DEFAULT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); - - /* package */ static final String VCARD_TYPE_V30_GENERIC_STR = "v30_generic"; - - /** - * <p> - * General vCard format for the vCard 2.1 with some Europe convension. Uses Utf-8. - * Currently, only name order is considered ("Prefix Middle Given Family Suffix") - * </p> - */ - public static final int VCARD_TYPE_V21_EUROPE = - (FLAG_V21 | NAME_ORDER_EUROPE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); - - /* package */ static final String VCARD_TYPE_V21_EUROPE_STR = "v21_europe"; - - /** - * <p> - * General vCard format with the version 3.0 with some Europe convension. Uses UTF-8. - * </p> - * <p> - * Not ready yet. Use with caution when you use this. - * </p> - */ - public static final int VCARD_TYPE_V30_EUROPE = - (FLAG_V30 | NAME_ORDER_EUROPE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); - - /* package */ static final String VCARD_TYPE_V30_EUROPE_STR = "v30_europe"; - - /** - * <p> - * The vCard 2.1 format for miscellaneous Japanese devices, using UTF-8 as default charset. - * </p> - * <p> - * Not ready yet. Use with caution when you use this. - * </p> - */ - public static final int VCARD_TYPE_V21_JAPANESE = - (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); - - /* package */ static final String VCARD_TYPE_V21_JAPANESE_STR = "v21_japanese_utf8"; - - /** - * <p> - * The vCard 3.0 format for miscellaneous Japanese devices, using UTF-8 as default charset. - * </p> - * <p> - * Not ready yet. Use with caution when you use this. - * </p> - */ - public static final int VCARD_TYPE_V30_JAPANESE = - (FLAG_V30 | NAME_ORDER_JAPANESE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); - - /* package */ static final String VCARD_TYPE_V30_JAPANESE_STR = "v30_japanese_utf8"; - - /** - * <p> - * The vCard 2.1 based format which (partially) considers the convention in Japanese - * mobile phones, where phonetic names are translated to half-width katakana if - * possible, etc. It would be better to use Shift_JIS as a charset for maximum - * compatibility. - * </p> - * @hide Should not be available world wide. - */ - public static final int VCARD_TYPE_V21_JAPANESE_MOBILE = - (FLAG_V21 | NAME_ORDER_JAPANESE | - FLAG_CONVERT_PHONETIC_NAME_STRINGS | FLAG_REFRAIN_QP_TO_NAME_PROPERTIES); - - /* package */ static final String VCARD_TYPE_V21_JAPANESE_MOBILE_STR = "v21_japanese_mobile"; - - /** - * <p> - * The vCard format used in DoCoMo, which is one of Japanese mobile phone careers. - * </p> - * <p> - * Base version is vCard 2.1, but the data has several DoCoMo-specific convensions. - * No Android-specific property nor defact property is included. The "Primary" properties - * are NOT encoded to Quoted-Printable. - * </p> - * @hide Should not be available world wide. - */ - public static final int VCARD_TYPE_DOCOMO = - (VCARD_TYPE_V21_JAPANESE_MOBILE | FLAG_DOCOMO); - - /* package */ static final String VCARD_TYPE_DOCOMO_STR = "docomo"; - - public static int VCARD_TYPE_DEFAULT = VCARD_TYPE_V21_GENERIC; - - private static final Map<String, Integer> sVCardTypeMap; - private static final Set<Integer> sJapaneseMobileTypeSet; - - static { - sVCardTypeMap = new HashMap<String, Integer>(); - sVCardTypeMap.put(VCARD_TYPE_V21_GENERIC_STR, VCARD_TYPE_V21_GENERIC); - sVCardTypeMap.put(VCARD_TYPE_V30_GENERIC_STR, VCARD_TYPE_V30_GENERIC); - sVCardTypeMap.put(VCARD_TYPE_V21_EUROPE_STR, VCARD_TYPE_V21_EUROPE); - sVCardTypeMap.put(VCARD_TYPE_V30_EUROPE_STR, VCARD_TYPE_V30_EUROPE); - sVCardTypeMap.put(VCARD_TYPE_V21_JAPANESE_STR, VCARD_TYPE_V21_JAPANESE); - sVCardTypeMap.put(VCARD_TYPE_V30_JAPANESE_STR, VCARD_TYPE_V30_JAPANESE); - sVCardTypeMap.put(VCARD_TYPE_V21_JAPANESE_MOBILE_STR, VCARD_TYPE_V21_JAPANESE_MOBILE); - sVCardTypeMap.put(VCARD_TYPE_DOCOMO_STR, VCARD_TYPE_DOCOMO); - - sJapaneseMobileTypeSet = new HashSet<Integer>(); - sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE); - sJapaneseMobileTypeSet.add(VCARD_TYPE_V30_JAPANESE); - sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE_MOBILE); - sJapaneseMobileTypeSet.add(VCARD_TYPE_DOCOMO); - } - - public static int getVCardTypeFromString(final String vcardTypeString) { - final String loweredKey = vcardTypeString.toLowerCase(); - if (sVCardTypeMap.containsKey(loweredKey)) { - return sVCardTypeMap.get(loweredKey); - } else if ("default".equalsIgnoreCase(vcardTypeString)) { - return VCARD_TYPE_DEFAULT; - } else { - Log.e(LOG_TAG, "Unknown vCard type String: \"" + vcardTypeString + "\""); - return VCARD_TYPE_DEFAULT; - } - } - - public static boolean isV30(final int vcardType) { - return ((vcardType & FLAG_V30) != 0); - } - - public static boolean shouldUseQuotedPrintable(final int vcardType) { - return !isV30(vcardType); - } - - public static int getNameOrderType(final int vcardType) { - return vcardType & NAME_ORDER_MASK; - } - - public static boolean usesAndroidSpecificProperty(final int vcardType) { - return ((vcardType & FLAG_USE_ANDROID_PROPERTY) != 0); - } - - public static boolean usesDefactProperty(final int vcardType) { - return ((vcardType & FLAG_USE_DEFACT_PROPERTY) != 0); - } - - public static boolean showPerformanceLog() { - return (VCardConfig.LOG_LEVEL & VCardConfig.LOG_LEVEL_PERFORMANCE_MEASUREMENT) != 0; - } - - public static boolean shouldRefrainQPToNameProperties(final int vcardType) { - return (!shouldUseQuotedPrintable(vcardType) || - ((vcardType & FLAG_REFRAIN_QP_TO_NAME_PROPERTIES) != 0)); - } - - public static boolean appendTypeParamName(final int vcardType) { - return (isV30(vcardType) || ((vcardType & FLAG_APPEND_TYPE_PARAM) != 0)); - } - - /** - * @return true if the device is Japanese and some Japanese convension is - * applied to creating "formatted" something like FORMATTED_ADDRESS. - */ - public static boolean isJapaneseDevice(final int vcardType) { - // TODO: Some mask will be required so that this method wrongly interpret - // Japanese"-like" vCard type. - // e.g. VCARD_TYPE_V21_JAPANESE_SJIS | FLAG_APPEND_TYPE_PARAMS - return sJapaneseMobileTypeSet.contains(vcardType); - } - - /* package */ static boolean refrainPhoneNumberFormatting(final int vcardType) { - return ((vcardType & FLAG_REFRAIN_PHONE_NUMBER_FORMATTING) != 0); - } - - public static boolean needsToConvertPhoneticString(final int vcardType) { - return ((vcardType & FLAG_CONVERT_PHONETIC_NAME_STRINGS) != 0); - } - - public static boolean onlyOneNoteFieldIsAvailable(final int vcardType) { - return vcardType == VCARD_TYPE_DOCOMO; - } - - public static boolean isDoCoMo(final int vcardType) { - return ((vcardType & FLAG_DOCOMO) != 0); - } - - private VCardConfig() { - } -} diff --git a/core/java/android/pim/vcard/VCardConstants.java b/core/java/android/pim/vcard/VCardConstants.java deleted file mode 100644 index e11b1fd..0000000 --- a/core/java/android/pim/vcard/VCardConstants.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -/** - * Constants used in both exporter and importer code. - */ -public class VCardConstants { - public static final String VERSION_V21 = "2.1"; - public static final String VERSION_V30 = "3.0"; - - // The property names valid both in vCard 2.1 and 3.0. - public static final String PROPERTY_BEGIN = "BEGIN"; - public static final String PROPERTY_VERSION = "VERSION"; - public static final String PROPERTY_N = "N"; - public static final String PROPERTY_FN = "FN"; - public static final String PROPERTY_ADR = "ADR"; - public static final String PROPERTY_EMAIL = "EMAIL"; - public static final String PROPERTY_NOTE = "NOTE"; - public static final String PROPERTY_ORG = "ORG"; - public static final String PROPERTY_SOUND = "SOUND"; // Not fully supported. - public static final String PROPERTY_TEL = "TEL"; - public static final String PROPERTY_TITLE = "TITLE"; - public static final String PROPERTY_ROLE = "ROLE"; - public static final String PROPERTY_PHOTO = "PHOTO"; - public static final String PROPERTY_LOGO = "LOGO"; - public static final String PROPERTY_URL = "URL"; - public static final String PROPERTY_BDAY = "BDAY"; // Birthday - public static final String PROPERTY_END = "END"; - - // Valid property names not supported (not appropriately handled) by our vCard importer now. - public static final String PROPERTY_REV = "REV"; - public static final String PROPERTY_AGENT = "AGENT"; - - // Available in vCard 3.0. Shoud not use when composing vCard 2.1 file. - public static final String PROPERTY_NAME = "NAME"; - public static final String PROPERTY_NICKNAME = "NICKNAME"; - public static final String PROPERTY_SORT_STRING = "SORT-STRING"; - - // De-fact property values expressing phonetic names. - public static final String PROPERTY_X_PHONETIC_FIRST_NAME = "X-PHONETIC-FIRST-NAME"; - public static final String PROPERTY_X_PHONETIC_MIDDLE_NAME = "X-PHONETIC-MIDDLE-NAME"; - public static final String PROPERTY_X_PHONETIC_LAST_NAME = "X-PHONETIC-LAST-NAME"; - - // Properties both ContactsStruct in Eclair and de-fact vCard extensions - // shown in http://en.wikipedia.org/wiki/VCard support are defined here. - public static final String PROPERTY_X_AIM = "X-AIM"; - public static final String PROPERTY_X_MSN = "X-MSN"; - public static final String PROPERTY_X_YAHOO = "X-YAHOO"; - public static final String PROPERTY_X_ICQ = "X-ICQ"; - public static final String PROPERTY_X_JABBER = "X-JABBER"; - public static final String PROPERTY_X_GOOGLE_TALK = "X-GOOGLE-TALK"; - public static final String PROPERTY_X_SKYPE_USERNAME = "X-SKYPE-USERNAME"; - // Properties only ContactsStruct has. We alse use this. - public static final String PROPERTY_X_QQ = "X-QQ"; - public static final String PROPERTY_X_NETMEETING = "X-NETMEETING"; - - // Phone number for Skype, available as usual phone. - public static final String PROPERTY_X_SKYPE_PSTNNUMBER = "X-SKYPE-PSTNNUMBER"; - - // Property for Android-specific fields. - public static final String PROPERTY_X_ANDROID_CUSTOM = "X-ANDROID-CUSTOM"; - - // Properties for DoCoMo vCard. - public static final String PROPERTY_X_CLASS = "X-CLASS"; - public static final String PROPERTY_X_REDUCTION = "X-REDUCTION"; - public static final String PROPERTY_X_NO = "X-NO"; - public static final String PROPERTY_X_DCM_HMN_MODE = "X-DCM-HMN-MODE"; - - public static final String PARAM_TYPE = "TYPE"; - - public static final String PARAM_TYPE_HOME = "HOME"; - public static final String PARAM_TYPE_WORK = "WORK"; - public static final String PARAM_TYPE_FAX = "FAX"; - public static final String PARAM_TYPE_CELL = "CELL"; - public static final String PARAM_TYPE_VOICE = "VOICE"; - public static final String PARAM_TYPE_INTERNET = "INTERNET"; - - // Abbreviation of "prefered" according to vCard 2.1 specification. - // We interpret this value as "primary" property during import/export. - // - // Note: Both vCard specs does not mention anything about the requirement for this parameter, - // but there may be some vCard importer which will get confused with more than - // one "PREF"s in one property name, while Android accepts them. - public static final String PARAM_TYPE_PREF = "PREF"; - - // Phone type parameters valid in vCard and known to ContactsContract, but not so common. - public static final String PARAM_TYPE_CAR = "CAR"; - public static final String PARAM_TYPE_ISDN = "ISDN"; - public static final String PARAM_TYPE_PAGER = "PAGER"; - public static final String PARAM_TYPE_TLX = "TLX"; // Telex - - // Phone types existing in vCard 2.1 but not known to ContactsContract. - public static final String PARAM_TYPE_MODEM = "MODEM"; - public static final String PARAM_TYPE_MSG = "MSG"; - public static final String PARAM_TYPE_BBS = "BBS"; - public static final String PARAM_TYPE_VIDEO = "VIDEO"; - - public static final String PARAM_ENCODING_7BIT = "7BIT"; - public static final String PARAM_ENCODING_8BIT = "8BIT"; - public static final String PARAM_ENCODING_QP = "QUOTED-PRINTABLE"; - public static final String PARAM_ENCODING_BASE64 = "BASE64"; // Available in vCard 2.1 - public static final String PARAM_ENCODING_B = "B"; // Available in vCard 3.0 - - // TYPE parameters for Phones, which are not formally valid in vCard (at least 2.1). - // These types are basically encoded to "X-" parameters when composing vCard. - // Parser passes these when "X-" is added to the parameter or not. - public static final String PARAM_PHONE_EXTRA_TYPE_CALLBACK = "CALLBACK"; - public static final String PARAM_PHONE_EXTRA_TYPE_RADIO = "RADIO"; - public static final String PARAM_PHONE_EXTRA_TYPE_TTY_TDD = "TTY-TDD"; - public static final String PARAM_PHONE_EXTRA_TYPE_ASSISTANT = "ASSISTANT"; - // vCard composer translates this type to "WORK" + "PREF". Just for parsing. - public static final String PARAM_PHONE_EXTRA_TYPE_COMPANY_MAIN = "COMPANY-MAIN"; - // vCard composer translates this type to "VOICE" Just for parsing. - public static final String PARAM_PHONE_EXTRA_TYPE_OTHER = "OTHER"; - - // TYPE parameters for postal addresses. - public static final String PARAM_ADR_TYPE_PARCEL = "PARCEL"; - public static final String PARAM_ADR_TYPE_DOM = "DOM"; - public static final String PARAM_ADR_TYPE_INTL = "INTL"; - - // TYPE parameters not officially valid but used in some vCard exporter. - // Do not use in composer side. - public static final String PARAM_EXTRA_TYPE_COMPANY = "COMPANY"; - - public interface ImportOnly { - public static final String PROPERTY_X_NICKNAME = "X-NICKNAME"; - // Some device emits this "X-" parameter for expressing Google Talk, - // which is specifically invalid but should be always properly accepted, and emitted - // in some special case (for that device/application). - public static final String PROPERTY_X_GOOGLE_TALK_WITH_SPACE = "X-GOOGLE TALK"; - } - - //// Mainly for package constants. - - // DoCoMo specific type parameter. Used with "SOUND" property, which is alternate of - // SORT-STRING invCard 3.0. - /* package */ static final String PARAM_TYPE_X_IRMC_N = "X-IRMC-N"; - - /* 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 VCardConstants() { - } -}
\ No newline at end of file diff --git a/core/java/android/pim/vcard/VCardEntry.java b/core/java/android/pim/vcard/VCardEntry.java deleted file mode 100644 index 5b9cf17..0000000 --- a/core/java/android/pim/vcard/VCardEntry.java +++ /dev/null @@ -1,1425 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import android.accounts.Account; -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; -import android.content.ContentResolver; -import android.content.OperationApplicationException; -import android.database.Cursor; -import android.net.Uri; -import android.os.RemoteException; -import android.provider.ContactsContract; -import android.provider.ContactsContract.Contacts; -import android.provider.ContactsContract.Data; -import android.provider.ContactsContract.Groups; -import android.provider.ContactsContract.RawContacts; -import android.provider.ContactsContract.CommonDataKinds.Email; -import android.provider.ContactsContract.CommonDataKinds.Event; -import android.provider.ContactsContract.CommonDataKinds.GroupMembership; -import android.provider.ContactsContract.CommonDataKinds.Im; -import android.provider.ContactsContract.CommonDataKinds.Nickname; -import android.provider.ContactsContract.CommonDataKinds.Note; -import android.provider.ContactsContract.CommonDataKinds.Organization; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.Photo; -import android.provider.ContactsContract.CommonDataKinds.StructuredName; -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; -import android.provider.ContactsContract.CommonDataKinds.Website; -import android.telephony.PhoneNumberUtils; -import android.text.TextUtils; -import android.util.Log; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; - -/** - * This class bridges between data structure of Contact app and VCard data. - */ -public class VCardEntry { - private static final String LOG_TAG = "VCardEntry"; - - private final static int DEFAULT_ORGANIZATION_TYPE = Organization.TYPE_WORK; - - private static final Map<String, Integer> sImMap = new HashMap<String, Integer>(); - - static { - sImMap.put(VCardConstants.PROPERTY_X_AIM, Im.PROTOCOL_AIM); - sImMap.put(VCardConstants.PROPERTY_X_MSN, Im.PROTOCOL_MSN); - sImMap.put(VCardConstants.PROPERTY_X_YAHOO, Im.PROTOCOL_YAHOO); - sImMap.put(VCardConstants.PROPERTY_X_ICQ, Im.PROTOCOL_ICQ); - sImMap.put(VCardConstants.PROPERTY_X_JABBER, Im.PROTOCOL_JABBER); - sImMap.put(VCardConstants.PROPERTY_X_SKYPE_USERNAME, Im.PROTOCOL_SKYPE); - sImMap.put(VCardConstants.PROPERTY_X_GOOGLE_TALK, Im.PROTOCOL_GOOGLE_TALK); - sImMap.put(VCardConstants.ImportOnly.PROPERTY_X_GOOGLE_TALK_WITH_SPACE, - Im.PROTOCOL_GOOGLE_TALK); - } - - public static class PhoneData { - public final int type; - public final String data; - public final String label; - // isPrimary is (not final but) changable, only when there's no appropriate one existing - // in the original VCard. - public boolean isPrimary; - public PhoneData(int type, String data, String label, boolean isPrimary) { - this.type = type; - this.data = data; - this.label = label; - this.isPrimary = isPrimary; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof PhoneData)) { - return false; - } - PhoneData phoneData = (PhoneData)obj; - return (type == phoneData.type && data.equals(phoneData.data) && - label.equals(phoneData.label) && isPrimary == phoneData.isPrimary); - } - - @Override - public String toString() { - return String.format("type: %d, data: %s, label: %s, isPrimary: %s", - type, data, label, isPrimary); - } - } - - public static class EmailData { - public final int type; - public final String data; - // Used only when TYPE is TYPE_CUSTOM. - public final String label; - public boolean isPrimary; - public EmailData(int type, String data, String label, boolean isPrimary) { - this.type = type; - this.data = data; - this.label = label; - this.isPrimary = isPrimary; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof EmailData)) { - return false; - } - EmailData emailData = (EmailData)obj; - return (type == emailData.type && data.equals(emailData.data) && - label.equals(emailData.label) && isPrimary == emailData.isPrimary); - } - - @Override - public String toString() { - return String.format("type: %d, data: %s, label: %s, isPrimary: %s", - type, data, label, isPrimary); - } - } - - public static class PostalData { - // Determined by vCard specification. - // - PO Box, Extended Addr, Street, Locality, Region, Postal Code, Country Name - public static final int ADDR_MAX_DATA_SIZE = 7; - private final String[] dataArray; - public final String pobox; - public final String extendedAddress; - public final String street; - public final String localty; - public final String region; - public final String postalCode; - public final String country; - public final int type; - public final String label; - public boolean isPrimary; - - public PostalData(final int type, final List<String> propValueList, - final String label, boolean isPrimary) { - this.type = type; - dataArray = new String[ADDR_MAX_DATA_SIZE]; - - int size = propValueList.size(); - if (size > ADDR_MAX_DATA_SIZE) { - size = ADDR_MAX_DATA_SIZE; - } - - // adr-value = 0*6(text-value ";") text-value - // ; PO Box, Extended Address, Street, Locality, Region, Postal - // ; Code, Country Name - // - // Use Iterator assuming List may be LinkedList, though actually it is - // always ArrayList in the current implementation. - int i = 0; - for (String addressElement : propValueList) { - dataArray[i] = addressElement; - if (++i >= size) { - break; - } - } - while (i < ADDR_MAX_DATA_SIZE) { - dataArray[i++] = null; - } - - this.pobox = dataArray[0]; - this.extendedAddress = dataArray[1]; - this.street = dataArray[2]; - this.localty = dataArray[3]; - this.region = dataArray[4]; - this.postalCode = dataArray[5]; - this.country = dataArray[6]; - this.label = label; - this.isPrimary = isPrimary; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof PostalData)) { - return false; - } - final PostalData postalData = (PostalData)obj; - return (Arrays.equals(dataArray, postalData.dataArray) && - (type == postalData.type && - (type == StructuredPostal.TYPE_CUSTOM ? - (label == postalData.label) : true)) && - (isPrimary == postalData.isPrimary)); - } - - public String getFormattedAddress(final int vcardType) { - StringBuilder builder = new StringBuilder(); - boolean empty = true; - if (VCardConfig.isJapaneseDevice(vcardType)) { - // In Japan, the order is reversed. - for (int i = ADDR_MAX_DATA_SIZE - 1; i >= 0; i--) { - String addressPart = dataArray[i]; - if (!TextUtils.isEmpty(addressPart)) { - if (!empty) { - builder.append(' '); - } else { - empty = false; - } - builder.append(addressPart); - } - } - } else { - for (int i = 0; i < ADDR_MAX_DATA_SIZE; i++) { - String addressPart = dataArray[i]; - if (!TextUtils.isEmpty(addressPart)) { - if (!empty) { - builder.append(' '); - } else { - empty = false; - } - builder.append(addressPart); - } - } - } - - return builder.toString().trim(); - } - - @Override - public String toString() { - return String.format("type: %d, label: %s, isPrimary: %s", - type, label, isPrimary); - } - } - - public static class OrganizationData { - public final int type; - // non-final is Intentional: we may change the values since this info is separated into - // two parts in vCard: "ORG" + "TITLE", and we have to cope with each field in - // different timing. - public String companyName; - public String departmentName; - public String titleName; - public boolean isPrimary; - - public OrganizationData(int type, - String companyName, - String departmentName, - String titleName, - boolean isPrimary) { - this.type = type; - this.companyName = companyName; - this.departmentName = departmentName; - this.titleName = titleName; - this.isPrimary = isPrimary; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof OrganizationData)) { - return false; - } - OrganizationData organization = (OrganizationData)obj; - return (type == organization.type && - TextUtils.equals(companyName, organization.companyName) && - TextUtils.equals(departmentName, organization.departmentName) && - TextUtils.equals(titleName, organization.titleName) && - isPrimary == organization.isPrimary); - } - - public String getFormattedString() { - final StringBuilder builder = new StringBuilder(); - if (!TextUtils.isEmpty(companyName)) { - builder.append(companyName); - } - - if (!TextUtils.isEmpty(departmentName)) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append(departmentName); - } - - if (!TextUtils.isEmpty(titleName)) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append(titleName); - } - - return builder.toString(); - } - - @Override - public String toString() { - return String.format( - "type: %d, company: %s, department: %s, title: %s, isPrimary: %s", - type, companyName, departmentName, titleName, isPrimary); - } - } - - public static class ImData { - public final int protocol; - public final String customProtocol; - public final int type; - public final String data; - public final boolean isPrimary; - - public ImData(final int protocol, final String customProtocol, final int type, - final String data, final boolean isPrimary) { - this.protocol = protocol; - this.customProtocol = customProtocol; - this.type = type; - this.data = data; - this.isPrimary = isPrimary; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof ImData)) { - return false; - } - ImData imData = (ImData)obj; - return (type == imData.type && protocol == imData.protocol - && (customProtocol != null ? customProtocol.equals(imData.customProtocol) : - (imData.customProtocol == null)) - && (data != null ? data.equals(imData.data) : (imData.data == null)) - && isPrimary == imData.isPrimary); - } - - @Override - public String toString() { - return String.format( - "type: %d, protocol: %d, custom_protcol: %s, data: %s, isPrimary: %s", - type, protocol, customProtocol, data, isPrimary); - } - } - - public static class PhotoData { - public static final String FORMAT_FLASH = "SWF"; - public final int type; - public final String formatName; // used when type is not defined in ContactsContract. - public final byte[] photoBytes; - public final boolean isPrimary; - - public PhotoData(int type, String formatName, byte[] photoBytes, boolean isPrimary) { - this.type = type; - this.formatName = formatName; - this.photoBytes = photoBytes; - this.isPrimary = isPrimary; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof PhotoData)) { - return false; - } - PhotoData photoData = (PhotoData)obj; - return (type == photoData.type && - (formatName == null ? (photoData.formatName == null) : - formatName.equals(photoData.formatName)) && - (Arrays.equals(photoBytes, photoData.photoBytes)) && - (isPrimary == photoData.isPrimary)); - } - - @Override - public String toString() { - return String.format("type: %d, format: %s: size: %d, isPrimary: %s", - type, formatName, photoBytes.length, isPrimary); - } - } - - /* package */ static class Property { - private String mPropertyName; - private Map<String, Collection<String>> mParameterMap = - new HashMap<String, Collection<String>>(); - private List<String> mPropertyValueList = new ArrayList<String>(); - private byte[] mPropertyBytes; - - public void setPropertyName(final String propertyName) { - mPropertyName = propertyName; - } - - public void addParameter(final String paramName, final String paramValue) { - Collection<String> values; - if (!mParameterMap.containsKey(paramName)) { - if (paramName.equals("TYPE")) { - values = new HashSet<String>(); - } else { - values = new ArrayList<String>(); - } - mParameterMap.put(paramName, values); - } else { - values = mParameterMap.get(paramName); - } - values.add(paramValue); - } - - public void addToPropertyValueList(final String propertyValue) { - mPropertyValueList.add(propertyValue); - } - - public void setPropertyBytes(final byte[] propertyBytes) { - mPropertyBytes = propertyBytes; - } - - public final Collection<String> getParameters(String type) { - return mParameterMap.get(type); - } - - public final List<String> getPropertyValueList() { - return mPropertyValueList; - } - - public void clear() { - mPropertyName = null; - mParameterMap.clear(); - mPropertyValueList.clear(); - mPropertyBytes = null; - } - } - - private String mFamilyName; - private String mGivenName; - private String mMiddleName; - private String mPrefix; - private String mSuffix; - - // Used only when no family nor given name is found. - private String mFormattedName; - - private String mPhoneticFamilyName; - private String mPhoneticGivenName; - private String mPhoneticMiddleName; - - private String mPhoneticFullName; - - private List<String> mNickNameList; - - private String mDisplayName; - - private String mBirthday; - - private List<String> mNoteList; - private List<PhoneData> mPhoneList; - private List<EmailData> mEmailList; - private List<PostalData> mPostalList; - private List<OrganizationData> mOrganizationList; - private List<ImData> mImList; - private List<PhotoData> mPhotoList; - private List<String> mWebsiteList; - private List<List<String>> mAndroidCustomPropertyList; - - private final int mVCardType; - private final Account mAccount; - - public VCardEntry() { - this(VCardConfig.VCARD_TYPE_V21_GENERIC); - } - - public VCardEntry(int vcardType) { - this(vcardType, null); - } - - public VCardEntry(int vcardType, Account account) { - mVCardType = vcardType; - mAccount = account; - } - - private void addPhone(int type, String data, String label, boolean isPrimary) { - if (mPhoneList == null) { - mPhoneList = new ArrayList<PhoneData>(); - } - final StringBuilder builder = new StringBuilder(); - final String trimed = data.trim(); - final String formattedNumber; - if (type == Phone.TYPE_PAGER || VCardConfig.refrainPhoneNumberFormatting(mVCardType)) { - formattedNumber = trimed; - } else { - final int length = trimed.length(); - for (int i = 0; i < length; i++) { - char ch = trimed.charAt(i); - if (('0' <= ch && ch <= '9') || (i == 0 && ch == '+')) { - builder.append(ch); - } - } - - final int formattingType = VCardUtils.getPhoneNumberFormat(mVCardType); - formattedNumber = PhoneNumberUtils.formatNumber(builder.toString(), formattingType); - } - PhoneData phoneData = new PhoneData(type, formattedNumber, label, isPrimary); - mPhoneList.add(phoneData); - } - - private void addNickName(final String nickName) { - if (mNickNameList == null) { - mNickNameList = new ArrayList<String>(); - } - mNickNameList.add(nickName); - } - - private void addEmail(int type, String data, String label, boolean isPrimary){ - if (mEmailList == null) { - mEmailList = new ArrayList<EmailData>(); - } - mEmailList.add(new EmailData(type, data, label, isPrimary)); - } - - private void addPostal(int type, List<String> propValueList, String label, boolean isPrimary){ - if (mPostalList == null) { - mPostalList = new ArrayList<PostalData>(0); - } - mPostalList.add(new PostalData(type, propValueList, label, isPrimary)); - } - - /** - * Should be called via {@link #handleOrgValue(int, List, boolean)} or - * {@link #handleTitleValue(String)}. - */ - private void addNewOrganization(int type, final String companyName, - final String departmentName, - final String titleName, boolean isPrimary) { - if (mOrganizationList == null) { - mOrganizationList = new ArrayList<OrganizationData>(); - } - mOrganizationList.add(new OrganizationData(type, companyName, - departmentName, titleName, isPrimary)); - } - - private static final List<String> sEmptyList = - Collections.unmodifiableList(new ArrayList<String>(0)); - - /** - * Set "ORG" related values to the appropriate data. If there's more than one - * {@link OrganizationData} objects, this input data are attached to the last one which - * does not have valid values (not including empty but only null). If there's no - * {@link OrganizationData} object, a new {@link OrganizationData} is created, - * whose title is set to null. - */ - private void handleOrgValue(final int type, List<String> orgList, boolean isPrimary) { - if (orgList == null) { - orgList = sEmptyList; - } - final String companyName; - final String departmentName; - final int size = orgList.size(); - switch (size) { - case 0: { - companyName = ""; - departmentName = null; - break; - } - case 1: { - companyName = orgList.get(0); - departmentName = null; - break; - } - default: { // More than 1. - companyName = orgList.get(0); - // We're not sure which is the correct string for department. - // In order to keep all the data, concatinate the rest of elements. - StringBuilder builder = new StringBuilder(); - for (int i = 1; i < size; i++) { - if (i > 1) { - builder.append(' '); - } - builder.append(orgList.get(i)); - } - departmentName = builder.toString(); - } - } - if (mOrganizationList == null) { - // Create new first organization entry, with "null" title which may be - // added via handleTitleValue(). - addNewOrganization(type, companyName, departmentName, null, isPrimary); - return; - } - for (OrganizationData organizationData : mOrganizationList) { - // Not use TextUtils.isEmpty() since ORG was set but the elements might be empty. - // e.g. "ORG;PREF:;" -> Both companyName and departmentName become empty but not null. - if (organizationData.companyName == null && - organizationData.departmentName == null) { - // Probably the "TITLE" property comes before the "ORG" property via - // handleTitleLine(). - organizationData.companyName = companyName; - organizationData.departmentName = departmentName; - organizationData.isPrimary = isPrimary; - return; - } - } - // No OrganizatioData is available. Create another one, with "null" title, which may be - // added via handleTitleValue(). - addNewOrganization(type, companyName, departmentName, null, isPrimary); - } - - /** - * Set "title" value to the appropriate data. If there's more than one - * OrganizationData objects, this input is attached to the last one which does not - * have valid title value (not including empty but only null). If there's no - * OrganizationData object, a new OrganizationData is created, whose company name is - * set to null. - */ - private void handleTitleValue(final String title) { - if (mOrganizationList == null) { - // Create new first organization entry, with "null" other info, which may be - // added via handleOrgValue(). - addNewOrganization(DEFAULT_ORGANIZATION_TYPE, null, null, title, false); - return; - } - for (OrganizationData organizationData : mOrganizationList) { - if (organizationData.titleName == null) { - organizationData.titleName = title; - return; - } - } - // No Organization is available. Create another one, with "null" other info, which may be - // added via handleOrgValue(). - addNewOrganization(DEFAULT_ORGANIZATION_TYPE, null, null, title, false); - } - - private void addIm(int protocol, String customProtocol, int type, - String propValue, boolean isPrimary) { - if (mImList == null) { - mImList = new ArrayList<ImData>(); - } - mImList.add(new ImData(protocol, customProtocol, type, propValue, isPrimary)); - } - - private void addNote(final String note) { - if (mNoteList == null) { - mNoteList = new ArrayList<String>(1); - } - mNoteList.add(note); - } - - private void addPhotoBytes(String formatName, byte[] photoBytes, boolean isPrimary) { - if (mPhotoList == null) { - mPhotoList = new ArrayList<PhotoData>(1); - } - final PhotoData photoData = new PhotoData(0, null, photoBytes, isPrimary); - mPhotoList.add(photoData); - } - - @SuppressWarnings("fallthrough") - private void handleNProperty(List<String> elems) { - // Family, Given, Middle, Prefix, Suffix. (1 - 5) - int size; - if (elems == null || (size = elems.size()) < 1) { - return; - } - if (size > 5) { - size = 5; - } - - switch (size) { - // fallthrough - case 5: mSuffix = elems.get(4); - case 4: mPrefix = elems.get(3); - case 3: mMiddleName = elems.get(2); - case 2: mGivenName = elems.get(1); - default: mFamilyName = elems.get(0); - } - } - - /** - * Note: Some Japanese mobile phones use this field for phonetic name, - * since vCard 2.1 does not have "SORT-STRING" type. - * Also, in some cases, the field has some ';'s in it. - * Assume the ';' means the same meaning in N property - */ - @SuppressWarnings("fallthrough") - private void handlePhoneticNameFromSound(List<String> elems) { - if (!(TextUtils.isEmpty(mPhoneticFamilyName) && - TextUtils.isEmpty(mPhoneticMiddleName) && - TextUtils.isEmpty(mPhoneticGivenName))) { - // This means the other properties like "X-PHONETIC-FIRST-NAME" was already found. - // Ignore "SOUND;X-IRMC-N". - return; - } - - int size; - if (elems == null || (size = elems.size()) < 1) { - return; - } - - // Assume that the order is "Family, Given, Middle". - // This is not from specification but mere assumption. Some Japanese phones use this order. - if (size > 3) { - size = 3; - } - - if (elems.get(0).length() > 0) { - boolean onlyFirstElemIsNonEmpty = true; - for (int i = 1; i < size; i++) { - if (elems.get(i).length() > 0) { - onlyFirstElemIsNonEmpty = false; - break; - } - } - if (onlyFirstElemIsNonEmpty) { - final String[] namesArray = elems.get(0).split(" "); - final int nameArrayLength = namesArray.length; - if (nameArrayLength == 3) { - // Assume the string is "Family Middle Given". - mPhoneticFamilyName = namesArray[0]; - mPhoneticMiddleName = namesArray[1]; - mPhoneticGivenName = namesArray[2]; - } else if (nameArrayLength == 2) { - // Assume the string is "Family Given" based on the Japanese mobile - // phones' preference. - mPhoneticFamilyName = namesArray[0]; - mPhoneticGivenName = namesArray[1]; - } else { - mPhoneticFullName = elems.get(0); - } - return; - } - } - - switch (size) { - // fallthrough - case 3: mPhoneticMiddleName = elems.get(2); - case 2: mPhoneticGivenName = elems.get(1); - default: mPhoneticFamilyName = elems.get(0); - } - } - - public void addProperty(final Property property) { - final String propName = property.mPropertyName; - final Map<String, Collection<String>> paramMap = property.mParameterMap; - final List<String> propValueList = property.mPropertyValueList; - byte[] propBytes = property.mPropertyBytes; - - if (propValueList.size() == 0) { - return; - } - final String propValue = listToString(propValueList).trim(); - - if (propName.equals(VCardConstants.PROPERTY_VERSION)) { - // vCard version. Ignore this. - } else if (propName.equals(VCardConstants.PROPERTY_FN)) { - mFormattedName = propValue; - } else if (propName.equals(VCardConstants.PROPERTY_NAME) && mFormattedName == null) { - // Only in vCard 3.0. Use this if FN, which must exist in vCard 3.0 but may not - // actually exist in the real vCard data, does not exist. - mFormattedName = propValue; - } else if (propName.equals(VCardConstants.PROPERTY_N)) { - handleNProperty(propValueList); - } else if (propName.equals(VCardConstants.PROPERTY_SORT_STRING)) { - mPhoneticFullName = propValue; - } else if (propName.equals(VCardConstants.PROPERTY_NICKNAME) || - propName.equals(VCardConstants.ImportOnly.PROPERTY_X_NICKNAME)) { - addNickName(propValue); - } else if (propName.equals(VCardConstants.PROPERTY_SOUND)) { - Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE); - if (typeCollection != null - && typeCollection.contains(VCardConstants.PARAM_TYPE_X_IRMC_N)) { - // As of 2009-10-08, Parser side does not split a property value into separated - // values using ';' (in other words, propValueList.size() == 1), - // which is correct behavior from the view of vCard 2.1. - // But we want it to be separated, so do the separation here. - final List<String> phoneticNameList = - VCardUtils.constructListFromValue(propValue, - VCardConfig.isV30(mVCardType)); - handlePhoneticNameFromSound(phoneticNameList); - } else { - // Ignore this field since Android cannot understand what it is. - } - } else if (propName.equals(VCardConstants.PROPERTY_ADR)) { - boolean valuesAreAllEmpty = true; - for (String value : propValueList) { - if (value.length() > 0) { - valuesAreAllEmpty = false; - break; - } - } - if (valuesAreAllEmpty) { - return; - } - - int type = -1; - String label = ""; - boolean isPrimary = false; - Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE); - if (typeCollection != null) { - for (String typeString : typeCollection) { - typeString = typeString.toUpperCase(); - if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) { - isPrimary = true; - } else if (typeString.equals(VCardConstants.PARAM_TYPE_HOME)) { - type = StructuredPostal.TYPE_HOME; - label = ""; - } else if (typeString.equals(VCardConstants.PARAM_TYPE_WORK) || - typeString.equalsIgnoreCase(VCardConstants.PARAM_EXTRA_TYPE_COMPANY)) { - // "COMPANY" seems emitted by Windows Mobile, which is not - // specifically supported by vCard 2.1. We assume this is same - // as "WORK". - type = StructuredPostal.TYPE_WORK; - label = ""; - } else if (typeString.equals(VCardConstants.PARAM_ADR_TYPE_PARCEL) || - typeString.equals(VCardConstants.PARAM_ADR_TYPE_DOM) || - typeString.equals(VCardConstants.PARAM_ADR_TYPE_INTL)) { - // We do not have any appropriate way to store this information. - } else { - if (typeString.startsWith("X-") && type < 0) { - typeString = typeString.substring(2); - } - // vCard 3.0 allows iana-token. Also some vCard 2.1 exporters - // emit non-standard types. We do not handle their values now. - type = StructuredPostal.TYPE_CUSTOM; - label = typeString; - } - } - } - // We use "HOME" as default - if (type < 0) { - type = StructuredPostal.TYPE_HOME; - } - - addPostal(type, propValueList, label, isPrimary); - } else if (propName.equals(VCardConstants.PROPERTY_EMAIL)) { - int type = -1; - String label = null; - boolean isPrimary = false; - Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE); - if (typeCollection != null) { - for (String typeString : typeCollection) { - typeString = typeString.toUpperCase(); - if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) { - isPrimary = true; - } else if (typeString.equals(VCardConstants.PARAM_TYPE_HOME)) { - type = Email.TYPE_HOME; - } else if (typeString.equals(VCardConstants.PARAM_TYPE_WORK)) { - type = Email.TYPE_WORK; - } else if (typeString.equals(VCardConstants.PARAM_TYPE_CELL)) { - type = Email.TYPE_MOBILE; - } else { - if (typeString.startsWith("X-") && type < 0) { - typeString = typeString.substring(2); - } - // vCard 3.0 allows iana-token. - // We may have INTERNET (specified in vCard spec), - // SCHOOL, etc. - type = Email.TYPE_CUSTOM; - label = typeString; - } - } - } - if (type < 0) { - type = Email.TYPE_OTHER; - } - addEmail(type, propValue, label, isPrimary); - } else if (propName.equals(VCardConstants.PROPERTY_ORG)) { - // vCard specification does not specify other types. - final int type = Organization.TYPE_WORK; - boolean isPrimary = false; - Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE); - if (typeCollection != null) { - for (String typeString : typeCollection) { - if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) { - isPrimary = true; - } - } - } - handleOrgValue(type, propValueList, isPrimary); - } else if (propName.equals(VCardConstants.PROPERTY_TITLE)) { - handleTitleValue(propValue); - } else if (propName.equals(VCardConstants.PROPERTY_ROLE)) { - // This conflicts with TITLE. Ignore for now... - // handleTitleValue(propValue); - } else if (propName.equals(VCardConstants.PROPERTY_PHOTO) || - propName.equals(VCardConstants.PROPERTY_LOGO)) { - Collection<String> paramMapValue = paramMap.get("VALUE"); - if (paramMapValue != null && paramMapValue.contains("URL")) { - // Currently we do not have appropriate example for testing this case. - } else { - final Collection<String> typeCollection = paramMap.get("TYPE"); - String formatName = null; - boolean isPrimary = false; - if (typeCollection != null) { - for (String typeValue : typeCollection) { - if (VCardConstants.PARAM_TYPE_PREF.equals(typeValue)) { - isPrimary = true; - } else if (formatName == null){ - formatName = typeValue; - } - } - } - addPhotoBytes(formatName, propBytes, isPrimary); - } - } else if (propName.equals(VCardConstants.PROPERTY_TEL)) { - final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE); - final Object typeObject = - VCardUtils.getPhoneTypeFromStrings(typeCollection, propValue); - final int type; - final String label; - if (typeObject instanceof Integer) { - type = (Integer)typeObject; - label = null; - } else { - type = Phone.TYPE_CUSTOM; - label = typeObject.toString(); - } - - final boolean isPrimary; - if (typeCollection != null && typeCollection.contains(VCardConstants.PARAM_TYPE_PREF)) { - isPrimary = true; - } else { - isPrimary = false; - } - addPhone(type, propValue, label, isPrimary); - } else if (propName.equals(VCardConstants.PROPERTY_X_SKYPE_PSTNNUMBER)) { - // The phone number available via Skype. - Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE); - final int type = Phone.TYPE_OTHER; - final boolean isPrimary; - if (typeCollection != null && typeCollection.contains(VCardConstants.PARAM_TYPE_PREF)) { - isPrimary = true; - } else { - isPrimary = false; - } - addPhone(type, propValue, null, isPrimary); - } else if (sImMap.containsKey(propName)) { - final int protocol = sImMap.get(propName); - boolean isPrimary = false; - int type = -1; - final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE); - if (typeCollection != null) { - for (String typeString : typeCollection) { - if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) { - isPrimary = true; - } else if (type < 0) { - if (typeString.equalsIgnoreCase(VCardConstants.PARAM_TYPE_HOME)) { - type = Im.TYPE_HOME; - } else if (typeString.equalsIgnoreCase(VCardConstants.PARAM_TYPE_WORK)) { - type = Im.TYPE_WORK; - } - } - } - } - if (type < 0) { - type = Phone.TYPE_HOME; - } - addIm(protocol, null, type, propValue, isPrimary); - } else if (propName.equals(VCardConstants.PROPERTY_NOTE)) { - addNote(propValue); - } else if (propName.equals(VCardConstants.PROPERTY_URL)) { - if (mWebsiteList == null) { - mWebsiteList = new ArrayList<String>(1); - } - mWebsiteList.add(propValue); - } else if (propName.equals(VCardConstants.PROPERTY_BDAY)) { - mBirthday = propValue; - } else if (propName.equals(VCardConstants.PROPERTY_X_PHONETIC_FIRST_NAME)) { - mPhoneticGivenName = propValue; - } else if (propName.equals(VCardConstants.PROPERTY_X_PHONETIC_MIDDLE_NAME)) { - mPhoneticMiddleName = propValue; - } else if (propName.equals(VCardConstants.PROPERTY_X_PHONETIC_LAST_NAME)) { - mPhoneticFamilyName = propValue; - } else if (propName.equals(VCardConstants.PROPERTY_X_ANDROID_CUSTOM)) { - final List<String> customPropertyList = - VCardUtils.constructListFromValue(propValue, - VCardConfig.isV30(mVCardType)); - handleAndroidCustomProperty(customPropertyList); - /*} else if (propName.equals("REV")) { - // Revision of this VCard entry. I think we can ignore this. - } else if (propName.equals("UID")) { - } else if (propName.equals("KEY")) { - // Type is X509 or PGP? I don't know how to handle this... - } else if (propName.equals("MAILER")) { - } else if (propName.equals("TZ")) { - } else if (propName.equals("GEO")) { - } else if (propName.equals("CLASS")) { - // vCard 3.0 only. - // e.g. CLASS:CONFIDENTIAL - } else if (propName.equals("PROFILE")) { - // VCard 3.0 only. Must be "VCARD". I think we can ignore this. - } else if (propName.equals("CATEGORIES")) { - // VCard 3.0 only. - // e.g. CATEGORIES:INTERNET,IETF,INDUSTRY,INFORMATION TECHNOLOGY - } else if (propName.equals("SOURCE")) { - // VCard 3.0 only. - } else if (propName.equals("PRODID")) { - // VCard 3.0 only. - // To specify the identifier for the product that created - // the vCard object.*/ - } else { - // Unknown X- words and IANA token. - } - } - - private void handleAndroidCustomProperty(final List<String> customPropertyList) { - if (mAndroidCustomPropertyList == null) { - mAndroidCustomPropertyList = new ArrayList<List<String>>(); - } - mAndroidCustomPropertyList.add(customPropertyList); - } - - /** - * Construct the display name. The constructed data must not be null. - */ - private void constructDisplayName() { - // FullName (created via "FN" or "NAME" field) is prefered. - if (!TextUtils.isEmpty(mFormattedName)) { - mDisplayName = mFormattedName; - } else if (!(TextUtils.isEmpty(mFamilyName) && TextUtils.isEmpty(mGivenName))) { - mDisplayName = VCardUtils.constructNameFromElements(mVCardType, - mFamilyName, mMiddleName, mGivenName, mPrefix, mSuffix); - } else if (!(TextUtils.isEmpty(mPhoneticFamilyName) && - TextUtils.isEmpty(mPhoneticGivenName))) { - mDisplayName = VCardUtils.constructNameFromElements(mVCardType, - mPhoneticFamilyName, mPhoneticMiddleName, mPhoneticGivenName); - } else if (mEmailList != null && mEmailList.size() > 0) { - mDisplayName = mEmailList.get(0).data; - } else if (mPhoneList != null && mPhoneList.size() > 0) { - mDisplayName = mPhoneList.get(0).data; - } else if (mPostalList != null && mPostalList.size() > 0) { - mDisplayName = mPostalList.get(0).getFormattedAddress(mVCardType); - } else if (mOrganizationList != null && mOrganizationList.size() > 0) { - mDisplayName = mOrganizationList.get(0).getFormattedString(); - } - - if (mDisplayName == null) { - mDisplayName = ""; - } - } - - /** - * Consolidate several fielsds (like mName) using name candidates, - */ - public void consolidateFields() { - constructDisplayName(); - - if (mPhoneticFullName != null) { - mPhoneticFullName = mPhoneticFullName.trim(); - } - } - - public Uri pushIntoContentResolver(ContentResolver resolver) { - ArrayList<ContentProviderOperation> operationList = - new ArrayList<ContentProviderOperation>(); - // After applying the batch the first result's Uri is returned so it is important that - // the RawContact is the first operation that gets inserted into the list - ContentProviderOperation.Builder builder = - ContentProviderOperation.newInsert(RawContacts.CONTENT_URI); - String myGroupsId = null; - if (mAccount != null) { - builder.withValue(RawContacts.ACCOUNT_NAME, mAccount.name); - builder.withValue(RawContacts.ACCOUNT_TYPE, mAccount.type); - } else { - builder.withValue(RawContacts.ACCOUNT_NAME, null); - builder.withValue(RawContacts.ACCOUNT_TYPE, null); - } - operationList.add(builder.build()); - - if (!nameFieldsAreEmpty()) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(StructuredName.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); - - builder.withValue(StructuredName.GIVEN_NAME, mGivenName); - builder.withValue(StructuredName.FAMILY_NAME, mFamilyName); - builder.withValue(StructuredName.MIDDLE_NAME, mMiddleName); - builder.withValue(StructuredName.PREFIX, mPrefix); - builder.withValue(StructuredName.SUFFIX, mSuffix); - - if (!(TextUtils.isEmpty(mPhoneticGivenName) - && TextUtils.isEmpty(mPhoneticFamilyName) - && TextUtils.isEmpty(mPhoneticMiddleName))) { - builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, mPhoneticGivenName); - builder.withValue(StructuredName.PHONETIC_FAMILY_NAME, mPhoneticFamilyName); - builder.withValue(StructuredName.PHONETIC_MIDDLE_NAME, mPhoneticMiddleName); - } else if (!TextUtils.isEmpty(mPhoneticFullName)) { - builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, mPhoneticFullName); - } - - builder.withValue(StructuredName.DISPLAY_NAME, getDisplayName()); - operationList.add(builder.build()); - } - - if (mNickNameList != null && mNickNameList.size() > 0) { - for (String nickName : mNickNameList) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(Nickname.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE); - builder.withValue(Nickname.TYPE, Nickname.TYPE_DEFAULT); - builder.withValue(Nickname.NAME, nickName); - operationList.add(builder.build()); - } - } - - if (mPhoneList != null) { - for (PhoneData phoneData : mPhoneList) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(Phone.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); - - builder.withValue(Phone.TYPE, phoneData.type); - if (phoneData.type == Phone.TYPE_CUSTOM) { - builder.withValue(Phone.LABEL, phoneData.label); - } - builder.withValue(Phone.NUMBER, phoneData.data); - if (phoneData.isPrimary) { - builder.withValue(Phone.IS_PRIMARY, 1); - } - operationList.add(builder.build()); - } - } - - if (mOrganizationList != null) { - for (OrganizationData organizationData : mOrganizationList) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(Organization.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE); - builder.withValue(Organization.TYPE, organizationData.type); - if (organizationData.companyName != null) { - builder.withValue(Organization.COMPANY, organizationData.companyName); - } - if (organizationData.departmentName != null) { - builder.withValue(Organization.DEPARTMENT, organizationData.departmentName); - } - if (organizationData.titleName != null) { - builder.withValue(Organization.TITLE, organizationData.titleName); - } - if (organizationData.isPrimary) { - builder.withValue(Organization.IS_PRIMARY, 1); - } - operationList.add(builder.build()); - } - } - - if (mEmailList != null) { - for (EmailData emailData : mEmailList) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(Email.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); - - builder.withValue(Email.TYPE, emailData.type); - if (emailData.type == Email.TYPE_CUSTOM) { - builder.withValue(Email.LABEL, emailData.label); - } - builder.withValue(Email.DATA, emailData.data); - if (emailData.isPrimary) { - builder.withValue(Data.IS_PRIMARY, 1); - } - operationList.add(builder.build()); - } - } - - if (mPostalList != null) { - for (PostalData postalData : mPostalList) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - VCardUtils.insertStructuredPostalDataUsingContactsStruct( - mVCardType, builder, postalData); - operationList.add(builder.build()); - } - } - - if (mImList != null) { - for (ImData imData : mImList) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(Im.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE); - builder.withValue(Im.TYPE, imData.type); - builder.withValue(Im.PROTOCOL, imData.protocol); - if (imData.protocol == Im.PROTOCOL_CUSTOM) { - builder.withValue(Im.CUSTOM_PROTOCOL, imData.customProtocol); - } - if (imData.isPrimary) { - builder.withValue(Data.IS_PRIMARY, 1); - } - } - } - - if (mNoteList != null) { - for (String note : mNoteList) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(Note.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, Note.CONTENT_ITEM_TYPE); - builder.withValue(Note.NOTE, note); - operationList.add(builder.build()); - } - } - - if (mPhotoList != null) { - for (PhotoData photoData : mPhotoList) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(Photo.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); - builder.withValue(Photo.PHOTO, photoData.photoBytes); - if (photoData.isPrimary) { - builder.withValue(Photo.IS_PRIMARY, 1); - } - operationList.add(builder.build()); - } - } - - if (mWebsiteList != null) { - for (String website : mWebsiteList) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(Website.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, Website.CONTENT_ITEM_TYPE); - builder.withValue(Website.URL, website); - // There's no information about the type of URL in vCard. - // We use TYPE_HOMEPAGE for safety. - builder.withValue(Website.TYPE, Website.TYPE_HOMEPAGE); - operationList.add(builder.build()); - } - } - - if (!TextUtils.isEmpty(mBirthday)) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(Event.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE); - builder.withValue(Event.START_DATE, mBirthday); - builder.withValue(Event.TYPE, Event.TYPE_BIRTHDAY); - operationList.add(builder.build()); - } - - if (mAndroidCustomPropertyList != null) { - for (List<String> customPropertyList : mAndroidCustomPropertyList) { - int size = customPropertyList.size(); - if (size < 2 || TextUtils.isEmpty(customPropertyList.get(0))) { - continue; - } else if (size > VCardConstants.MAX_DATA_COLUMN + 1) { - size = VCardConstants.MAX_DATA_COLUMN + 1; - customPropertyList = - customPropertyList.subList(0, VCardConstants.MAX_DATA_COLUMN + 2); - } - - int i = 0; - for (final String customPropertyValue : customPropertyList) { - if (i == 0) { - final String mimeType = customPropertyValue; - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, mimeType); - } else { // 1 <= i && i <= MAX_DATA_COLUMNS - if (!TextUtils.isEmpty(customPropertyValue)) { - builder.withValue("data" + i, customPropertyValue); - } - } - - i++; - } - operationList.add(builder.build()); - } - } - - if (myGroupsId != null) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE); - builder.withValue(GroupMembership.GROUP_SOURCE_ID, myGroupsId); - operationList.add(builder.build()); - } - - try { - ContentProviderResult[] results = resolver.applyBatch( - ContactsContract.AUTHORITY, operationList); - // the first result is always the raw_contact. return it's uri so - // that it can be found later. do null checking for badly behaving - // ContentResolvers - return (results == null || results.length == 0 || results[0] == null) - ? null - : results[0].uri; - } catch (RemoteException e) { - Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage())); - return null; - } catch (OperationApplicationException e) { - Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage())); - return null; - } - } - - public static VCardEntry buildFromResolver(ContentResolver resolver) { - return buildFromResolver(resolver, Contacts.CONTENT_URI); - } - - public static VCardEntry buildFromResolver(ContentResolver resolver, Uri uri) { - - return null; - } - - private boolean nameFieldsAreEmpty() { - return (TextUtils.isEmpty(mFamilyName) - && TextUtils.isEmpty(mMiddleName) - && TextUtils.isEmpty(mGivenName) - && TextUtils.isEmpty(mPrefix) - && TextUtils.isEmpty(mSuffix) - && TextUtils.isEmpty(mFormattedName) - && TextUtils.isEmpty(mPhoneticFamilyName) - && TextUtils.isEmpty(mPhoneticMiddleName) - && TextUtils.isEmpty(mPhoneticGivenName) - && TextUtils.isEmpty(mPhoneticFullName)); - } - - public boolean isIgnorable() { - return getDisplayName().length() == 0; - } - - private String listToString(List<String> list){ - final int size = list.size(); - if (size > 1) { - StringBuilder builder = new StringBuilder(); - int i = 0; - for (String type : list) { - builder.append(type); - if (i < size - 1) { - builder.append(";"); - } - } - return builder.toString(); - } else if (size == 1) { - return list.get(0); - } else { - return ""; - } - } - - // All getter methods should be used carefully, since they may change - // in the future as of 2009-10-05, on which I cannot be sure this structure - // is completely consolidated. - // - // Also note that these getter methods should be used only after - // all properties being pushed into this object. If not, incorrect - // value will "be stored in the local cache and" be returned to you. - - public String getFamilyName() { - return mFamilyName; - } - - public String getGivenName() { - return mGivenName; - } - - public String getMiddleName() { - return mMiddleName; - } - - public String getPrefix() { - return mPrefix; - } - - public String getSuffix() { - return mSuffix; - } - - public String getFullName() { - return mFormattedName; - } - - public String getPhoneticFamilyName() { - return mPhoneticFamilyName; - } - - public String getPhoneticGivenName() { - return mPhoneticGivenName; - } - - public String getPhoneticMiddleName() { - return mPhoneticMiddleName; - } - - public String getPhoneticFullName() { - return mPhoneticFullName; - } - - public final List<String> getNickNameList() { - return mNickNameList; - } - - public String getBirthday() { - return mBirthday; - } - - public final List<String> getNotes() { - return mNoteList; - } - - public final List<PhoneData> getPhoneList() { - return mPhoneList; - } - - public final List<EmailData> getEmailList() { - return mEmailList; - } - - public final List<PostalData> getPostalList() { - return mPostalList; - } - - public final List<OrganizationData> getOrganizationList() { - return mOrganizationList; - } - - public final List<ImData> getImList() { - return mImList; - } - - public final List<PhotoData> getPhotoList() { - return mPhotoList; - } - - public final List<String> getWebsiteList() { - return mWebsiteList; - } - - public String getDisplayName() { - if (mDisplayName == null) { - constructDisplayName(); - } - return mDisplayName; - } -} diff --git a/core/java/android/pim/vcard/VCardEntryCommitter.java b/core/java/android/pim/vcard/VCardEntryCommitter.java deleted file mode 100644 index a8c8057..0000000 --- a/core/java/android/pim/vcard/VCardEntryCommitter.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import android.content.ContentResolver; -import android.net.Uri; -import android.util.Log; - -import java.util.ArrayList; - -/** - * <P> - * {@link VCardEntryHandler} implementation which commits the entry to ContentResolver. - * </P> - * <P> - * Note:<BR /> - * Each vCard may contain big photo images encoded by BASE64, - * If we store all vCard entries in memory, OutOfMemoryError may be thrown. - * Thus, this class push each VCard entry into ContentResolver immediately. - * </P> - */ -public class VCardEntryCommitter implements VCardEntryHandler { - public static String LOG_TAG = "VCardEntryComitter"; - - private final ContentResolver mContentResolver; - private long mTimeToCommit; - private ArrayList<Uri> mCreatedUris = new ArrayList<Uri>(); - - public VCardEntryCommitter(ContentResolver resolver) { - mContentResolver = resolver; - } - - public void onStart() { - } - - public void onEnd() { - if (VCardConfig.showPerformanceLog()) { - Log.d(LOG_TAG, String.format("time to commit entries: %d ms", mTimeToCommit)); - } - } - - public void onEntryCreated(final VCardEntry vcardEntry) { - long start = System.currentTimeMillis(); - mCreatedUris.add(vcardEntry.pushIntoContentResolver(mContentResolver)); - mTimeToCommit += System.currentTimeMillis() - start; - } - - /** - * Returns the list of created Uris. This list should not be modified by the caller as it is - * not a clone. - */ - public ArrayList<Uri> getCreatedUris() { - return mCreatedUris; - } -}
\ No newline at end of file diff --git a/core/java/android/pim/vcard/VCardEntryConstructor.java b/core/java/android/pim/vcard/VCardEntryConstructor.java deleted file mode 100644 index a0abae8..0000000 --- a/core/java/android/pim/vcard/VCardEntryConstructor.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import android.accounts.Account; -import android.text.TextUtils; -import android.util.CharsetUtils; -import android.util.Log; - -import org.apache.commons.codec.binary.Base64; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * <p> - * The {@link VCardInterpreter} implementation which enables {@link VCardEntryHandler} objects - * to easily handle each vCard entry. - * </p> - * <p> - * This class understand details inside vCard and translates it to {@link VCardEntry}. - * Then the class throw it to {@link VCardEntryHandler} registered via - * {@link #addEntryHandler(VCardEntryHandler)}, so that all those registered objects - * are able to handle the {@link VCardEntry} object. - * </p> - * <p> - * If you want to know the detail inside vCard, it would be better to implement - * {@link VCardInterpreter} directly, instead of relying on this class and - * {@link VCardEntry} created by the object. - * </p> - */ -public class VCardEntryConstructor implements VCardInterpreter { - private static String LOG_TAG = "VCardEntryConstructor"; - - private VCardEntry.Property mCurrentProperty = new VCardEntry.Property(); - private VCardEntry mCurrentVCardEntry; - private String mParamType; - - // The charset using which {@link VCardInterpreter} parses the text. - // Each String is first decoded into binary stream with this charset, and encoded back - // to "target charset", which may be explicitly specified by the vCard with "CHARSET" - // property or implicitly mentioned by its version (e.g. vCard 3.0 recommends UTF-8). - private final String mSourceCharset; - - private final boolean mStrictLineBreaking; - private final int mVCardType; - private final Account mAccount; - - // For measuring performance. - private long mTimePushIntoContentResolver; - - private final List<VCardEntryHandler> mEntryHandlers = new ArrayList<VCardEntryHandler>(); - - public VCardEntryConstructor() { - this(VCardConfig.VCARD_TYPE_V21_GENERIC, null, null, false); - } - - public VCardEntryConstructor(final int vcardType) { - this(vcardType, null, null, false); - } - - public VCardEntryConstructor(final int vcardType, final Account account) { - this(vcardType, account, null, false); - } - - public VCardEntryConstructor(final int vcardType, final Account account, - final String inputCharset) { - this(vcardType, account, inputCharset, false); - } - - /** - * @hide - */ - public VCardEntryConstructor(final int vcardType, final Account account, - final String inputCharset, final boolean strictLineBreakParsing) { - if (inputCharset != null) { - mSourceCharset = inputCharset; - } else { - mSourceCharset = VCardConfig.DEFAULT_INTERMEDIATE_CHARSET; - } - mStrictLineBreaking = strictLineBreakParsing; - mVCardType = vcardType; - mAccount = account; - } - - public void addEntryHandler(VCardEntryHandler entryHandler) { - mEntryHandlers.add(entryHandler); - } - - public void start() { - for (VCardEntryHandler entryHandler : mEntryHandlers) { - entryHandler.onStart(); - } - } - - public void end() { - for (VCardEntryHandler entryHandler : mEntryHandlers) { - entryHandler.onEnd(); - } - } - - public void clear() { - mCurrentVCardEntry = null; - mCurrentProperty = new VCardEntry.Property(); - } - - public void startEntry() { - if (mCurrentVCardEntry != null) { - Log.e(LOG_TAG, "Nested VCard code is not supported now."); - } - mCurrentVCardEntry = new VCardEntry(mVCardType, mAccount); - } - - public void endEntry() { - mCurrentVCardEntry.consolidateFields(); - for (VCardEntryHandler entryHandler : mEntryHandlers) { - entryHandler.onEntryCreated(mCurrentVCardEntry); - } - mCurrentVCardEntry = null; - } - - public void startProperty() { - mCurrentProperty.clear(); - } - - public void endProperty() { - mCurrentVCardEntry.addProperty(mCurrentProperty); - } - - public void propertyName(String name) { - mCurrentProperty.setPropertyName(name); - } - - public void propertyGroup(String group) { - } - - public void propertyParamType(String type) { - if (mParamType != null) { - Log.e(LOG_TAG, "propertyParamType() is called more than once " + - "before propertyParamValue() is called"); - } - mParamType = type; - } - - public void propertyParamValue(String value) { - if (mParamType == null) { - // From vCard 2.1 specification. vCard 3.0 formally does not allow this case. - mParamType = "TYPE"; - } - mCurrentProperty.addParameter(mParamType, value); - mParamType = null; - } - - private static String encodeToSystemCharset(String originalString, - String sourceCharset, String targetCharset) { - if (sourceCharset.equalsIgnoreCase(targetCharset)) { - return originalString; - } - final Charset charset = Charset.forName(sourceCharset); - final ByteBuffer byteBuffer = charset.encode(originalString); - // byteBuffer.array() "may" return byte array which is larger than - // byteBuffer.remaining(). Here, we keep on the safe side. - final byte[] bytes = new byte[byteBuffer.remaining()]; - byteBuffer.get(bytes); - try { - String ret = new String(bytes, targetCharset); - return ret; - } catch (UnsupportedEncodingException e) { - Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset); - return null; - } - } - - private String handleOneValue(String value, - String sourceCharset, String targetCharset, String encoding) { - if (encoding != null) { - if (encoding.equals("BASE64") || encoding.equals("B")) { - mCurrentProperty.setPropertyBytes(Base64.decodeBase64(value.getBytes())); - return value; - } else if (encoding.equals("QUOTED-PRINTABLE")) { - return VCardUtils.parseQuotedPrintable( - value, mStrictLineBreaking, sourceCharset, targetCharset); - } - Log.w(LOG_TAG, "Unknown encoding. Fall back to default."); - } - - // Just translate the charset of a given String from inputCharset to a system one. - return encodeToSystemCharset(value, sourceCharset, targetCharset); - } - - public void propertyValues(List<String> values) { - if (values == null || values.isEmpty()) { - return; - } - - final Collection<String> charsetCollection = mCurrentProperty.getParameters("CHARSET"); - final Collection<String> encodingCollection = mCurrentProperty.getParameters("ENCODING"); - final String encoding = - ((encodingCollection != null) ? encodingCollection.iterator().next() : null); - String targetCharset = CharsetUtils.nameForDefaultVendor( - ((charsetCollection != null) ? charsetCollection.iterator().next() : null)); - if (TextUtils.isEmpty(targetCharset)) { - targetCharset = VCardConfig.DEFAULT_IMPORT_CHARSET; - } - - for (final String value : values) { - mCurrentProperty.addToPropertyValueList( - handleOneValue(value, mSourceCharset, targetCharset, encoding)); - } - } - - /** - * @hide - */ - public void showPerformanceInfo() { - Log.d(LOG_TAG, "time for insert ContactStruct to database: " + - mTimePushIntoContentResolver + " ms"); - } -} diff --git a/core/java/android/pim/vcard/VCardEntryCounter.java b/core/java/android/pim/vcard/VCardEntryCounter.java deleted file mode 100644 index 7bab50d..0000000 --- a/core/java/android/pim/vcard/VCardEntryCounter.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import java.util.List; - -/** - * The class which just counts the number of vCard entries in the specified input. - */ -public class VCardEntryCounter implements VCardInterpreter { - private int mCount; - - public int getCount() { - return mCount; - } - - public void start() { - } - - public void end() { - } - - public void startEntry() { - } - - public void endEntry() { - mCount++; - } - - public void startProperty() { - } - - public void endProperty() { - } - - public void propertyGroup(String group) { - } - - public void propertyName(String name) { - } - - public void propertyParamType(String type) { - } - - public void propertyParamValue(String value) { - } - - public void propertyValues(List<String> values) { - } -} diff --git a/core/java/android/pim/vcard/VCardEntryHandler.java b/core/java/android/pim/vcard/VCardEntryHandler.java deleted file mode 100644 index 56bf69d..0000000 --- a/core/java/android/pim/vcard/VCardEntryHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -/** - * <p> - * The interface called by {@link VCardEntryConstructor}. - * </p> - * <p> - * This class is useful when you don't want to know vCard data in detail. If you want to know - * it, it would be better to consider using {@link VCardInterpreter}. - * </p> - */ -public interface VCardEntryHandler { - /** - * Called when the parsing started. - */ - public void onStart(); - - /** - * The method called when one VCard entry is successfully created - */ - public void onEntryCreated(final VCardEntry entry); - - /** - * Called when the parsing ended. - * Able to be use this method for showing performance log, etc. - */ - public void onEnd(); -} diff --git a/core/java/android/pim/vcard/VCardInterpreter.java b/core/java/android/pim/vcard/VCardInterpreter.java deleted file mode 100644 index 03704a2..0000000 --- a/core/java/android/pim/vcard/VCardInterpreter.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import java.util.List; - -/** - * <P> - * The interface which should be implemented by the classes which have to analyze each - * vCard entry minutely. - * </P> - * <P> - * Here, there are several terms specific to vCard (and this library). - * </P> - * <P> - * The term "entry" is one vCard representation in the input, which should start with "BEGIN:VCARD" - * and end with "END:VCARD". - * </P> - * <P> - * The term "property" is one line in vCard entry, which consists of "group", "property name", - * "parameter(param) names and values", and "property values". - * </P> - * <P> - * e.g. group1.propName;paramName1=paramValue1;paramName2=paramValue2;propertyValue1;propertyValue2... - * </P> - */ -public interface VCardInterpreter { - /** - * Called when vCard interpretation started. - */ - void start(); - - /** - * Called when vCard interpretation finished. - */ - void end(); - - /** - * Called when parsing one vCard entry started. - * More specifically, this method is called when "BEGIN:VCARD" is read. - */ - void startEntry(); - - /** - * Called when parsing one vCard entry ended. - * More specifically, this method is called when "END:VCARD" is read. - * Note that {@link #startEntry()} may be called since - * vCard (especially 2.1) allows nested vCard. - */ - void endEntry(); - - /** - * Called when reading one property started. - */ - void startProperty(); - - /** - * Called when reading one property ended. - */ - void endProperty(); - - /** - * @param group A group name. This method may be called more than once or may not be - * called at all, depending on how many gruoups are appended to the property. - */ - void propertyGroup(String group); - - /** - * @param name A property name like "N", "FN", "ADR", etc. - */ - void propertyName(String name); - - /** - * @param type A parameter name like "ENCODING", "CHARSET", etc. - */ - void propertyParamType(String type); - - /** - * @param value A parameter value. This method may be called without - * {@link #propertyParamType(String)} being called (when the vCard is vCard 2.1). - */ - void propertyParamValue(String value); - - /** - * @param values List of property values. The size of values would be 1 unless - * coressponding property name is "N", "ADR", or "ORG". - */ - void propertyValues(List<String> values); -} diff --git a/core/java/android/pim/vcard/VCardInterpreterCollection.java b/core/java/android/pim/vcard/VCardInterpreterCollection.java deleted file mode 100644 index 4952dc7..0000000 --- a/core/java/android/pim/vcard/VCardInterpreterCollection.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import java.util.Collection; -import java.util.List; - -/** - * The {@link VCardInterpreter} implementation which aggregates more than one - * {@link VCardInterpreter} objects and make a user object treat them as one - * {@link VCardInterpreter} object. - */ -public final class VCardInterpreterCollection implements VCardInterpreter { - private final Collection<VCardInterpreter> mInterpreterCollection; - - public VCardInterpreterCollection(Collection<VCardInterpreter> interpreterCollection) { - mInterpreterCollection = interpreterCollection; - } - - public Collection<VCardInterpreter> getCollection() { - return mInterpreterCollection; - } - - public void start() { - for (VCardInterpreter builder : mInterpreterCollection) { - builder.start(); - } - } - - public void end() { - for (VCardInterpreter builder : mInterpreterCollection) { - builder.end(); - } - } - - public void startEntry() { - for (VCardInterpreter builder : mInterpreterCollection) { - builder.startEntry(); - } - } - - public void endEntry() { - for (VCardInterpreter builder : mInterpreterCollection) { - builder.endEntry(); - } - } - - public void startProperty() { - for (VCardInterpreter builder : mInterpreterCollection) { - builder.startProperty(); - } - } - - public void endProperty() { - for (VCardInterpreter builder : mInterpreterCollection) { - builder.endProperty(); - } - } - - public void propertyGroup(String group) { - for (VCardInterpreter builder : mInterpreterCollection) { - builder.propertyGroup(group); - } - } - - public void propertyName(String name) { - for (VCardInterpreter builder : mInterpreterCollection) { - builder.propertyName(name); - } - } - - public void propertyParamType(String type) { - for (VCardInterpreter builder : mInterpreterCollection) { - builder.propertyParamType(type); - } - } - - public void propertyParamValue(String value) { - for (VCardInterpreter builder : mInterpreterCollection) { - builder.propertyParamValue(value); - } - } - - public void propertyValues(List<String> values) { - for (VCardInterpreter builder : mInterpreterCollection) { - builder.propertyValues(values); - } - } -} diff --git a/core/java/android/pim/vcard/VCardParser.java b/core/java/android/pim/vcard/VCardParser.java deleted file mode 100644 index 31b9369..0000000 --- a/core/java/android/pim/vcard/VCardParser.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import android.pim.vcard.exception.VCardException; - -import java.io.IOException; -import java.io.InputStream; - -public interface VCardParser { - /** - * <p> - * Parses the given stream and send the vCard data into VCardBuilderBase object. - * </p>. - * <p> - * Note that vCard 2.1 specification allows "CHARSET" parameter, and some career sets - * local encoding to it. For example, Japanese phone career uses Shift_JIS, which is - * formally allowed in vCard 2.1, but not allowed in vCard 3.0. In vCard 2.1, - * In some exreme case, it is allowed for vCard to have different charsets in one vCard. - * </p> - * <p> - * We recommend you use {@link VCardSourceDetector} and detect which kind of source the - * vCard comes from and explicitly specify a charset using the result. - * </p> - * - * @param is The source to parse. - * @param interepreter A {@link VCardInterpreter} object which used to construct data. - * @throws IOException, VCardException - */ - public void parse(InputStream is, VCardInterpreter interepreter) - throws IOException, VCardException; - - /** - * <p> - * Cancel parsing vCard. Useful when you want to stop the parse in the other threads. - * </p> - * <p> - * Actual cancel is done after parsing the current vcard. - * </p> - */ - public abstract void cancel(); -} diff --git a/core/java/android/pim/vcard/VCardParserImpl_V21.java b/core/java/android/pim/vcard/VCardParserImpl_V21.java deleted file mode 100644 index 7d294cc..0000000 --- a/core/java/android/pim/vcard/VCardParserImpl_V21.java +++ /dev/null @@ -1,967 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import android.pim.vcard.exception.VCardAgentNotSupportedException; -import android.pim.vcard.exception.VCardException; -import android.pim.vcard.exception.VCardInvalidCommentLineException; -import android.pim.vcard.exception.VCardInvalidLineException; -import android.pim.vcard.exception.VCardNestedException; -import android.pim.vcard.exception.VCardVersionException; -import android.text.TextUtils; -import android.util.Log; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; - -/** - * <p> - * Basic implementation achieving vCard parsing. Based on vCard 2.1, - * </p> - * @hide - */ -/* package */ class VCardParserImpl_V21 { - private static final String LOG_TAG = "VCardParserImpl_V21"; - - private static final class CustomBufferedReader extends BufferedReader { - private long mTime; - - public CustomBufferedReader(Reader in) { - super(in); - } - - @Override - public String readLine() throws IOException { - long start = System.currentTimeMillis(); - String ret = super.readLine(); - long end = System.currentTimeMillis(); - mTime += end - start; - return ret; - } - - public long getTotalmillisecond() { - return mTime; - } - } - - private static final String sDefaultEncoding = "8BIT"; - - protected boolean mCanceled; - protected VCardInterpreter mInterpreter; - - protected final String mImportCharset; - - /** - * <p> - * The encoding type for deconding byte streams. This member variable is - * reset to a default encoding every time when a new item comes. - * </p> - * <p> - * "Encoding" in vCard is different from "Charset". It is mainly used for - * addresses, notes, images. "7BIT", "8BIT", "BASE64", and - * "QUOTED-PRINTABLE" are known examples. - * </p> - */ - protected String mCurrentEncoding; - - /** - * <p> - * The reader object to be used internally. - * </p> - * <p> - * Developers should not directly read a line from this object. Use - * getLine() unless there some reason. - * </p> - */ - protected BufferedReader mReader; - - /** - * <p> - * Set for storing unkonwn TYPE attributes, which is not acceptable in vCard - * specification, but happens to be seen in real world vCard. - * </p> - */ - protected final Set<String> mUnknownTypeSet = new HashSet<String>(); - - /** - * <p> - * Set for storing unkonwn VALUE attributes, which is not acceptable in - * vCard specification, but happens to be seen in real world vCard. - * </p> - */ - protected final Set<String> mUnknownValueSet = new HashSet<String>(); - - - // In some cases, vCard is nested. Currently, we only consider the most - // interior vCard data. - // See v21_foma_1.vcf in test directory for more information. - // TODO: Don't ignore by using count, but read all of information outside vCard. - private int mNestCount; - - // Used only for parsing END:VCARD. - private String mPreviousLine; - - // For measuring performance. - private long mTimeTotal; - private long mTimeReadStartRecord; - private long mTimeReadEndRecord; - private long mTimeStartProperty; - private long mTimeEndProperty; - private long mTimeParseItems; - private long mTimeParseLineAndHandleGroup; - private long mTimeParsePropertyValues; - private long mTimeParseAdrOrgN; - private long mTimeHandleMiscPropertyValue; - private long mTimeHandleQuotedPrintable; - private long mTimeHandleBase64; - - public VCardParserImpl_V21() { - this(VCardConfig.VCARD_TYPE_DEFAULT, null); - } - - public VCardParserImpl_V21(int vcardType) { - this(vcardType, null); - } - - public VCardParserImpl_V21(int vcardType, String importCharset) { - if ((vcardType & VCardConfig.FLAG_TORELATE_NEST) != 0) { - mNestCount = 1; - } - - mImportCharset = (!TextUtils.isEmpty(importCharset) ? importCharset : - VCardConfig.DEFAULT_INTERMEDIATE_CHARSET); - } - - /** - * <p> - * Parses the file at the given position. - * </p> - */ - // <pre class="prettyprint">vcard_file = [wsls] vcard [wsls]</pre> - protected void parseVCardFile() throws IOException, VCardException { - boolean readingFirstFile = true; - while (true) { - if (mCanceled) { - break; - } - if (!parseOneVCard(readingFirstFile)) { - break; - } - readingFirstFile = false; - } - - if (mNestCount > 0) { - boolean useCache = true; - for (int i = 0; i < mNestCount; i++) { - readEndVCard(useCache, true); - useCache = false; - } - } - } - - /** - * @return true when a given property name is a valid property name. - */ - protected boolean isValidPropertyName(final String propertyName) { - if (!(getKnownPropertyNameSet().contains(propertyName.toUpperCase()) || - propertyName.startsWith("X-")) - && !mUnknownTypeSet.contains(propertyName)) { - mUnknownTypeSet.add(propertyName); - Log.w(LOG_TAG, "Property name unsupported by vCard 2.1: " + propertyName); - } - return true; - } - - /** - * @return String. It may be null, or its length may be 0 - * @throws IOException - */ - protected String getLine() throws IOException { - return mReader.readLine(); - } - - /** - * @return String with it's length > 0 - * @throws IOException - * @throws VCardException when the stream reached end of line - */ - protected String getNonEmptyLine() throws IOException, VCardException { - String line; - while (true) { - line = getLine(); - if (line == null) { - throw new VCardException("Reached end of buffer."); - } else if (line.trim().length() > 0) { - return line; - } - } - } - - /* - * vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF - * items *CRLF - * "END" [ws] ":" [ws] "VCARD" - */ - private boolean parseOneVCard(boolean firstRead) throws IOException, VCardException { - boolean allowGarbage = false; - if (firstRead) { - if (mNestCount > 0) { - for (int i = 0; i < mNestCount; i++) { - if (!readBeginVCard(allowGarbage)) { - return false; - } - allowGarbage = true; - } - } - } - - if (!readBeginVCard(allowGarbage)) { - return false; - } - long start; - if (mInterpreter != null) { - start = System.currentTimeMillis(); - mInterpreter.startEntry(); - mTimeReadStartRecord += System.currentTimeMillis() - start; - } - start = System.currentTimeMillis(); - parseItems(); - mTimeParseItems += System.currentTimeMillis() - start; - readEndVCard(true, false); - if (mInterpreter != null) { - start = System.currentTimeMillis(); - mInterpreter.endEntry(); - mTimeReadEndRecord += System.currentTimeMillis() - start; - } - return true; - } - - /** - * @return True when successful. False when reaching the end of line - * @throws IOException - * @throws VCardException - */ - protected boolean readBeginVCard(boolean allowGarbage) throws IOException, VCardException { - String line; - do { - while (true) { - line = getLine(); - if (line == null) { - return false; - } else if (line.trim().length() > 0) { - break; - } - } - String[] strArray = line.split(":", 2); - int length = strArray.length; - - // Though vCard 2.1/3.0 specification does not allow lower cases, - // vCard file emitted by some external vCard expoter have such - // invalid Strings. - // So we allow it. - // e.g. BEGIN:vCard - if (length == 2 && strArray[0].trim().equalsIgnoreCase("BEGIN") - && strArray[1].trim().equalsIgnoreCase("VCARD")) { - return true; - } else if (!allowGarbage) { - if (mNestCount > 0) { - mPreviousLine = line; - return false; - } else { - throw new VCardException("Expected String \"BEGIN:VCARD\" did not come " - + "(Instead, \"" + line + "\" came)"); - } - } - } while (allowGarbage); - - throw new VCardException("Reached where must not be reached."); - } - - /** - * <p> - * The arguments useCache and allowGarbase are usually true and false - * accordingly when this function is called outside this function itself. - * </p> - * - * @param useCache When true, line is obtained from mPreviousline. - * Otherwise, getLine() is used. - * @param allowGarbage When true, ignore non "END:VCARD" line. - * @throws IOException - * @throws VCardException - */ - protected void readEndVCard(boolean useCache, boolean allowGarbage) throws IOException, - VCardException { - String line; - do { - if (useCache) { - // Though vCard specification does not allow lower cases, - // some data may have them, so we allow it. - line = mPreviousLine; - } else { - while (true) { - line = getLine(); - if (line == null) { - throw new VCardException("Expected END:VCARD was not found."); - } else if (line.trim().length() > 0) { - break; - } - } - } - - String[] strArray = line.split(":", 2); - if (strArray.length == 2 && strArray[0].trim().equalsIgnoreCase("END") - && strArray[1].trim().equalsIgnoreCase("VCARD")) { - return; - } else if (!allowGarbage) { - throw new VCardException("END:VCARD != \"" + mPreviousLine + "\""); - } - useCache = false; - } while (allowGarbage); - } - - /* - * items = *CRLF item / item - */ - protected void parseItems() throws IOException, VCardException { - boolean ended = false; - - if (mInterpreter != null) { - long start = System.currentTimeMillis(); - mInterpreter.startProperty(); - mTimeStartProperty += System.currentTimeMillis() - start; - } - ended = parseItem(); - if (mInterpreter != null && !ended) { - long start = System.currentTimeMillis(); - mInterpreter.endProperty(); - mTimeEndProperty += System.currentTimeMillis() - start; - } - - while (!ended) { - // follow VCARD ,it wont reach endProperty - if (mInterpreter != null) { - long start = System.currentTimeMillis(); - mInterpreter.startProperty(); - mTimeStartProperty += System.currentTimeMillis() - start; - } - try { - ended = parseItem(); - } catch (VCardInvalidCommentLineException e) { - Log.e(LOG_TAG, "Invalid line which looks like some comment was found. Ignored."); - ended = false; - } - if (mInterpreter != null && !ended) { - long start = System.currentTimeMillis(); - mInterpreter.endProperty(); - mTimeEndProperty += System.currentTimeMillis() - start; - } - } - } - - /* - * item = [groups "."] name [params] ":" value CRLF / [groups "."] "ADR" - * [params] ":" addressparts CRLF / [groups "."] "ORG" [params] ":" orgparts - * CRLF / [groups "."] "N" [params] ":" nameparts CRLF / [groups "."] - * "AGENT" [params] ":" vcard CRLF - */ - protected boolean parseItem() throws IOException, VCardException { - mCurrentEncoding = sDefaultEncoding; - - final String line = getNonEmptyLine(); - long start = System.currentTimeMillis(); - - String[] propertyNameAndValue = separateLineAndHandleGroup(line); - if (propertyNameAndValue == null) { - return true; - } - if (propertyNameAndValue.length != 2) { - throw new VCardInvalidLineException("Invalid line \"" + line + "\""); - } - String propertyName = propertyNameAndValue[0].toUpperCase(); - String propertyValue = propertyNameAndValue[1]; - - mTimeParseLineAndHandleGroup += System.currentTimeMillis() - start; - - if (propertyName.equals("ADR") || propertyName.equals("ORG") || propertyName.equals("N")) { - start = System.currentTimeMillis(); - handleMultiplePropertyValue(propertyName, propertyValue); - mTimeParseAdrOrgN += System.currentTimeMillis() - start; - return false; - } else if (propertyName.equals("AGENT")) { - handleAgent(propertyValue); - return false; - } else if (isValidPropertyName(propertyName)) { - if (propertyName.equals("BEGIN")) { - if (propertyValue.equals("VCARD")) { - throw new VCardNestedException("This vCard has nested vCard data in it."); - } else { - throw new VCardException("Unknown BEGIN type: " + propertyValue); - } - } else if (propertyName.equals("VERSION") && !propertyValue.equals(getVersionString())) { - throw new VCardVersionException("Incompatible version: " + propertyValue + " != " - + getVersionString()); - } - start = System.currentTimeMillis(); - handlePropertyValue(propertyName, propertyValue); - mTimeParsePropertyValues += System.currentTimeMillis() - start; - return false; - } - - throw new VCardException("Unknown property name: \"" + propertyName + "\""); - } - - // For performance reason, the states for group and property name are merged into one. - static private final int STATE_GROUP_OR_PROPERTY_NAME = 0; - static private final int STATE_PARAMS = 1; - // vCard 3.0 specification allows double-quoted parameters, while vCard 2.1 does not. - static private final int STATE_PARAMS_IN_DQUOTE = 2; - - protected String[] separateLineAndHandleGroup(String line) throws VCardException { - final String[] propertyNameAndValue = new String[2]; - final int length = line.length(); - if (length > 0 && line.charAt(0) == '#') { - throw new VCardInvalidCommentLineException(); - } - - int state = STATE_GROUP_OR_PROPERTY_NAME; - int nameIndex = 0; - - // This loop is developed so that we don't have to take care of bottle neck here. - // Refactor carefully when you need to do so. - for (int i = 0; i < length; i++) { - final char ch = line.charAt(i); - switch (state) { - case STATE_GROUP_OR_PROPERTY_NAME: { - if (ch == ':') { // End of a property name. - final String propertyName = line.substring(nameIndex, i); - if (propertyName.equalsIgnoreCase("END")) { - mPreviousLine = line; - return null; - } - if (mInterpreter != null) { - mInterpreter.propertyName(propertyName); - } - propertyNameAndValue[0] = propertyName; - if (i < length - 1) { - propertyNameAndValue[1] = line.substring(i + 1); - } else { - propertyNameAndValue[1] = ""; - } - return propertyNameAndValue; - } else if (ch == '.') { // Each group is followed by the dot. - final String groupName = line.substring(nameIndex, i); - if (groupName.length() == 0) { - Log.w(LOG_TAG, "Empty group found. Ignoring."); - } else if (mInterpreter != null) { - mInterpreter.propertyGroup(groupName); - } - nameIndex = i + 1; // Next should be another group or a property name. - } else if (ch == ';') { // End of property name and beginneng of parameters. - final String propertyName = line.substring(nameIndex, i); - if (propertyName.equalsIgnoreCase("END")) { - mPreviousLine = line; - return null; - } - if (mInterpreter != null) { - mInterpreter.propertyName(propertyName); - } - propertyNameAndValue[0] = propertyName; - nameIndex = i + 1; - state = STATE_PARAMS; // Start parameter parsing. - } - break; - } - case STATE_PARAMS: { - if (ch == '"') { - if (VCardConstants.VERSION_V21.equalsIgnoreCase(getVersionString())) { - Log.w(LOG_TAG, "Double-quoted params found in vCard 2.1. " + - "Silently allow it"); - } - state = STATE_PARAMS_IN_DQUOTE; - } else if (ch == ';') { // Starts another param. - handleParams(line.substring(nameIndex, i)); - nameIndex = i + 1; - } else if (ch == ':') { // End of param and beginenning of values. - handleParams(line.substring(nameIndex, i)); - if (i < length - 1) { - propertyNameAndValue[1] = line.substring(i + 1); - } else { - propertyNameAndValue[1] = ""; - } - return propertyNameAndValue; - } - break; - } - case STATE_PARAMS_IN_DQUOTE: { - if (ch == '"') { - if (VCardConstants.VERSION_V21.equalsIgnoreCase(getVersionString())) { - Log.w(LOG_TAG, "Double-quoted params found in vCard 2.1. " + - "Silently allow it"); - } - state = STATE_PARAMS; - } - break; - } - } - } - - throw new VCardInvalidLineException("Invalid line: \"" + line + "\""); - } - - /* - * params = ";" [ws] paramlist paramlist = paramlist [ws] ";" [ws] param / - * param param = "TYPE" [ws] "=" [ws] ptypeval / "VALUE" [ws] "=" [ws] - * pvalueval / "ENCODING" [ws] "=" [ws] pencodingval / "CHARSET" [ws] "=" - * [ws] charsetval / "LANGUAGE" [ws] "=" [ws] langval / "X-" word [ws] "=" - * [ws] word / knowntype - */ - protected void handleParams(String params) throws VCardException { - final String[] strArray = params.split("=", 2); - if (strArray.length == 2) { - final String paramName = strArray[0].trim().toUpperCase(); - String paramValue = strArray[1].trim(); - if (paramName.equals("TYPE")) { - handleType(paramValue); - } else if (paramName.equals("VALUE")) { - handleValue(paramValue); - } else if (paramName.equals("ENCODING")) { - handleEncoding(paramValue); - } else if (paramName.equals("CHARSET")) { - handleCharset(paramValue); - } else if (paramName.equals("LANGUAGE")) { - handleLanguage(paramValue); - } else if (paramName.startsWith("X-")) { - handleAnyParam(paramName, paramValue); - } else { - throw new VCardException("Unknown type \"" + paramName + "\""); - } - } else { - handleParamWithoutName(strArray[0]); - } - } - - /** - * vCard 3.0 parser implementation may throw VCardException. - */ - @SuppressWarnings("unused") - protected void handleParamWithoutName(final String paramValue) throws VCardException { - handleType(paramValue); - } - - /* - * ptypeval = knowntype / "X-" word - */ - protected void handleType(final String ptypeval) { - if (!(getKnownTypeSet().contains(ptypeval.toUpperCase()) - || ptypeval.startsWith("X-")) - && !mUnknownTypeSet.contains(ptypeval)) { - mUnknownTypeSet.add(ptypeval); - Log.w(LOG_TAG, String.format("TYPE unsupported by %s: ", getVersion(), ptypeval)); - } - if (mInterpreter != null) { - mInterpreter.propertyParamType("TYPE"); - mInterpreter.propertyParamValue(ptypeval); - } - } - - /* - * pvalueval = "INLINE" / "URL" / "CONTENT-ID" / "CID" / "X-" word - */ - protected void handleValue(final String pvalueval) { - if (!(getKnownValueSet().contains(pvalueval.toUpperCase()) - || pvalueval.startsWith("X-") - || mUnknownValueSet.contains(pvalueval))) { - mUnknownValueSet.add(pvalueval); - Log.w(LOG_TAG, String.format( - "The value unsupported by TYPE of %s: ", getVersion(), pvalueval)); - } - if (mInterpreter != null) { - mInterpreter.propertyParamType("VALUE"); - mInterpreter.propertyParamValue(pvalueval); - } - } - - /* - * pencodingval = "7BIT" / "8BIT" / "QUOTED-PRINTABLE" / "BASE64" / "X-" word - */ - protected void handleEncoding(String pencodingval) throws VCardException { - if (getAvailableEncodingSet().contains(pencodingval) || - pencodingval.startsWith("X-")) { - if (mInterpreter != null) { - mInterpreter.propertyParamType("ENCODING"); - mInterpreter.propertyParamValue(pencodingval); - } - mCurrentEncoding = pencodingval; - } else { - throw new VCardException("Unknown encoding \"" + pencodingval + "\""); - } - } - - /** - * <p> - * vCard 2.1 specification only allows us-ascii and iso-8859-xxx (See RFC 1521), - * but recent vCard files often contain other charset like UTF-8, SHIFT_JIS, etc. - * We allow any charset. - * </p> - */ - protected void handleCharset(String charsetval) { - if (mInterpreter != null) { - mInterpreter.propertyParamType("CHARSET"); - mInterpreter.propertyParamValue(charsetval); - } - } - - /** - * See also Section 7.1 of RFC 1521 - */ - protected void handleLanguage(String langval) throws VCardException { - String[] strArray = langval.split("-"); - if (strArray.length != 2) { - throw new VCardException("Invalid Language: \"" + langval + "\""); - } - String tmp = strArray[0]; - int length = tmp.length(); - for (int i = 0; i < length; i++) { - if (!isAsciiLetter(tmp.charAt(i))) { - throw new VCardException("Invalid Language: \"" + langval + "\""); - } - } - tmp = strArray[1]; - length = tmp.length(); - for (int i = 0; i < length; i++) { - if (!isAsciiLetter(tmp.charAt(i))) { - throw new VCardException("Invalid Language: \"" + langval + "\""); - } - } - if (mInterpreter != null) { - mInterpreter.propertyParamType("LANGUAGE"); - mInterpreter.propertyParamValue(langval); - } - } - - private boolean isAsciiLetter(char ch) { - if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { - return true; - } - return false; - } - - /** - * Mainly for "X-" type. This accepts any kind of type without check. - */ - protected void handleAnyParam(String paramName, String paramValue) { - if (mInterpreter != null) { - mInterpreter.propertyParamType(paramName); - mInterpreter.propertyParamValue(paramValue); - } - } - - protected void handlePropertyValue(String propertyName, String propertyValue) - throws IOException, VCardException { - final String upperEncoding = mCurrentEncoding.toUpperCase(); - if (upperEncoding.equals(VCardConstants.PARAM_ENCODING_QP)) { - final long start = System.currentTimeMillis(); - final String result = getQuotedPrintable(propertyValue); - if (mInterpreter != null) { - ArrayList<String> v = new ArrayList<String>(); - v.add(result); - mInterpreter.propertyValues(v); - } - mTimeHandleQuotedPrintable += System.currentTimeMillis() - start; - } else if (upperEncoding.equals(VCardConstants.PARAM_ENCODING_BASE64) - || upperEncoding.equals(VCardConstants.PARAM_ENCODING_B)) { - final long start = System.currentTimeMillis(); - // It is very rare, but some BASE64 data may be so big that - // OutOfMemoryError occurs. To ignore such cases, use try-catch. - try { - final String result = getBase64(propertyValue); - if (mInterpreter != null) { - ArrayList<String> arrayList = new ArrayList<String>(); - arrayList.add(result); - mInterpreter.propertyValues(arrayList); - } - } catch (OutOfMemoryError error) { - Log.e(LOG_TAG, "OutOfMemoryError happened during parsing BASE64 data!"); - if (mInterpreter != null) { - mInterpreter.propertyValues(null); - } - } - mTimeHandleBase64 += System.currentTimeMillis() - start; - } else { - if (!(upperEncoding.equals("7BIT") || upperEncoding.equals("8BIT") || - upperEncoding.startsWith("X-"))) { - Log.w(LOG_TAG, - String.format("The encoding \"%s\" is unsupported by vCard %s", - mCurrentEncoding, getVersionString())); - } - - final long start = System.currentTimeMillis(); - if (mInterpreter != null) { - ArrayList<String> v = new ArrayList<String>(); - v.add(maybeUnescapeText(propertyValue)); - mInterpreter.propertyValues(v); - } - mTimeHandleMiscPropertyValue += System.currentTimeMillis() - start; - } - } - - /** - * <p> - * Parses and returns Quoted-Printable. - * </p> - * - * @param firstString The string following a parameter name and attributes. - * Example: "string" in - * "ADR:ENCODING=QUOTED-PRINTABLE:string\n\r". - * @return whole Quoted-Printable string, including a given argument and - * following lines. Excludes the last empty line following to Quoted - * Printable lines. - * @throws IOException - * @throws VCardException - */ - private String getQuotedPrintable(String firstString) throws IOException, VCardException { - // Specifically, there may be some padding between = and CRLF. - // See the following: - // - // qp-line := *(qp-segment transport-padding CRLF) - // qp-part transport-padding - // qp-segment := qp-section *(SPACE / TAB) "=" - // ; Maximum length of 76 characters - // - // e.g. (from RFC 2045) - // Now's the time = - // for all folk to come= - // to the aid of their country. - if (firstString.trim().endsWith("=")) { - // remove "transport-padding" - int pos = firstString.length() - 1; - while (firstString.charAt(pos) != '=') { - } - StringBuilder builder = new StringBuilder(); - builder.append(firstString.substring(0, pos + 1)); - builder.append("\r\n"); - String line; - while (true) { - line = getLine(); - if (line == null) { - throw new VCardException("File ended during parsing a Quoted-Printable String"); - } - if (line.trim().endsWith("=")) { - // remove "transport-padding" - pos = line.length() - 1; - while (line.charAt(pos) != '=') { - } - builder.append(line.substring(0, pos + 1)); - builder.append("\r\n"); - } else { - builder.append(line); - break; - } - } - return builder.toString(); - } else { - return firstString; - } - } - - protected String getBase64(String firstString) throws IOException, VCardException { - StringBuilder builder = new StringBuilder(); - builder.append(firstString); - - while (true) { - String line = getLine(); - if (line == null) { - throw new VCardException("File ended during parsing BASE64 binary"); - } - if (line.length() == 0) { - break; - } - builder.append(line); - } - - return builder.toString(); - } - - /** - * <p> - * Mainly for "ADR", "ORG", and "N" - * </p> - */ - /* - * addressparts = 0*6(strnosemi ";") strnosemi ; PO Box, Extended Addr, - * Street, Locality, Region, Postal Code, Country Name orgparts = - * *(strnosemi ";") strnosemi ; First is Organization Name, remainder are - * Organization Units. nameparts = 0*4(strnosemi ";") strnosemi ; Family, - * Given, Middle, Prefix, Suffix. ; Example:Public;John;Q.;Reverend Dr.;III, - * Esq. strnosemi = *(*nonsemi ("\;" / "\" CRLF)) *nonsemi ; To include a - * semicolon in this string, it must be escaped ; with a "\" character. We - * do not care the number of "strnosemi" here. We are not sure whether we - * should add "\" CRLF to each value. We exclude them for now. - */ - protected void handleMultiplePropertyValue(String propertyName, String propertyValue) - throws IOException, VCardException { - // vCard 2.1 does not allow QUOTED-PRINTABLE here, but some - // softwares/devices - // emit such data. - if (mCurrentEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) { - propertyValue = getQuotedPrintable(propertyValue); - } - - if (mInterpreter != null) { - mInterpreter.propertyValues(VCardUtils.constructListFromValue(propertyValue, - (getVersion() == VCardConfig.FLAG_V30))); - } - } - - /* - * vCard 2.1 specifies AGENT allows one vcard entry. Currently we emit an - * error toward the AGENT property. - * // TODO: Support AGENT property. - * item = - * ... / [groups "."] "AGENT" [params] ":" vcard CRLF vcard = "BEGIN" [ws] - * ":" [ws] "VCARD" [ws] 1*CRLF items *CRLF "END" [ws] ":" [ws] "VCARD" - */ - protected void handleAgent(final String propertyValue) throws VCardException { - if (!propertyValue.toUpperCase().contains("BEGIN:VCARD")) { - // Apparently invalid line seen in Windows Mobile 6.5. Ignore them. - return; - } else { - throw new VCardAgentNotSupportedException("AGENT Property is not supported now."); - } - } - - /** - * For vCard 3.0. - */ - protected String maybeUnescapeText(final String text) { - return text; - } - - /** - * Returns unescaped String if the character should be unescaped. Return - * null otherwise. e.g. In vCard 2.1, "\;" should be unescaped into ";" - * while "\x" should not be. - */ - protected String maybeUnescapeCharacter(final char ch) { - return unescapeCharacter(ch); - } - - /* package */ static String unescapeCharacter(final char ch) { - // Original vCard 2.1 specification does not allow transformation - // "\:" -> ":", "\," -> ",", and "\\" -> "\", but previous - // implementation of - // this class allowed them, so keep it as is. - if (ch == '\\' || ch == ';' || ch == ':' || ch == ',') { - return String.valueOf(ch); - } else { - return null; - } - } - - private void showPerformanceInfo() { - Log.d(LOG_TAG, "Total parsing time: " + mTimeTotal + " ms"); - if (mReader instanceof CustomBufferedReader) { - Log.d(LOG_TAG, "Total readLine time: " - + ((CustomBufferedReader) mReader).getTotalmillisecond() + " ms"); - } - Log.d(LOG_TAG, "Time for handling the beggining of the record: " + mTimeReadStartRecord - + " ms"); - Log.d(LOG_TAG, "Time for handling the end of the record: " + mTimeReadEndRecord + " ms"); - Log.d(LOG_TAG, "Time for parsing line, and handling group: " + mTimeParseLineAndHandleGroup - + " ms"); - Log.d(LOG_TAG, "Time for parsing ADR, ORG, and N fields:" + mTimeParseAdrOrgN + " ms"); - Log.d(LOG_TAG, "Time for parsing property values: " + mTimeParsePropertyValues + " ms"); - Log.d(LOG_TAG, "Time for handling normal property values: " + mTimeHandleMiscPropertyValue - + " ms"); - Log.d(LOG_TAG, "Time for handling Quoted-Printable: " + mTimeHandleQuotedPrintable + " ms"); - Log.d(LOG_TAG, "Time for handling Base64: " + mTimeHandleBase64 + " ms"); - } - - /** - * @return {@link VCardConfig#FLAG_V21} - */ - protected int getVersion() { - return VCardConfig.FLAG_V21; - } - - /** - * @return {@link VCardConfig#FLAG_V30} - */ - protected String getVersionString() { - return VCardConstants.VERSION_V21; - } - - protected Set<String> getKnownPropertyNameSet() { - return VCardParser_V21.sKnownPropertyNameSet; - } - - protected Set<String> getKnownTypeSet() { - return VCardParser_V21.sKnownTypeSet; - } - - protected Set<String> getKnownValueSet() { - return VCardParser_V21.sKnownValueSet; - } - - protected Set<String> getAvailableEncodingSet() { - return VCardParser_V21.sAvailableEncoding; - } - - protected String getDefaultEncoding() { - return sDefaultEncoding; - } - - - public void parse(InputStream is, VCardInterpreter interpreter) - throws IOException, VCardException { - if (is == null) { - throw new NullPointerException("InputStream must not be null."); - } - - final InputStreamReader tmpReader = new InputStreamReader(is, mImportCharset); - if (VCardConfig.showPerformanceLog()) { - mReader = new CustomBufferedReader(tmpReader); - } else { - mReader = new BufferedReader(tmpReader); - } - - mInterpreter = interpreter; - - final long start = System.currentTimeMillis(); - if (mInterpreter != null) { - mInterpreter.start(); - } - parseVCardFile(); - if (mInterpreter != null) { - mInterpreter.end(); - } - mTimeTotal += System.currentTimeMillis() - start; - - if (VCardConfig.showPerformanceLog()) { - showPerformanceInfo(); - } - } - - public final void cancel() { - mCanceled = true; - } -} diff --git a/core/java/android/pim/vcard/VCardParserImpl_V30.java b/core/java/android/pim/vcard/VCardParserImpl_V30.java deleted file mode 100644 index a48a3b4..0000000 --- a/core/java/android/pim/vcard/VCardParserImpl_V30.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import java.io.IOException; -import java.util.Set; - -import android.pim.vcard.exception.VCardException; -import android.util.Log; - -/** - * <p> - * Basic implementation achieving vCard 3.0 parsing. - * </p> - * <p> - * This class inherits vCard 2.1 implementation since technically they are similar, - * while specifically there's logical no relevance between them. - * So that developers are not confused with the inheritance, - * {@link VCardParser_V30} does not inherit {@link VCardParser_V21}, while - * {@link VCardParserImpl_V30} inherits {@link VCardParserImpl_V21}. - * </p> - * @hide - */ -/* package */ class VCardParserImpl_V30 extends VCardParserImpl_V21 { - private static final String LOG_TAG = "VCardParserImpl_V30"; - - private String mPreviousLine; - private boolean mEmittedAgentWarning = false; - - public VCardParserImpl_V30() { - super(); - } - - public VCardParserImpl_V30(int vcardType) { - super(vcardType, null); - } - - public VCardParserImpl_V30(int vcardType, String importCharset) { - super(vcardType, importCharset); - } - - @Override - protected int getVersion() { - return VCardConfig.FLAG_V30; - } - - @Override - protected String getVersionString() { - return VCardConstants.VERSION_V30; - } - - @Override - protected String getLine() throws IOException { - if (mPreviousLine != null) { - String ret = mPreviousLine; - mPreviousLine = null; - return ret; - } else { - return mReader.readLine(); - } - } - - /** - * vCard 3.0 requires that the line with space at the beginning of the line - * must be combined with previous line. - */ - @Override - protected String getNonEmptyLine() throws IOException, VCardException { - String line; - StringBuilder builder = null; - while (true) { - line = mReader.readLine(); - if (line == null) { - if (builder != null) { - return builder.toString(); - } else if (mPreviousLine != null) { - String ret = mPreviousLine; - mPreviousLine = null; - return ret; - } - throw new VCardException("Reached end of buffer."); - } else if (line.length() == 0) { - if (builder != null) { - return builder.toString(); - } else if (mPreviousLine != null) { - String ret = mPreviousLine; - mPreviousLine = null; - return ret; - } - } else if (line.charAt(0) == ' ' || line.charAt(0) == '\t') { - if (builder != null) { - // See Section 5.8.1 of RFC 2425 (MIME-DIR document). - // Following is the excerpts from it. - // - // DESCRIPTION:This is a long description that exists on a long line. - // - // Can be represented as: - // - // DESCRIPTION:This is a long description - // that exists on a long line. - // - // It could also be represented as: - // - // DESCRIPTION:This is a long descrip - // tion that exists o - // n a long line. - builder.append(line.substring(1)); - } else if (mPreviousLine != null) { - builder = new StringBuilder(); - builder.append(mPreviousLine); - mPreviousLine = null; - builder.append(line.substring(1)); - } else { - throw new VCardException("Space exists at the beginning of the line"); - } - } else { - if (mPreviousLine == null) { - mPreviousLine = line; - if (builder != null) { - return builder.toString(); - } - } else { - String ret = mPreviousLine; - mPreviousLine = line; - return ret; - } - } - } - } - - /* - * vcard = [group "."] "BEGIN" ":" "VCARD" 1 * CRLF - * 1 * (contentline) - * ;A vCard object MUST include the VERSION, FN and N types. - * [group "."] "END" ":" "VCARD" 1 * CRLF - */ - @Override - protected boolean readBeginVCard(boolean allowGarbage) throws IOException, VCardException { - // TODO: vCard 3.0 supports group. - return super.readBeginVCard(allowGarbage); - } - - @Override - protected void readEndVCard(boolean useCache, boolean allowGarbage) - throws IOException, VCardException { - // TODO: vCard 3.0 supports group. - super.readEndVCard(useCache, allowGarbage); - } - - /** - * vCard 3.0 allows iana-token as paramType, while vCard 2.1 does not. - */ - @Override - protected void handleParams(final String params) throws VCardException { - try { - super.handleParams(params); - } catch (VCardException e) { - // maybe IANA type - String[] strArray = params.split("=", 2); - if (strArray.length == 2) { - handleAnyParam(strArray[0], strArray[1]); - } else { - // Must not come here in the current implementation. - throw new VCardException( - "Unknown params value: " + params); - } - } - } - - @Override - protected void handleAnyParam(final String paramName, final String paramValue) { - super.handleAnyParam(paramName, paramValue); - } - - @Override - protected void handleParamWithoutName(final String paramValue) throws VCardException { - super.handleParamWithoutName(paramValue); - } - - /* - * vCard 3.0 defines - * - * param = param-name "=" param-value *("," param-value) - * param-name = iana-token / x-name - * param-value = ptext / quoted-string - * quoted-string = DQUOTE QSAFE-CHAR DQUOTE - */ - @Override - protected void handleType(final String ptypevalues) { - String[] ptypeArray = ptypevalues.split(","); - mInterpreter.propertyParamType("TYPE"); - for (String value : ptypeArray) { - int length = value.length(); - if (length >= 2 && value.startsWith("\"") && value.endsWith("\"")) { - mInterpreter.propertyParamValue(value.substring(1, value.length() - 1)); - } else { - mInterpreter.propertyParamValue(value); - } - } - } - - @Override - protected void handleAgent(final String propertyValue) { - // The way how vCard 3.0 supports "AGENT" is completely different from vCard 2.1. - // - // e.g. - // AGENT:BEGIN:VCARD\nFN:Joe Friday\nTEL:+1-919-555-7878\n - // TITLE:Area Administrator\, Assistant\n EMAIL\;TYPE=INTERN\n - // ET:jfriday@host.com\nEND:VCARD\n - // - // TODO: fix this. - // - // issue: - // vCard 3.0 also allows this as an example. - // - // AGENT;VALUE=uri: - // CID:JQPUBLIC.part3.960129T083020.xyzMail@host3.com - // - // This is not vCard. Should we support this? - // - // Just ignore the line for now, since we cannot know how to handle it... - if (!mEmittedAgentWarning) { - Log.w(LOG_TAG, "AGENT in vCard 3.0 is not supported yet. Ignore it"); - mEmittedAgentWarning = true; - } - } - - /** - * vCard 3.0 does not require two CRLF at the last of BASE64 data. - * It only requires that data should be MIME-encoded. - */ - @Override - protected String getBase64(final String firstString) - throws IOException, VCardException { - final StringBuilder builder = new StringBuilder(); - builder.append(firstString); - - while (true) { - final String line = getLine(); - if (line == null) { - throw new VCardException("File ended during parsing BASE64 binary"); - } - if (line.length() == 0) { - break; - } else if (!line.startsWith(" ") && !line.startsWith("\t")) { - mPreviousLine = line; - break; - } - builder.append(line); - } - - return builder.toString(); - } - - /** - * ESCAPED-CHAR = "\\" / "\;" / "\," / "\n" / "\N") - * ; \\ encodes \, \n or \N encodes newline - * ; \; encodes ;, \, encodes , - * - * Note: Apple escapes ':' into '\:' while does not escape '\' - */ - @Override - protected String maybeUnescapeText(final String text) { - return unescapeText(text); - } - - public static String unescapeText(final String text) { - StringBuilder builder = new StringBuilder(); - final int length = text.length(); - for (int i = 0; i < length; i++) { - char ch = text.charAt(i); - if (ch == '\\' && i < length - 1) { - final char next_ch = text.charAt(++i); - if (next_ch == 'n' || next_ch == 'N') { - builder.append("\n"); - } else { - builder.append(next_ch); - } - } else { - builder.append(ch); - } - } - return builder.toString(); - } - - @Override - protected String maybeUnescapeCharacter(final char ch) { - return unescapeCharacter(ch); - } - - public static String unescapeCharacter(final char ch) { - if (ch == 'n' || ch == 'N') { - return "\n"; - } else { - return String.valueOf(ch); - } - } - - @Override - protected Set<String> getKnownPropertyNameSet() { - return VCardParser_V30.sKnownPropertyNameSet; - } -} diff --git a/core/java/android/pim/vcard/VCardParser_V21.java b/core/java/android/pim/vcard/VCardParser_V21.java deleted file mode 100644 index b625695..0000000 --- a/core/java/android/pim/vcard/VCardParser_V21.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import android.pim.vcard.exception.VCardException; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * </p> - * vCard parser for vCard 2.1. See the specification for more detail about the spec itself. - * </p> - * <p> - * The spec is written in 1996, and currently various types of "vCard 2.1" exist. - * To handle real the world vCard formats appropriately and effectively, this class does not - * obey with strict vCard 2.1. - * In stead, not only vCard spec but also real world vCard is considered. - * </p> - * e.g. A lot of devices and softwares let vCard importer/exporter to use - * the PNG format to determine the type of image, while it is not allowed in - * the original specification. As of 2010, we can see even the FLV format - * (possible in Japanese mobile phones). - * </p> - */ -public final class VCardParser_V21 implements VCardParser { - /** - * A unmodifiable Set storing the property names available in the vCard 2.1 specification. - */ - /* package */ static final Set<String> sKnownPropertyNameSet = - Collections.unmodifiableSet(new HashSet<String>( - Arrays.asList("BEGIN", "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND", - "VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL", - "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER"))); - - /** - * A unmodifiable Set storing the types known in vCard 2.1. - */ - /* package */ static final Set<String> sKnownTypeSet = - Collections.unmodifiableSet(new HashSet<String>( - Arrays.asList("DOM", "INTL", "POSTAL", "PARCEL", "HOME", "WORK", - "PREF", "VOICE", "FAX", "MSG", "CELL", "PAGER", "BBS", - "MODEM", "CAR", "ISDN", "VIDEO", "AOL", "APPLELINK", - "ATTMAIL", "CIS", "EWORLD", "INTERNET", "IBMMAIL", - "MCIMAIL", "POWERSHARE", "PRODIGY", "TLX", "X400", "GIF", - "CGM", "WMF", "BMP", "MET", "PMB", "DIB", "PICT", "TIFF", - "PDF", "PS", "JPEG", "QTIME", "MPEG", "MPEG2", "AVI", - "WAVE", "AIFF", "PCM", "X509", "PGP"))); - - /** - * A unmodifiable Set storing the values for the type "VALUE", available in the vCard 2.1. - */ - /* package */ static final Set<String> sKnownValueSet = - Collections.unmodifiableSet(new HashSet<String>( - Arrays.asList("INLINE", "URL", "CONTENT-ID", "CID"))); - - /** - * <p> - * A unmodifiable Set storing the values for the type "ENCODING", available in the vCard 2.1. - * </p> - * <p> - * Though vCard 2.1 specification does not allow "B" encoding, some data may have it. - * We allow it for safety. - * </p> - */ - /* package */ static final Set<String> sAvailableEncoding = - Collections.unmodifiableSet(new HashSet<String>( - Arrays.asList(VCardConstants.PARAM_ENCODING_7BIT, - VCardConstants.PARAM_ENCODING_8BIT, - VCardConstants.PARAM_ENCODING_QP, - VCardConstants.PARAM_ENCODING_BASE64, - VCardConstants.PARAM_ENCODING_B))); - - private final VCardParserImpl_V21 mVCardParserImpl; - - public VCardParser_V21() { - mVCardParserImpl = new VCardParserImpl_V21(); - } - - public VCardParser_V21(int vcardType) { - mVCardParserImpl = new VCardParserImpl_V21(vcardType); - } - - public VCardParser_V21(int parseType, String inputCharset) { - mVCardParserImpl = new VCardParserImpl_V21(parseType, null); - } - - public void parse(InputStream is, VCardInterpreter interepreter) - throws IOException, VCardException { - mVCardParserImpl.parse(is, interepreter); - } - - public void cancel() { - mVCardParserImpl.cancel(); - } -} diff --git a/core/java/android/pim/vcard/VCardParser_V30.java b/core/java/android/pim/vcard/VCardParser_V30.java deleted file mode 100644 index 40792ab..0000000 --- a/core/java/android/pim/vcard/VCardParser_V30.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import android.pim.vcard.exception.VCardException; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * <p> - * vCard parser for vCard 3.0. See RFC 2426 for more detail. - * </p> - * <p> - * This parser allows vCard format which is not allowed in the RFC, since - * we have seen several vCard 3.0 files which don't comply with it. - * </p> - * <p> - * e.g. vCard 3.0 does not allow "CHARSET" attribute, but some actual files - * have it and they uses non UTF-8 charsets. UTF-8 is recommended in RFC 2426, - * but it is not a must. We silently allow "CHARSET". - * </p> - */ -public class VCardParser_V30 implements VCardParser { - /* package */ static final Set<String> sKnownPropertyNameSet = - Collections.unmodifiableSet(new HashSet<String>(Arrays.asList( - "BEGIN", "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND", - "VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL", - "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER", // 2.1 - "NAME", "PROFILE", "SOURCE", "NICKNAME", "CLASS", - "SORT-STRING", "CATEGORIES", "PRODID"))); // 3.0 - - /** - * <p> - * A unmodifiable Set storing the values for the type "ENCODING", available in the vCard 3.0. - * </p> - * <p> - * Though vCard 2.1 specification does not allow "7BIT" or "BASE64", we allow them for safety. - * </p> - * <p> - * "QUOTED-PRINTABLE" is not allowed in vCard 3.0 and not in this parser either, - * because the encoding ambiguates how the vCard file to be parsed. - * </p> - */ - /* package */ static final Set<String> sAcceptableEncoding = - Collections.unmodifiableSet(new HashSet<String>(Arrays.asList( - VCardConstants.PARAM_ENCODING_7BIT, - VCardConstants.PARAM_ENCODING_8BIT, - VCardConstants.PARAM_ENCODING_BASE64, - VCardConstants.PARAM_ENCODING_B))); - - private final VCardParserImpl_V30 mVCardParserImpl; - - public VCardParser_V30() { - mVCardParserImpl = new VCardParserImpl_V30(); - } - - public VCardParser_V30(int vcardType) { - mVCardParserImpl = new VCardParserImpl_V30(vcardType); - } - - public VCardParser_V30(int vcardType, String importCharset) { - mVCardParserImpl = new VCardParserImpl_V30(vcardType, importCharset); - } - - public void parse(InputStream is, VCardInterpreter interepreter) - throws IOException, VCardException { - mVCardParserImpl.parse(is, interepreter); - } - - public void cancel() { - mVCardParserImpl.cancel(); - } -} diff --git a/core/java/android/pim/vcard/VCardSourceDetector.java b/core/java/android/pim/vcard/VCardSourceDetector.java deleted file mode 100644 index 291deca..0000000 --- a/core/java/android/pim/vcard/VCardSourceDetector.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import android.text.TextUtils; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * <p> - * The class which tries to detects the source of a vCard file from its contents. - * </p> - * <p> - * The specification of vCard (including both 2.1 and 3.0) is not so strict as to - * guess its format just by reading beginning few lines (usually we can, but in - * some most pessimistic case, we cannot until at almost the end of the file). - * Also we cannot store all vCard entries in memory, while there's no specification - * how big the vCard entry would become after the parse. - * </p> - * <p> - * This class is usually used for the "first scan", in which we can understand which vCard - * version is used (and how many entries exist in a file). - * </p> - */ -public class VCardSourceDetector implements VCardInterpreter { - private static Set<String> APPLE_SIGNS = new HashSet<String>(Arrays.asList( - "X-PHONETIC-FIRST-NAME", "X-PHONETIC-MIDDLE-NAME", "X-PHONETIC-LAST-NAME", - "X-ABADR", "X-ABUID")); - - private static Set<String> JAPANESE_MOBILE_PHONE_SIGNS = new HashSet<String>(Arrays.asList( - "X-GNO", "X-GN", "X-REDUCTION")); - - private static Set<String> WINDOWS_MOBILE_PHONE_SIGNS = new HashSet<String>(Arrays.asList( - "X-MICROSOFT-ASST_TEL", "X-MICROSOFT-ASSISTANT", "X-MICROSOFT-OFFICELOC")); - - // Note: these signes appears before the signs of the other type (e.g. "X-GN"). - // In other words, Japanese FOMA mobile phones are detected as FOMA, not JAPANESE_MOBILE_PHONES. - private static Set<String> FOMA_SIGNS = new HashSet<String>(Arrays.asList( - "X-SD-VERN", "X-SD-FORMAT_VER", "X-SD-CATEGORIES", "X-SD-CLASS", "X-SD-DCREATED", - "X-SD-DESCRIPTION")); - private static String TYPE_FOMA_CHARSET_SIGN = "X-SD-CHAR_CODE"; - - - // TODO: Should replace this with types in VCardConfig - private static final int PARSE_TYPE_UNKNOWN = 0; - // For Apple's software, which does not mean this type is effective for all its products. - // We confirmed they usually use UTF-8, but not sure about vCard type. - private static final int PARSE_TYPE_APPLE = 1; - // For Japanese mobile phones, which are usually using Shift_JIS as a charset. - private static final int PARSE_TYPE_MOBILE_PHONE_JP = 2; - // For some of mobile phones released from DoCoMo, which use nested vCard. - private static final int PARSE_TYPE_DOCOMO_TORELATE_NEST = 3; - // For Japanese Windows Mobel phones. It's version is supposed to be 6.5. - private static final int PARSE_TYPE_WINDOWS_MOBILE_V65_JP = 4; - - private int mParseType = 0; // Not sure. - - // Some mobile phones (like FOMA) tells us the charset of the data. - private boolean mNeedParseSpecifiedCharset; - private String mSpecifiedCharset; - - public void start() { - } - - public void end() { - } - - public void startEntry() { - } - - public void startProperty() { - mNeedParseSpecifiedCharset = false; - } - - public void endProperty() { - } - - public void endEntry() { - } - - public void propertyGroup(String group) { - } - - public void propertyName(String name) { - if (name.equalsIgnoreCase(TYPE_FOMA_CHARSET_SIGN)) { - mParseType = PARSE_TYPE_DOCOMO_TORELATE_NEST; - // Probably Shift_JIS is used, but we should double confirm. - mNeedParseSpecifiedCharset = true; - return; - } - if (mParseType != PARSE_TYPE_UNKNOWN) { - return; - } - if (WINDOWS_MOBILE_PHONE_SIGNS.contains(name)) { - mParseType = PARSE_TYPE_WINDOWS_MOBILE_V65_JP; - } else if (FOMA_SIGNS.contains(name)) { - mParseType = PARSE_TYPE_DOCOMO_TORELATE_NEST; - } else if (JAPANESE_MOBILE_PHONE_SIGNS.contains(name)) { - mParseType = PARSE_TYPE_MOBILE_PHONE_JP; - } else if (APPLE_SIGNS.contains(name)) { - mParseType = PARSE_TYPE_APPLE; - } - } - - public void propertyParamType(String type) { - } - - public void propertyParamValue(String value) { - } - - public void propertyValues(List<String> values) { - if (mNeedParseSpecifiedCharset && values.size() > 0) { - mSpecifiedCharset = values.get(0); - } - } - - /** - * @return The available type can be used with vCard parser. You probably need to - * use {{@link #getEstimatedCharset()} to understand the charset to be used. - */ - public int getEstimatedType() { - switch (mParseType) { - case PARSE_TYPE_DOCOMO_TORELATE_NEST: - return VCardConfig.VCARD_TYPE_DOCOMO | VCardConfig.FLAG_TORELATE_NEST; - case PARSE_TYPE_MOBILE_PHONE_JP: - return VCardConfig.VCARD_TYPE_V21_JAPANESE_MOBILE; - case PARSE_TYPE_APPLE: - case PARSE_TYPE_WINDOWS_MOBILE_V65_JP: - default: - return VCardConfig.VCARD_TYPE_UNKNOWN; - } - } - - /** - * <p> - * Returns charset String guessed from the source's properties. - * This method must be called after parsing target file(s). - * </p> - * @return Charset String. Null is returned if guessing the source fails. - */ - public String getEstimatedCharset() { - if (TextUtils.isEmpty(mSpecifiedCharset)) { - return mSpecifiedCharset; - } - switch (mParseType) { - case PARSE_TYPE_WINDOWS_MOBILE_V65_JP: - case PARSE_TYPE_DOCOMO_TORELATE_NEST: - case PARSE_TYPE_MOBILE_PHONE_JP: - return "SHIFT_JIS"; - case PARSE_TYPE_APPLE: - return "UTF-8"; - default: - return null; - } - } -} diff --git a/core/java/android/pim/vcard/VCardUtils.java b/core/java/android/pim/vcard/VCardUtils.java deleted file mode 100644 index 680ef6f..0000000 --- a/core/java/android/pim/vcard/VCardUtils.java +++ /dev/null @@ -1,653 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import android.content.ContentProviderOperation; -import android.provider.ContactsContract.Data; -import android.provider.ContactsContract.CommonDataKinds.Im; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; -import android.telephony.PhoneNumberUtils; -import android.text.TextUtils; -import android.util.Log; - -import org.apache.commons.codec.DecoderException; -import org.apache.commons.codec.net.QuotedPrintableCodec; - -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Utilities for VCard handling codes. - * @hide - */ -public class VCardUtils { - private static final String LOG_TAG = "VCardUtils"; - - // Note that not all types are included in this map/set, since, for example, TYPE_HOME_FAX is - // converted to two parameter Strings. These only contain some minor fields valid in both - // vCard and current (as of 2009-08-07) Contacts structure. - private static final Map<Integer, String> sKnownPhoneTypesMap_ItoS; - private static final Set<String> sPhoneTypesUnknownToContactsSet; - private static final Map<String, Integer> sKnownPhoneTypeMap_StoI; - private static final Map<Integer, String> sKnownImPropNameMap_ItoS; - private static final Set<String> sMobilePhoneLabelSet; - - static { - sKnownPhoneTypesMap_ItoS = new HashMap<Integer, String>(); - sKnownPhoneTypeMap_StoI = new HashMap<String, Integer>(); - - sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_CAR, VCardConstants.PARAM_TYPE_CAR); - sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_CAR, Phone.TYPE_CAR); - sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_PAGER, VCardConstants.PARAM_TYPE_PAGER); - sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_PAGER, Phone.TYPE_PAGER); - sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_ISDN, VCardConstants.PARAM_TYPE_ISDN); - sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_ISDN, Phone.TYPE_ISDN); - - sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_HOME, Phone.TYPE_HOME); - sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_WORK, Phone.TYPE_WORK); - sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_CELL, Phone.TYPE_MOBILE); - - sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_OTHER, Phone.TYPE_OTHER); - sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_CALLBACK, - Phone.TYPE_CALLBACK); - sKnownPhoneTypeMap_StoI.put( - VCardConstants.PARAM_PHONE_EXTRA_TYPE_COMPANY_MAIN, Phone.TYPE_COMPANY_MAIN); - sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_RADIO, Phone.TYPE_RADIO); - sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_TTY_TDD, - Phone.TYPE_TTY_TDD); - sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_ASSISTANT, - Phone.TYPE_ASSISTANT); - - sPhoneTypesUnknownToContactsSet = new HashSet<String>(); - sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_MODEM); - sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_MSG); - sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_BBS); - sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_VIDEO); - - sKnownImPropNameMap_ItoS = new HashMap<Integer, String>(); - sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_AIM, VCardConstants.PROPERTY_X_AIM); - sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_MSN, VCardConstants.PROPERTY_X_MSN); - sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_YAHOO, VCardConstants.PROPERTY_X_YAHOO); - sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_SKYPE, VCardConstants.PROPERTY_X_SKYPE_USERNAME); - sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_GOOGLE_TALK, - VCardConstants.PROPERTY_X_GOOGLE_TALK); - sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_ICQ, VCardConstants.PROPERTY_X_ICQ); - sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_JABBER, VCardConstants.PROPERTY_X_JABBER); - sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_QQ, VCardConstants.PROPERTY_X_QQ); - sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_NETMEETING, VCardConstants.PROPERTY_X_NETMEETING); - - // \u643A\u5E2F\u96FB\u8A71 = Full-width Hiragana "Keitai-Denwa" (mobile phone) - // \u643A\u5E2F = Full-width Hiragana "Keitai" (mobile phone) - // \u30B1\u30A4\u30BF\u30A4 = Full-width Katakana "Keitai" (mobile phone) - // \uFF79\uFF72\uFF80\uFF72 = Half-width Katakana "Keitai" (mobile phone) - sMobilePhoneLabelSet = new HashSet<String>(Arrays.asList( - "MOBILE", "\u643A\u5E2F\u96FB\u8A71", "\u643A\u5E2F", "\u30B1\u30A4\u30BF\u30A4", - "\uFF79\uFF72\uFF80\uFF72")); - } - - public static String getPhoneTypeString(Integer type) { - return sKnownPhoneTypesMap_ItoS.get(type); - } - - /** - * Returns Interger when the given types can be parsed as known type. Returns String object - * when not, which should be set to label. - */ - public static Object getPhoneTypeFromStrings(Collection<String> types, - String number) { - if (number == null) { - number = ""; - } - int type = -1; - String label = null; - boolean isFax = false; - boolean hasPref = false; - - if (types != null) { - for (String typeString : types) { - if (typeString == null) { - continue; - } - typeString = typeString.toUpperCase(); - if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) { - hasPref = true; - } else if (typeString.equals(VCardConstants.PARAM_TYPE_FAX)) { - isFax = true; - } else { - if (typeString.startsWith("X-") && type < 0) { - typeString = typeString.substring(2); - } - if (typeString.length() == 0) { - continue; - } - final Integer tmp = sKnownPhoneTypeMap_StoI.get(typeString); - if (tmp != null) { - final int typeCandidate = tmp; - // TYPE_PAGER is prefered when the number contains @ surronded by - // a pager number and a domain name. - // e.g. - // o 1111@domain.com - // x @domain.com - // x 1111@ - final int indexOfAt = number.indexOf("@"); - if ((typeCandidate == Phone.TYPE_PAGER - && 0 < indexOfAt && indexOfAt < number.length() - 1) - || type < 0 - || type == Phone.TYPE_CUSTOM) { - type = tmp; - } - } else if (type < 0) { - type = Phone.TYPE_CUSTOM; - label = typeString; - } - } - } - } - if (type < 0) { - if (hasPref) { - type = Phone.TYPE_MAIN; - } else { - // default to TYPE_HOME - type = Phone.TYPE_HOME; - } - } - if (isFax) { - if (type == Phone.TYPE_HOME) { - type = Phone.TYPE_FAX_HOME; - } else if (type == Phone.TYPE_WORK) { - type = Phone.TYPE_FAX_WORK; - } else if (type == Phone.TYPE_OTHER) { - type = Phone.TYPE_OTHER_FAX; - } - } - if (type == Phone.TYPE_CUSTOM) { - return label; - } else { - return type; - } - } - - @SuppressWarnings("deprecation") - public static boolean isMobilePhoneLabel(final String label) { - // For backward compatibility. - // Detail: Until Donut, there isn't TYPE_MOBILE for email while there is now. - // To support mobile type at that time, this custom label had been used. - return (android.provider.Contacts.ContactMethodsColumns.MOBILE_EMAIL_TYPE_NAME.equals(label) - || sMobilePhoneLabelSet.contains(label)); - } - - public static boolean isValidInV21ButUnknownToContactsPhoteType(final String label) { - return sPhoneTypesUnknownToContactsSet.contains(label); - } - - public static String getPropertyNameForIm(final int protocol) { - return sKnownImPropNameMap_ItoS.get(protocol); - } - - public static String[] sortNameElements(final int vcardType, - final String familyName, final String middleName, final String givenName) { - final String[] list = new String[3]; - final int nameOrderType = VCardConfig.getNameOrderType(vcardType); - switch (nameOrderType) { - case VCardConfig.NAME_ORDER_JAPANESE: { - if (containsOnlyPrintableAscii(familyName) && - containsOnlyPrintableAscii(givenName)) { - list[0] = givenName; - list[1] = middleName; - list[2] = familyName; - } else { - list[0] = familyName; - list[1] = middleName; - list[2] = givenName; - } - break; - } - case VCardConfig.NAME_ORDER_EUROPE: { - list[0] = middleName; - list[1] = givenName; - list[2] = familyName; - break; - } - default: { - list[0] = givenName; - list[1] = middleName; - list[2] = familyName; - break; - } - } - return list; - } - - public static int getPhoneNumberFormat(final int vcardType) { - if (VCardConfig.isJapaneseDevice(vcardType)) { - return PhoneNumberUtils.FORMAT_JAPAN; - } else { - return PhoneNumberUtils.FORMAT_NANP; - } - } - - /** - * <p> - * Inserts postal data into the builder object. - * </p> - * <p> - * Note that the data structure of ContactsContract is different from that defined in vCard. - * So some conversion may be performed in this method. - * </p> - */ - public static void insertStructuredPostalDataUsingContactsStruct(int vcardType, - final ContentProviderOperation.Builder builder, - final VCardEntry.PostalData postalData) { - builder.withValueBackReference(StructuredPostal.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE); - - builder.withValue(StructuredPostal.TYPE, postalData.type); - if (postalData.type == StructuredPostal.TYPE_CUSTOM) { - builder.withValue(StructuredPostal.LABEL, postalData.label); - } - - final String streetString; - if (TextUtils.isEmpty(postalData.street)) { - if (TextUtils.isEmpty(postalData.extendedAddress)) { - streetString = null; - } else { - streetString = postalData.extendedAddress; - } - } else { - if (TextUtils.isEmpty(postalData.extendedAddress)) { - streetString = postalData.street; - } else { - streetString = postalData.street + " " + postalData.extendedAddress; - } - } - builder.withValue(StructuredPostal.POBOX, postalData.pobox); - builder.withValue(StructuredPostal.STREET, streetString); - builder.withValue(StructuredPostal.CITY, postalData.localty); - builder.withValue(StructuredPostal.REGION, postalData.region); - builder.withValue(StructuredPostal.POSTCODE, postalData.postalCode); - builder.withValue(StructuredPostal.COUNTRY, postalData.country); - - builder.withValue(StructuredPostal.FORMATTED_ADDRESS, - postalData.getFormattedAddress(vcardType)); - if (postalData.isPrimary) { - builder.withValue(Data.IS_PRIMARY, 1); - } - } - - public static String constructNameFromElements(final int vcardType, - final String familyName, final String middleName, final String givenName) { - return constructNameFromElements(vcardType, familyName, middleName, givenName, - null, null); - } - - public static String constructNameFromElements(final int vcardType, - final String familyName, final String middleName, final String givenName, - final String prefix, final String suffix) { - final StringBuilder builder = new StringBuilder(); - final String[] nameList = sortNameElements(vcardType, familyName, middleName, givenName); - boolean first = true; - if (!TextUtils.isEmpty(prefix)) { - first = false; - builder.append(prefix); - } - for (final String namePart : nameList) { - if (!TextUtils.isEmpty(namePart)) { - if (first) { - first = false; - } else { - builder.append(' '); - } - builder.append(namePart); - } - } - if (!TextUtils.isEmpty(suffix)) { - if (!first) { - builder.append(' '); - } - builder.append(suffix); - } - return builder.toString(); - } - - public static List<String> constructListFromValue(final String value, - final boolean isV30) { - final List<String> list = new ArrayList<String>(); - StringBuilder builder = new StringBuilder(); - int length = value.length(); - for (int i = 0; i < length; i++) { - char ch = value.charAt(i); - if (ch == '\\' && i < length - 1) { - char nextCh = value.charAt(i + 1); - final String unescapedString = - (isV30 ? VCardParserImpl_V30.unescapeCharacter(nextCh) : - VCardParserImpl_V21.unescapeCharacter(nextCh)); - if (unescapedString != null) { - builder.append(unescapedString); - i++; - } else { - builder.append(ch); - } - } else if (ch == ';') { - list.add(builder.toString()); - builder = new StringBuilder(); - } else { - builder.append(ch); - } - } - list.add(builder.toString()); - return list; - } - - public static boolean containsOnlyPrintableAscii(final String...values) { - if (values == null) { - return true; - } - return containsOnlyPrintableAscii(Arrays.asList(values)); - } - - public static boolean containsOnlyPrintableAscii(final Collection<String> values) { - if (values == null) { - return true; - } - for (final String value : values) { - if (TextUtils.isEmpty(value)) { - continue; - } - if (!TextUtils.isPrintableAsciiOnly(value)) { - return false; - } - } - return true; - } - - /** - * <p> - * This is useful when checking the string should be encoded into quoted-printable - * or not, which is required by vCard 2.1. - * </p> - * <p> - * See the definition of "7bit" in vCard 2.1 spec for more information. - * </p> - */ - public static boolean containsOnlyNonCrLfPrintableAscii(final String...values) { - if (values == null) { - return true; - } - return containsOnlyNonCrLfPrintableAscii(Arrays.asList(values)); - } - - public static boolean containsOnlyNonCrLfPrintableAscii(final Collection<String> values) { - if (values == null) { - return true; - } - final int asciiFirst = 0x20; - final int asciiLast = 0x7E; // included - for (final String value : values) { - if (TextUtils.isEmpty(value)) { - continue; - } - final int length = value.length(); - for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) { - final int c = value.codePointAt(i); - if (!(asciiFirst <= c && c <= asciiLast)) { - return false; - } - } - } - return true; - } - - private static final Set<Character> sUnAcceptableAsciiInV21WordSet = - new HashSet<Character>(Arrays.asList('[', ']', '=', ':', '.', ',', ' ')); - - /** - * <p> - * This is useful since vCard 3.0 often requires the ("X-") properties and groups - * should contain only alphabets, digits, and hyphen. - * </p> - * <p> - * Note: It is already known some devices (wrongly) outputs properties with characters - * which should not be in the field. One example is "X-GOOGLE TALK". We accept - * such kind of input but must never output it unless the target is very specific - * to the device which is able to parse the malformed input. - * </p> - */ - public static boolean containsOnlyAlphaDigitHyphen(final String...values) { - if (values == null) { - return true; - } - return containsOnlyAlphaDigitHyphen(Arrays.asList(values)); - } - - public static boolean containsOnlyAlphaDigitHyphen(final Collection<String> values) { - if (values == null) { - return true; - } - final int upperAlphabetFirst = 0x41; // A - final int upperAlphabetAfterLast = 0x5b; // [ - final int lowerAlphabetFirst = 0x61; // a - final int lowerAlphabetAfterLast = 0x7b; // { - final int digitFirst = 0x30; // 0 - final int digitAfterLast = 0x3A; // : - final int hyphen = '-'; - for (final String str : values) { - if (TextUtils.isEmpty(str)) { - continue; - } - final int length = str.length(); - for (int i = 0; i < length; i = str.offsetByCodePoints(i, 1)) { - int codepoint = str.codePointAt(i); - if (!((lowerAlphabetFirst <= codepoint && codepoint < lowerAlphabetAfterLast) || - (upperAlphabetFirst <= codepoint && codepoint < upperAlphabetAfterLast) || - (digitFirst <= codepoint && codepoint < digitAfterLast) || - (codepoint == hyphen))) { - return false; - } - } - } - return true; - } - - /** - * <p> - * Returns true when the given String is categorized as "word" specified in vCard spec 2.1. - * </p> - * <p> - * vCard 2.1 specifies:<br /> - * word = <any printable 7bit us-ascii except []=:., > - * </p> - */ - public static boolean isV21Word(final String value) { - if (TextUtils.isEmpty(value)) { - return true; - } - final int asciiFirst = 0x20; - final int asciiLast = 0x7E; // included - final int length = value.length(); - for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) { - final int c = value.codePointAt(i); - if (!(asciiFirst <= c && c <= asciiLast) || - sUnAcceptableAsciiInV21WordSet.contains((char)c)) { - return false; - } - } - return true; - } - - public static String toHalfWidthString(final String orgString) { - if (TextUtils.isEmpty(orgString)) { - return null; - } - final StringBuilder builder = new StringBuilder(); - final int length = orgString.length(); - for (int i = 0; i < length; i = orgString.offsetByCodePoints(i, 1)) { - // All Japanese character is able to be expressed by char. - // Do not need to use String#codepPointAt(). - final char ch = orgString.charAt(i); - final String halfWidthText = JapaneseUtils.tryGetHalfWidthText(ch); - if (halfWidthText != null) { - builder.append(halfWidthText); - } else { - builder.append(ch); - } - } - return builder.toString(); - } - - /** - * Guesses the format of input image. Currently just the first few bytes are used. - * The type "GIF", "PNG", or "JPEG" is returned when possible. Returns null when - * the guess failed. - * @param input Image as byte array. - * @return The image type or null when the type cannot be determined. - */ - public static String guessImageType(final byte[] input) { - if (input == null) { - return null; - } - if (input.length >= 3 && input[0] == 'G' && input[1] == 'I' && input[2] == 'F') { - return "GIF"; - } else if (input.length >= 4 && input[0] == (byte) 0x89 - && input[1] == 'P' && input[2] == 'N' && input[3] == 'G') { - // Note: vCard 2.1 officially does not support PNG, but we may have it and - // using X- word like "X-PNG" may not let importers know it is PNG. - // So we use the String "PNG" as is... - return "PNG"; - } else if (input.length >= 2 && input[0] == (byte) 0xff - && input[1] == (byte) 0xd8) { - return "JPEG"; - } else { - return null; - } - } - - /** - * @return True when all the given values are null or empty Strings. - */ - public static boolean areAllEmpty(final String...values) { - if (values == null) { - return true; - } - - for (final String value : values) { - if (!TextUtils.isEmpty(value)) { - return false; - } - } - return true; - } - - //// The methods bellow may be used by unit test. - - /** - * @hide - */ - public static String parseQuotedPrintable(String value, boolean strictLineBreaking, - String sourceCharset, String targetCharset) { - // "= " -> " ", "=\t" -> "\t". - // Previous code had done this replacement. Keep on the safe side. - final String quotedPrintable; - { - final StringBuilder builder = new StringBuilder(); - final int length = value.length(); - for (int i = 0; i < length; i++) { - char ch = value.charAt(i); - if (ch == '=' && i < length - 1) { - char nextCh = value.charAt(i + 1); - if (nextCh == ' ' || nextCh == '\t') { - builder.append(nextCh); - i++; - continue; - } - } - builder.append(ch); - } - quotedPrintable = builder.toString(); - } - - String[] lines; - if (strictLineBreaking) { - lines = quotedPrintable.split("\r\n"); - } else { - StringBuilder builder = new StringBuilder(); - final int length = quotedPrintable.length(); - ArrayList<String> list = new ArrayList<String>(); - for (int i = 0; i < length; i++) { - char ch = quotedPrintable.charAt(i); - if (ch == '\n') { - list.add(builder.toString()); - builder = new StringBuilder(); - } else if (ch == '\r') { - list.add(builder.toString()); - builder = new StringBuilder(); - if (i < length - 1) { - char nextCh = quotedPrintable.charAt(i + 1); - if (nextCh == '\n') { - i++; - } - } - } else { - builder.append(ch); - } - } - final String lastLine = builder.toString(); - if (lastLine.length() > 0) { - list.add(lastLine); - } - lines = list.toArray(new String[0]); - } - - final StringBuilder builder = new StringBuilder(); - for (String line : lines) { - if (line.endsWith("=")) { - line = line.substring(0, line.length() - 1); - } - builder.append(line); - } - byte[] bytes; - try { - bytes = builder.toString().getBytes(sourceCharset); - } catch (UnsupportedEncodingException e1) { - Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset); - bytes = builder.toString().getBytes(); - } - - try { - bytes = QuotedPrintableCodec.decodeQuotedPrintable(bytes); - } catch (DecoderException e) { - Log.e(LOG_TAG, "Failed to decode quoted-printable: " + e); - return ""; - } - - try { - return new String(bytes, targetCharset); - } catch (UnsupportedEncodingException e) { - Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset); - return new String(bytes); - } - } - - private VCardUtils() { - } -} diff --git a/core/java/android/pim/vcard/exception/VCardAgentNotSupportedException.java b/core/java/android/pim/vcard/exception/VCardAgentNotSupportedException.java deleted file mode 100644 index e72c7df..0000000 --- a/core/java/android/pim/vcard/exception/VCardAgentNotSupportedException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.exception; - -public class VCardAgentNotSupportedException extends VCardNotSupportedException { - public VCardAgentNotSupportedException() { - super(); - } - - public VCardAgentNotSupportedException(String message) { - super(message); - } - -}
\ No newline at end of file diff --git a/core/java/android/pim/vcard/exception/VCardException.java b/core/java/android/pim/vcard/exception/VCardException.java deleted file mode 100644 index e557219..0000000 --- a/core/java/android/pim/vcard/exception/VCardException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.exception; - -public class VCardException extends java.lang.Exception { - /** - * Constructs a VCardException object - */ - public VCardException() { - super(); - } - - /** - * Constructs a VCardException object - * - * @param message the error message - */ - public VCardException(String message) { - super(message); - } - -} diff --git a/core/java/android/pim/vcard/exception/VCardInvalidCommentLineException.java b/core/java/android/pim/vcard/exception/VCardInvalidCommentLineException.java deleted file mode 100644 index 67db62c..0000000 --- a/core/java/android/pim/vcard/exception/VCardInvalidCommentLineException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.pim.vcard.exception; - -/** - * Thrown when the vCard has some line starting with '#'. In the specification, - * both vCard 2.1 and vCard 3.0 does not allow such line, but some actual exporter emit - * such lines. - */ -public class VCardInvalidCommentLineException extends VCardInvalidLineException { - public VCardInvalidCommentLineException() { - super(); - } - - public VCardInvalidCommentLineException(final String message) { - super(message); - } -} diff --git a/core/java/android/pim/vcard/exception/VCardInvalidLineException.java b/core/java/android/pim/vcard/exception/VCardInvalidLineException.java deleted file mode 100644 index 330153e..0000000 --- a/core/java/android/pim/vcard/exception/VCardInvalidLineException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.pim.vcard.exception; - -/** - * Thrown when the vCard has some line starting with '#'. In the specification, - * both vCard 2.1 and vCard 3.0 does not allow such line, but some actual exporter emit - * such lines. - */ -public class VCardInvalidLineException extends VCardException { - public VCardInvalidLineException() { - super(); - } - - public VCardInvalidLineException(final String message) { - super(message); - } -} diff --git a/core/java/android/pim/vcard/exception/VCardNestedException.java b/core/java/android/pim/vcard/exception/VCardNestedException.java deleted file mode 100644 index 503c2fb..0000000 --- a/core/java/android/pim/vcard/exception/VCardNestedException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.pim.vcard.exception; - -/** - * VCardException thrown when VCard is nested without VCardParser's being notified. - */ -public class VCardNestedException extends VCardNotSupportedException { - public VCardNestedException() { - super(); - } - public VCardNestedException(String message) { - super(message); - } -} diff --git a/core/java/android/pim/vcard/exception/VCardNotSupportedException.java b/core/java/android/pim/vcard/exception/VCardNotSupportedException.java deleted file mode 100644 index 616aa77..0000000 --- a/core/java/android/pim/vcard/exception/VCardNotSupportedException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.exception; - -/** - * The exception which tells that the input VCard is probably valid from the view of - * specification but not supported in the current framework for now. - * - * This is a kind of a good news from the view of development. - * It may be good to ask users to send a report with the VCard example - * for the future development. - */ -public class VCardNotSupportedException extends VCardException { - public VCardNotSupportedException() { - super(); - } - public VCardNotSupportedException(String message) { - super(message); - } -}
\ No newline at end of file diff --git a/core/java/android/pim/vcard/exception/VCardVersionException.java b/core/java/android/pim/vcard/exception/VCardVersionException.java deleted file mode 100644 index 9fe8b7f..0000000 --- a/core/java/android/pim/vcard/exception/VCardVersionException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.pim.vcard.exception; - -/** - * VCardException used only when the version of the vCard is different. - */ -public class VCardVersionException extends VCardException { - public VCardVersionException() { - super(); - } - public VCardVersionException(String message) { - super(message); - } -} diff --git a/core/java/android/pim/vcard/exception/package.html b/core/java/android/pim/vcard/exception/package.html deleted file mode 100644 index 26b8a32..0000000 --- a/core/java/android/pim/vcard/exception/package.html +++ /dev/null @@ -1,5 +0,0 @@ -<HTML> -<BODY> -{@hide} -</BODY> -</HTML>
\ No newline at end of file diff --git a/core/java/android/pim/vcard/package.html b/core/java/android/pim/vcard/package.html deleted file mode 100644 index 26b8a32..0000000 --- a/core/java/android/pim/vcard/package.html +++ /dev/null @@ -1,5 +0,0 @@ -<HTML> -<BODY> -{@hide} -</BODY> -</HTML>
\ No newline at end of file diff --git a/core/tests/coretests/res/raw/v21_backslash.vcf b/core/tests/coretests/res/raw/v21_backslash.vcf deleted file mode 100644 index bd3002b..0000000 --- a/core/tests/coretests/res/raw/v21_backslash.vcf +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN:VCARD
-VERSION:2.1
-N:;A\;B\\;C\\\;;D;\:E;\\\\;
-FN:A;B\C\;D:E\\
-END:VCARD
diff --git a/core/tests/coretests/res/raw/v21_complicated.vcf b/core/tests/coretests/res/raw/v21_complicated.vcf deleted file mode 100644 index de34e16..0000000 --- a/core/tests/coretests/res/raw/v21_complicated.vcf +++ /dev/null @@ -1,106 +0,0 @@ -BEGIN:VCARD
-VERSION:2.1
-N:Gump;Forrest;Hoge;Pos;Tao
-FN:Joe Due
-ORG:Gump Shrimp Co.;Sales Dept.\;Manager;Fish keeper
-ROLE:Fish Cake Keeper!
-X-CLASS:PUBLIC
-TITLE:Shrimp Man
-TEL;WORK;VOICE:(111) 555-1212
-TEL;HOME;VOICE:(404) 555-1212
-TEL;CELL:0311111111
-TEL;VIDEO:0322222222
-TEL;VOICE:0333333333
-ADR;WORK:;;100 Waters Edge;Baytown;LA;30314;United States of America
-LABEL;WORK;ENCODING=QUOTED-PRINTABLE:100 Waters Edge=0D=0ABaytown, LA 30314=0D=0AUnited States of America
-ADR;HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America
-LABEL;HOME;ENCODING=QUOTED-PRINTABLE:42 Plantation St.=0D=0A=
-Baytown, LA 30314=0D=0A=
-United States of America
-EMAIL;PREF;INTERNET:forrestgump@walladalla.com
-EMAIL;CELL:cell@example.com
-NOTE:The following note is the example from RFC 2045.
-NOTE;ENCODING=QUOTED-PRINTABLE:Now's the time =
-for all folk to come=
- to the aid of their country.
-
-PHOTO;ENCODING=BASE64;TYPE=JPEG:
- /9j/4QoPRXhpZgAATU0AKgAAAAgADQEOAAIAAAAPAAAAqgEPAAIAAAAHAAAAugEQAAIAAAAG
- AAAAwgESAAMAAAABAAEAAAEaAAUAAAABAAAAyAEbAAUAAAABAAAA0AEoAAMAAAABAAIAAAEx
- AAIAAAAOAAAA2AEyAAIAAAAUAAAA5gITAAMAAAABAAEAAIKYAAIAAAAOAAAA+odpAAQAAAAB
- AAABhMSlAAcAAAB8AAABCAAABB4yMDA4MTAyOTEzNTUzMQAARG9Db01vAABEOTA1aQAAAABI
- AAAAAQAAAEgAAAABRDkwNWkgVmVyMS4wMAAyMDA4OjEwOjI5IDEzOjU1OjQ3ACAgICAgICAg
- ICAgICAAUHJpbnRJTQAwMzAwAAAABgABABQAFAACAQAAAAADAAAANAEABQAAAAEBAQAAAAEQ
- gAAAAAAAEQkAACcQAAAPCwAAJxAAAAWXAAAnEAAACLAAACcQAAAcAQAAJxAAAAJeAAAnEAAA
- AIsAACcQAAADywAAJxAAABvlAAAnEAAogpoABQAAAAEAAANqgp0ABQAAAAEAAANyiCIAAwAA
- AAEAAgAAkAAABwAAAAQwMjIwkAMAAgAAABQAAAN6kAQAAgAAABQAAAOOkQEABwAAAAQBAgMA
- kQIABQAAAAEAAAOikgEACgAAAAEAAAOqkgIABQAAAAEAAAOykgQACgAAAAEAAAO6kgUABQAA
- AAEAAAPCkgcAAwAAAAEAAgAAkggAAwAAAAEAAAAAkgkAAwAAAAEAAAAAkgoABQAAAAEAAAPK
- knwABwAAAAEAAAAAkoYABwAAABYAAAPSoAAABwAAAAQwMTAwoAEAAwAAAAEAAQAAoAIAAwAA
- AAEAYAAAoAMAAwAAAAEASAAAoAUABAAAAAEAAAQAog4ABQAAAAEAAAPoog8ABQAAAAEAAAPw
- ohAAAwAAAAEAAgAAohcAAwAAAAEAAgAAowAABwAAAAEDAAAAowEABwAAAAEBAAAApAEAAwAA
- AAEAAAAApAIAAwAAAAEAAAAApAMAAwAAAAEAAAAApAQABQAAAAEAAAP4pAUAAwAAAAEAHQAA
- pAYAAwAAAAEAAAAApAcAAwAAAAEAAAAApAgAAwAAAAEAAAAApAkAAwAAAAEAAAAApAoAAwAA
- AAEAAAAApAwAAwAAAAEAAgAAAAAAAAAAAFMAACcQAAABXgAAAGQyMDA4OjEwOjI5IDEzOjU1
- OjMxADIwMDg6MTA6MjkgMTM6NTU6NDcAAAApiAAAGwAAAAKyAAAAZAAAAV4AAABkAAAAAAAA
- AGQAAAAlAAAACgAADpIAAAPoAAAAAAAAAAAyMDA4MTAyOTEzNTUzMQAAICoAAAAKAAAq4gAA
- AAoAAAAAAAAAAQACAAEAAgAAAARSOTgAAAIABwAAAAQwMTAwAAAAAAAGAQMAAwAAAAEABgAA
- ARoABQAAAAEAAARsARsABQAAAAEAAAR0ASgAAwAAAAEAAgAAAgEABAAAAAEAAAR8AgIABAAA
- AAEAAAWLAAAAAAAAAEgAAAABAAAASAAAAAH/2P/bAIQAIBYYHBgUIBwaHCQiICYwUDQwLCww
- YkZKOlB0Znp4cmZwboCQuJyAiK6KbnCg2qKuvsTO0M58muLy4MjwuMrOxgEiJCQwKjBeNDRe
- xoRwhMbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbG
- /8AAEQgAeACgAwEhAAIRAQMRAf/EAaIAAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKCxAA
- AgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkK
- FhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWG
- h4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl
- 5ufo6erx8vP09fb3+Pn6AQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgsRAAIBAgQEAwQH
- BQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBka
- JicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKT
- lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz
- 9PX29/j5+v/aAAwDAQACEQMRAD8AFFSqKkZIoqRVpgSKKeBTEOApwFADsUYpgIRSEUANIppF
- ICNhUTCgCMio2FICJhULCgC0oqVaAJFFSqKBkgFOApiHCnCgB2KMUCENJQA0imEUDGMKiYUA
- RtUbUgIWqJhQBZSpFoAlWpVoGPFPFMQ7tSK2ODQA4yKO9HmKe9FxAzDHFIOlAAaYaAGNUTUD
- ImqNqQETVE1AE6VKKAJFNSqaAHg08GmANIFFQM5Y5qJMBuT60ZNQIcrkVYSQMKuLGKaaasQx
- qiagZE1RtSAjaomoAkQ1KpoAlU1IpoAkU07OBTArO+5qkV12Y71lfUBmaKkCRSuznrTFba2a
- oCwGyM0E1qIjY1GxoGRNUZNICNqiagByGplNAEimpFNMB4YDvSucpxSYEIU04KazsAu1qArU
- WELtPpTSposBNETt5pxNaoCNjUbGgCNjUZoGRtUTUgFU1KpoAkBqQHigCFnO7rUqOdlZp6gA
- c+tODn1pXAXzD60eYfWncQvmNSGQ07gOMhCVEJGz1ptgS5yKYxqwGE1GxoAiamGkMapqVTQB
- Kpp+eKAICfmqWM/Kaz6gANOBqQFzRmmAuaTNACsfkqMHmm9wJs8U0mtRDGNRsaAI2phpDI1N
- SqaAJFNSA8UCISfmqSM/Kaz6jAHmnA1ICg0uaAFzSZpgKx+SmDrTe4E2eKaTWoiMmmMaAIzT
- DSGRKakU0ASKaeDTERseakjPyms+oxAacDUgOBpc0gFzSZpgOY/KKYv3qrqIlpprQBjGoyaA
- GGmmkMgU1IppgPBqQGgQu0Gn4wvFKwEQpwNZDHZpc0ALmigRKBleaQKBWtgA001QDGqM0gGm
- mGkMrqakBoAepp4NMRIDTwaAE2A008GokgHxjd1pzKFpW0uAg5NSBBTirgOpDWgDTTTQAw0w
- 0gGGmmgZWBp4pASKaeDTEOBp4NADwajbrUyBEkXWnSUdAGr1qeiAMSkNWAhphoAaaYaQDDTT
- SGVRTwaYDxTwaBDwaeDQA4GlK5oauIeo20pGaLaAKqgU6hKwBSGmAhphoAaaYaQxhpppDKgN
- PFMB4p4oEPFOBpgPBp4NAhwpwoAWloAKSgBDTTQMYaYaQDTTTSGA/9n/2wCEAAoHBwgHBgoI
- CAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9
- PjsBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7
- Ozs7Ozs7Ozs7Ozs7O//AABEIAEgAYAMBIQACEQEDEQH/xAGiAAABBQEBAQEBAQAAAAAAAAAA
- AQIDBAUGBwgJCgsQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNC
- scEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hp
- anN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS
- 09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+gEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcI
- CQoLEQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVi
- ctEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4
- eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY
- 2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AJ7SLgcVr20I4rNFGvbQAAHFaEUX
- SrQi5HCMdKk8oY6VSJYx4hjpVaWMelAFC4iGDxWPdR8mkxmRdxjBrEvI+tZjN20xtHNbNqAc
- UIDXg6Cr0WKtCY8XKQOyzOB3FKNWsyceZ+lS6sY6NkjvPSdwImBHUmmy4q076oCjOODWPdgc
- 0MpGPdAYNYl4o5rNjNKzkyorZtXxihAa1vIDip7m9Frb7/4jwKcnyxbEzN3ieJppZsyZ4U1H
- urzZau4mWVlNrGk0UuWPVa1YroXEIkHfrXZh5W90RWncAHmsi6bJNdQ0ZNw3BrGuiMGs2Mks
- puBzWzbzdOaEBeOpR2oUtkk9hTru7iuo4m8wgemKyqTi04sBsfkEf68j8KlUQZz9o/SuZRj3
- JYriAji4/Sp7W6htbV2aXcu70ramoxle4gN7HcIXjbis+4k5NdaaauhmVcv1rHuW61DGiG1m
- 6c1s20/TmgAv5vmj57VKk3+ixnPc1xVV70h9CVJuOtSrL71hFgxzScUkkn+iY/2q1i9xDrGT
- 9y31pJ5Otd1L+GhMy7mTrWXO2SapjRn28vTmta3nxjmgGOvJd2w1Kkv+ipz/ABGuOoveYdCe
- ObjrU6y5rlsA8ycUksn+ij/eNaw6iJLNsW59zTJn6816FP4EJmbO+Saz5m602UjIgk4HNadv
- LwKaBl+MpIMOMipp490SCJeF7CoqQvF2JuRqWQ4YEGrSiQJuKnHrXByMpki73GFBNXIoh9n2
- SrnnOK6MPTbd3sSwIVF2qMCqkzHmuy1lYRnTHrVGWpZaMKB+BWlbycYoQM0IZDxzV+GU8c1a
- IYy5Y+dnHatAsfsAHfArmS1mPoh1gT8x9qtk1rQX7tCe5DIapzGtGBQm71SlqGWjnIH6Vowt
- zmhAy/E3vV6F6tEMuxlWIyAfrVxCCAO1VZEEyYA4AApxNGwyJ+lVJRUsaKMw61SlFQzRAP/Z
-
-X-ATTRIBUTE:Some String
-BDAY:19800101
-GEO:35.6563854,139.6994233
-URL:http://www.example.com/
-REV:20080424T195243Z
-END:VCARD
\ No newline at end of file diff --git a/core/tests/coretests/res/raw/v21_invalid_comment_line.vcf b/core/tests/coretests/res/raw/v21_invalid_comment_line.vcf deleted file mode 100644 index f910710..0000000 --- a/core/tests/coretests/res/raw/v21_invalid_comment_line.vcf +++ /dev/null @@ -1,10 +0,0 @@ -BEGIN:vCard
-VERSION:2.1
-UID:357
-N:;Conference Call
-FN:Conference Call
-# This line must be ignored.
-NOTE;ENCODING=QUOTED-PRINTABLE:This is an (sharp ->=
-#<- sharp) example. This message must NOT be ignored.
-# This line must be ignored too.
-END:vCard
diff --git a/core/tests/coretests/res/raw/v21_japanese_1.vcf b/core/tests/coretests/res/raw/v21_japanese_1.vcf deleted file mode 100644 index d05e2ff..0000000 --- a/core/tests/coretests/res/raw/v21_japanese_1.vcf +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN:VCARD
-VERSION:2.1
-N;CHARSET=SHIFT_JIS:ˆÀ“¡ƒƒCƒh;;;;
-SOUND;X-IRMC-N;CHARSET=SHIFT_JIS:±ÝÄÞ³Û²ÄÞ;;;;
-TEL;PREF;VOICE:0300000000
-END:VCARD
diff --git a/core/tests/coretests/res/raw/v21_japanese_2.vcf b/core/tests/coretests/res/raw/v21_japanese_2.vcf deleted file mode 100644 index fa54acb..0000000 --- a/core/tests/coretests/res/raw/v21_japanese_2.vcf +++ /dev/null @@ -1,10 +0,0 @@ -BEGIN:VCARD
-VERSION:2.1
-FN;CHARSET=SHIFT_JIS:ˆÀ“¡ ƒƒCƒh 1
-N;CHARSET=SHIFT_JIS:ˆÀ“¡;ƒƒCƒh1;;;
-SOUND;X-IRMC-N;CHARSET=SHIFT_JIS:±ÝÄÞ³;Û²ÄÞ1;;;
-ADR;HOME;CHARSET=SHIFT_JIS;ENCODING=QUOTED-PRINTABLE:;=93=8C=8B=9E=93=73=
-=8F=61=92=4A=8B=E6=8D=F7=8B=75=92=AC26-1=83=5A=83=8B=83=8A=83=41=83=93=
-=83=5E=83=8F=81=5B6=8A=4B;;;;150-8512;
-NOTE;CHARSET=SHIFT_JIS;ENCODING=QUOTED-PRINTABLE:=83=81=83=82
-END:VCARD
diff --git a/core/tests/coretests/res/raw/v21_multiple_entry.vcf b/core/tests/coretests/res/raw/v21_multiple_entry.vcf deleted file mode 100644 index ebbb19a..0000000 --- a/core/tests/coretests/res/raw/v21_multiple_entry.vcf +++ /dev/null @@ -1,33 +0,0 @@ -BEGIN:VCARD
-VERSION:2.1
-N;CHARSET=SHIFT_JIS:ˆÀ“¡ƒƒCƒh3;;;;
-SOUND;X-IRMC-N;CHARSET=SHIFT_JIS:±ÝÄÞ³Û²ÄÞ3;;;;
-TEL;X-NEC-SECRET:9
-TEL;X-NEC-HOTEL:10
-TEL;X-NEC-SCHOOL:11
-TEL;HOME;FAX:12
-END:VCARD
-
-
-BEGIN:VCARD
-VERSION:2.1
-N;CHARSET=SHIFT_JIS:ˆÀ“¡ƒƒCƒh4;;;;
-SOUND;X-IRMC-N;CHARSET=SHIFT_JIS:±ÝÄÞ³Û²ÄÞ4;;;;
-TEL;MODEM:13
-TEL;PAGER:14
-TEL;X-NEC-FAMILY:15
-TEL;X-NEC-GIRL:16
-END:VCARD
-
-
-BEGIN:VCARD
-VERSION:2.1
-N;CHARSET=SHIFT_JIS:ˆÀ“¡ƒƒCƒh5;;;;
-SOUND;X-IRMC-N;CHARSET=SHIFT_JIS:±ÝÄÞ³Û²ÄÞ5;;;;
-TEL;X-NEC-BOY:17
-TEL;X-NEC-FRIEND:18
-TEL;X-NEC-PHS:19
-TEL;X-NEC-RESTAURANT:20
-END:VCARD
-
-
diff --git a/core/tests/coretests/res/raw/v21_org_before_title.vcf b/core/tests/coretests/res/raw/v21_org_before_title.vcf deleted file mode 100644 index 8ff1190..0000000 --- a/core/tests/coretests/res/raw/v21_org_before_title.vcf +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN:VCARD
-VERSION:2.1
-FN:Normal Guy
-ORG:Company;Organization;Devision;Room;Sheet No.
-TITLE:Excellent Janitor
-END:VCARD
diff --git a/core/tests/coretests/res/raw/v21_pref_handling.vcf b/core/tests/coretests/res/raw/v21_pref_handling.vcf deleted file mode 100644 index 5105310..0000000 --- a/core/tests/coretests/res/raw/v21_pref_handling.vcf +++ /dev/null @@ -1,15 +0,0 @@ -BEGIN:VCARD -VERSION:2.1 -FN:Smith -TEL;HOME:1 -TEL;WORK;PREF:2 -TEL;ISDN:3 -EMAIL;PREF;HOME:test@example.com -EMAIL;CELL;PREF:test2@examination.com -ORG:Company -TITLE:Engineer -ORG:Mystery -TITLE:Blogger -ORG:Poetry -TITLE:Poet -END:VCARD diff --git a/core/tests/coretests/res/raw/v21_simple_1.vcf b/core/tests/coretests/res/raw/v21_simple_1.vcf deleted file mode 100644 index 6aabb4c..0000000 --- a/core/tests/coretests/res/raw/v21_simple_1.vcf +++ /dev/null @@ -1,3 +0,0 @@ -BEGIN:VCARD
-N:Ando;Roid;
-END:VCARD
diff --git a/core/tests/coretests/res/raw/v21_simple_2.vcf b/core/tests/coretests/res/raw/v21_simple_2.vcf deleted file mode 100644 index f0d5ab5..0000000 --- a/core/tests/coretests/res/raw/v21_simple_2.vcf +++ /dev/null @@ -1,3 +0,0 @@ -BEGIN:VCARD
-FN:Ando Roid
-END:VCARD
diff --git a/core/tests/coretests/res/raw/v21_simple_3.vcf b/core/tests/coretests/res/raw/v21_simple_3.vcf deleted file mode 100644 index beddabb..0000000 --- a/core/tests/coretests/res/raw/v21_simple_3.vcf +++ /dev/null @@ -1,4 +0,0 @@ -BEGIN:VCARD
-N:Ando;Roid;
-FN:Ando Roid
-END:VCARD
diff --git a/core/tests/coretests/res/raw/v21_title_before_org.vcf b/core/tests/coretests/res/raw/v21_title_before_org.vcf deleted file mode 100644 index 9fdc738..0000000 --- a/core/tests/coretests/res/raw/v21_title_before_org.vcf +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN:VCARD
-VERSION:2.1
-FN:Nice Guy
-TITLE:Cool Title
-ORG:Marverous;Perfect;Great;Good;Bad;Poor
-END:VCARD
diff --git a/core/tests/coretests/res/raw/v21_winmo_65.vcf b/core/tests/coretests/res/raw/v21_winmo_65.vcf deleted file mode 100644 index f380d0d..0000000 --- a/core/tests/coretests/res/raw/v21_winmo_65.vcf +++ /dev/null @@ -1,10 +0,0 @@ -BEGIN:VCARD
-VERSION:2.1
-N:Example;;;;
-FN:Example
-ANNIVERSARY;VALUE=DATE:20091010
-AGENT:Invalid line which must be handled correctly.
-X-CLASS:PUBLIC
-X-REDUCTION:
-X-NO:
-END:VCARD
diff --git a/core/tests/coretests/res/raw/v30_comma_separated.vcf b/core/tests/coretests/res/raw/v30_comma_separated.vcf deleted file mode 100644 index 98a7f20..0000000 --- a/core/tests/coretests/res/raw/v30_comma_separated.vcf +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN:VCARD
-VERSION:3.0
-N:F;G;M;;
-TEL;TYPE=PAGER,WORK,MSG:6101231234@pagersample.com
-END:VCARD
diff --git a/core/tests/coretests/res/raw/v30_simple.vcf b/core/tests/coretests/res/raw/v30_simple.vcf deleted file mode 100644 index 418661f..0000000 --- a/core/tests/coretests/res/raw/v30_simple.vcf +++ /dev/null @@ -1,13 +0,0 @@ -BEGIN:VCARD
-VERSION:3.0
-FN:And Roid
-N:And;Roid;;;
-ORG:Open;Handset; Alliance
-SORT-STRING:android
-TEL;TYPE=PREF;TYPE=VOICE:0300000000
-CLASS:PUBLIC
-X-GNO:0
-X-GN:group0
-X-REDUCTION:0
-REV:20081031T065854Z
-END:VCARD
diff --git a/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java b/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java deleted file mode 100644 index 0820a68..0000000 --- a/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java +++ /dev/null @@ -1,969 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.pim.vcard; - -import android.content.ContentValues; -import android.pim.vcard.test_utils.ContactEntry; -import android.pim.vcard.test_utils.PropertyNodesVerifierElem; -import android.pim.vcard.test_utils.PropertyNodesVerifierElem.TypeSet; -import android.provider.ContactsContract.CommonDataKinds.Email; -import android.provider.ContactsContract.CommonDataKinds.Event; -import android.provider.ContactsContract.CommonDataKinds.Im; -import android.provider.ContactsContract.CommonDataKinds.Nickname; -import android.provider.ContactsContract.CommonDataKinds.Note; -import android.provider.ContactsContract.CommonDataKinds.Organization; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.Photo; -import android.provider.ContactsContract.CommonDataKinds.Relation; -import android.provider.ContactsContract.CommonDataKinds.StructuredName; -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; -import android.provider.ContactsContract.CommonDataKinds.Website; - -import java.util.Arrays; - -/** - * Tests for the code related to vCard exporter, inculding vCard composer. - * This test class depends on vCard importer code, so if tests for vCard importer fail, - * the result of this class will not be reliable. - */ -public class VCardExporterTests extends VCardTestsBase { - private static final byte[] sPhotoByteArray = - VCardImporterTests.sPhotoByteArrayForComplicatedCase; - - public void testSimpleV21() { - mVerifier.initForExportTest(V21); - mVerifier.addInputEntry().addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "Ando") - .put(StructuredName.GIVEN_NAME, "Roid"); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNode("FN", "Roid Ando") - .addExpectedNode("N", "Ando;Roid;;;", - Arrays.asList("Ando", "Roid", "", "", "")); - } - - private void testStructuredNameBasic(int vcardType) { - final boolean isV30 = VCardConfig.isV30(vcardType); - mVerifier.initForExportTest(vcardType); - mVerifier.addInputEntry().addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName") - .put(StructuredName.GIVEN_NAME, "AppropriateGivenName") - .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName") - .put(StructuredName.PREFIX, "AppropriatePrefix") - .put(StructuredName.SUFFIX, "AppropriateSuffix") - .put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily") - .put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven") - .put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle"); - - PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("N", - "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;" - + "AppropriatePrefix;AppropriateSuffix", - Arrays.asList("AppropriateFamilyName", "AppropriateGivenName", - "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix")) - .addExpectedNodeWithOrder("FN", - "AppropriatePrefix AppropriateGivenName " - + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix") - .addExpectedNode("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven") - .addExpectedNode("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle") - .addExpectedNode("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily"); - - if (isV30) { - elem.addExpectedNode("SORT-STRING", - "AppropriatePhoneticGiven AppropriatePhoneticMiddle " - + "AppropriatePhoneticFamily"); - } - } - - public void testStructuredNameBasicV21() { - testStructuredNameBasic(V21); - } - - public void testStructuredNameBasicV30() { - testStructuredNameBasic(V30); - } - - /** - * Test that only "primary" StructuredName is emitted, so that our vCard file - * will not confuse the external importer, assuming there may be some importer - * which presume that there's only one property toward each of "N", "FN", etc. - * Note that more than one "N", "FN", etc. properties are acceptable in vCard spec. - */ - private void testStructuredNameUsePrimaryCommon(int vcardType) { - final boolean isV30 = (vcardType == V30); - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1") - .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1") - .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1") - .put(StructuredName.PREFIX, "DoNotEmitPrefix1") - .put(StructuredName.SUFFIX, "DoNotEmitSuffix1") - .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily1") - .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven1") - .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle1"); - - // With "IS_PRIMARY=1". This is what we should use. - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName") - .put(StructuredName.GIVEN_NAME, "AppropriateGivenName") - .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName") - .put(StructuredName.PREFIX, "AppropriatePrefix") - .put(StructuredName.SUFFIX, "AppropriateSuffix") - .put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily") - .put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven") - .put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle") - .put(StructuredName.IS_PRIMARY, 1); - - // With "IS_PRIMARY=1", but we should ignore this time, since this is second, not first. - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2") - .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2") - .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2") - .put(StructuredName.PREFIX, "DoNotEmitPrefix2") - .put(StructuredName.SUFFIX, "DoNotEmitSuffix2") - .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily2") - .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven2") - .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle2") - .put(StructuredName.IS_PRIMARY, 1); - - PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("N", - "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;" - + "AppropriatePrefix;AppropriateSuffix", - Arrays.asList("AppropriateFamilyName", "AppropriateGivenName", - "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix")) - .addExpectedNodeWithOrder("FN", - "AppropriatePrefix AppropriateGivenName " - + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix") - .addExpectedNode("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven") - .addExpectedNode("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle") - .addExpectedNode("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily"); - - if (isV30) { - elem.addExpectedNode("SORT-STRING", - "AppropriatePhoneticGiven AppropriatePhoneticMiddle " - + "AppropriatePhoneticFamily"); - } - } - - public void testStructuredNameUsePrimaryV21() { - testStructuredNameUsePrimaryCommon(V21); - } - - public void testStructuredNameUsePrimaryV30() { - testStructuredNameUsePrimaryCommon(V30); - } - - /** - * Tests that only "super primary" StructuredName is emitted. - * See also the comment in {@link #testStructuredNameUsePrimaryCommon(int)}. - */ - private void testStructuredNameUseSuperPrimaryCommon(int vcardType) { - final boolean isV30 = (vcardType == V30); - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1") - .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1") - .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1") - .put(StructuredName.PREFIX, "DoNotEmitPrefix1") - .put(StructuredName.SUFFIX, "DoNotEmitSuffix1") - .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily1") - .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven1") - .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle1"); - - // With "IS_PRIMARY=1", but we should ignore this time. - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2") - .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2") - .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2") - .put(StructuredName.PREFIX, "DoNotEmitPrefix2") - .put(StructuredName.SUFFIX, "DoNotEmitSuffix2") - .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily2") - .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven2") - .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle2") - .put(StructuredName.IS_PRIMARY, 1); - - // With "IS_SUPER_PRIMARY=1". This is what we should use. - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName") - .put(StructuredName.GIVEN_NAME, "AppropriateGivenName") - .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName") - .put(StructuredName.PREFIX, "AppropriatePrefix") - .put(StructuredName.SUFFIX, "AppropriateSuffix") - .put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily") - .put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven") - .put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle") - .put(StructuredName.IS_SUPER_PRIMARY, 1); - - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName3") - .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName3") - .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName3") - .put(StructuredName.PREFIX, "DoNotEmitPrefix3") - .put(StructuredName.SUFFIX, "DoNotEmitSuffix3") - .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily3") - .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven3") - .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle3") - .put(StructuredName.IS_PRIMARY, 1); - - PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("N", - "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;" - + "AppropriatePrefix;AppropriateSuffix", - Arrays.asList("AppropriateFamilyName", "AppropriateGivenName", - "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix")) - .addExpectedNodeWithOrder("FN", - "AppropriatePrefix AppropriateGivenName " - + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix") - .addExpectedNode("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven") - .addExpectedNode("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle") - .addExpectedNode("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily"); - - if (isV30) { - elem.addExpectedNode("SORT-STRING", - "AppropriatePhoneticGiven AppropriatePhoneticMiddle" - + " AppropriatePhoneticFamily"); - } - } - - public void testStructuredNameUseSuperPrimaryV21() { - testStructuredNameUseSuperPrimaryCommon(V21); - } - - public void testStructuredNameUseSuperPrimaryV30() { - testStructuredNameUseSuperPrimaryCommon(V30); - } - - public void testNickNameV30() { - mVerifier.initForExportTest(V30); - mVerifier.addInputEntry().addContentValues(Nickname.CONTENT_ITEM_TYPE) - .put(Nickname.NAME, "Nicky"); - - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNodeWithOrder("NICKNAME", "Nicky"); - } - - private void testPhoneBasicCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - mVerifier.addInputEntry().addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "1") - .put(Phone.TYPE, Phone.TYPE_HOME); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("TEL", "1", new TypeSet("HOME")); - } - - public void testPhoneBasicV21() { - testPhoneBasicCommon(V21); - } - - public void testPhoneBasicV30() { - testPhoneBasicCommon(V30); - } - - public void testPhoneRefrainFormatting() { - mVerifier.initForExportTest(V21 | VCardConfig.FLAG_REFRAIN_PHONE_NUMBER_FORMATTING); - mVerifier.addInputEntry().addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "1234567890(abcdefghijklmnopqrstuvwxyz)") - .put(Phone.TYPE, Phone.TYPE_HOME); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("TEL", "1234567890(abcdefghijklmnopqrstuvwxyz)", - new TypeSet("HOME")); - } - - /** - * Tests that vCard composer emits corresponding type param which we expect. - */ - private void testPhoneVariousTypeSupport(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "10") - .put(Phone.TYPE, Phone.TYPE_HOME); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "20") - .put(Phone.TYPE, Phone.TYPE_WORK); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "30") - .put(Phone.TYPE, Phone.TYPE_FAX_HOME); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "40") - .put(Phone.TYPE, Phone.TYPE_FAX_WORK); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "50") - .put(Phone.TYPE, Phone.TYPE_MOBILE); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "60") - .put(Phone.TYPE, Phone.TYPE_PAGER); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "70") - .put(Phone.TYPE, Phone.TYPE_OTHER); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "80") - .put(Phone.TYPE, Phone.TYPE_CAR); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "90") - .put(Phone.TYPE, Phone.TYPE_COMPANY_MAIN); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "100") - .put(Phone.TYPE, Phone.TYPE_ISDN); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "110") - .put(Phone.TYPE, Phone.TYPE_MAIN); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "120") - .put(Phone.TYPE, Phone.TYPE_OTHER_FAX); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "130") - .put(Phone.TYPE, Phone.TYPE_TELEX); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "140") - .put(Phone.TYPE, Phone.TYPE_WORK_MOBILE); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "150") - .put(Phone.TYPE, Phone.TYPE_WORK_PAGER); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "160") - .put(Phone.TYPE, Phone.TYPE_MMS); - - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("TEL", "10", new TypeSet("HOME")) - .addExpectedNode("TEL", "20", new TypeSet("WORK")) - .addExpectedNode("TEL", "30", new TypeSet("HOME", "FAX")) - .addExpectedNode("TEL", "40", new TypeSet("WORK", "FAX")) - .addExpectedNode("TEL", "50", new TypeSet("CELL")) - .addExpectedNode("TEL", "60", new TypeSet("PAGER")) - .addExpectedNode("TEL", "70", new TypeSet("VOICE")) - .addExpectedNode("TEL", "80", new TypeSet("CAR")) - .addExpectedNode("TEL", "90", new TypeSet("WORK", "PREF")) - .addExpectedNode("TEL", "100", new TypeSet("ISDN")) - .addExpectedNode("TEL", "110", new TypeSet("PREF")) - .addExpectedNode("TEL", "120", new TypeSet("FAX")) - .addExpectedNode("TEL", "130", new TypeSet("TLX")) - .addExpectedNode("TEL", "140", new TypeSet("WORK", "CELL")) - .addExpectedNode("TEL", "150", new TypeSet("WORK", "PAGER")) - .addExpectedNode("TEL", "160", new TypeSet("MSG")); - } - - public void testPhoneVariousTypeSupportV21() { - testPhoneVariousTypeSupport(V21); - } - - public void testPhoneVariousTypeSupportV30() { - testPhoneVariousTypeSupport(V30); - } - - /** - * Tests that "PREF"s are emitted appropriately. - */ - private void testPhonePrefHandlingCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "1") - .put(Phone.TYPE, Phone.TYPE_HOME); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "2") - .put(Phone.TYPE, Phone.TYPE_WORK) - .put(Phone.IS_PRIMARY, 1); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "3") - .put(Phone.TYPE, Phone.TYPE_FAX_HOME) - .put(Phone.IS_PRIMARY, 1); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "4") - .put(Phone.TYPE, Phone.TYPE_FAX_WORK); - - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("TEL", "4", new TypeSet("WORK", "FAX")) - .addExpectedNode("TEL", "3", new TypeSet("HOME", "FAX", "PREF")) - .addExpectedNode("TEL", "2", new TypeSet("WORK", "PREF")) - .addExpectedNode("TEL", "1", new TypeSet("HOME")); - } - - public void testPhonePrefHandlingV21() { - testPhonePrefHandlingCommon(V21); - } - - public void testPhonePrefHandlingV30() { - testPhonePrefHandlingCommon(V30); - } - - private void testMiscPhoneTypeHandling(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "1") - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "Modem"); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "2") - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "MSG"); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "3") - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "BBS"); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "4") - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "VIDEO"); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "5") - .put(Phone.TYPE, Phone.TYPE_CUSTOM); - entry.addContentValues(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.addContentValues(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.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "8") - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "invalid"); - PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElemWithEmptyName(); - elem.addExpectedNode("TEL", "1", new TypeSet("MODEM")) - .addExpectedNode("TEL", "2", new TypeSet("MSG")) - .addExpectedNode("TEL", "3", new TypeSet("BBS")) - .addExpectedNode("TEL", "4", new TypeSet("VIDEO")) - .addExpectedNode("TEL", "5", new TypeSet("VOICE")) - .addExpectedNode("TEL", "6", new TypeSet("CELL")) - .addExpectedNode("TEL", "7", new TypeSet("CELL")) - .addExpectedNode("TEL", "8", new TypeSet("X-invalid")); - } - - public void testPhoneTypeHandlingV21() { - testMiscPhoneTypeHandling(V21); - } - - public void testPhoneTypeHandlingV30() { - testMiscPhoneTypeHandling(V30); - } - - private void testEmailBasicCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - mVerifier.addInputEntry().addContentValues(Email.CONTENT_ITEM_TYPE) - .put(Email.DATA, "sample@example.com"); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("EMAIL", "sample@example.com"); - } - - public void testEmailBasicV21() { - testEmailBasicCommon(V21); - } - - public void testEmailBasicV30() { - testEmailBasicCommon(V30); - } - - private void testEmailVariousTypeSupportCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Email.CONTENT_ITEM_TYPE) - .put(Email.DATA, "type_home@example.com") - .put(Email.TYPE, Email.TYPE_HOME); - entry.addContentValues(Email.CONTENT_ITEM_TYPE) - .put(Email.DATA, "type_work@example.com") - .put(Email.TYPE, Email.TYPE_WORK); - entry.addContentValues(Email.CONTENT_ITEM_TYPE) - .put(Email.DATA, "type_mobile@example.com") - .put(Email.TYPE, Email.TYPE_MOBILE); - entry.addContentValues(Email.CONTENT_ITEM_TYPE) - .put(Email.DATA, "type_other@example.com") - .put(Email.TYPE, Email.TYPE_OTHER); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("EMAIL", "type_home@example.com", new TypeSet("HOME")) - .addExpectedNode("EMAIL", "type_work@example.com", new TypeSet("WORK")) - .addExpectedNode("EMAIL", "type_mobile@example.com", new TypeSet("CELL")) - .addExpectedNode("EMAIL", "type_other@example.com"); - } - - public void testEmailVariousTypeSupportV21() { - testEmailVariousTypeSupportCommon(V21); - } - - public void testEmailVariousTypeSupportV30() { - testEmailVariousTypeSupportCommon(V30); - } - - private void testEmailPrefHandlingCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Email.CONTENT_ITEM_TYPE) - .put(Email.DATA, "type_home@example.com") - .put(Email.TYPE, Email.TYPE_HOME) - .put(Email.IS_PRIMARY, 1); - entry.addContentValues(Email.CONTENT_ITEM_TYPE) - .put(Email.DATA, "type_notype@example.com") - .put(Email.IS_PRIMARY, 1); - - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("EMAIL", "type_notype@example.com", new TypeSet("PREF")) - .addExpectedNode("EMAIL", "type_home@example.com", new TypeSet("HOME", "PREF")); - } - - public void testEmailPrefHandlingV21() { - testEmailPrefHandlingCommon(V21); - } - - public void testEmailPrefHandlingV30() { - testEmailPrefHandlingCommon(V30); - } - - private void testPostalAddressCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.POBOX, "Pobox") - .put(StructuredPostal.NEIGHBORHOOD, "Neighborhood") - .put(StructuredPostal.STREET, "Street") - .put(StructuredPostal.CITY, "City") - .put(StructuredPostal.REGION, "Region") - .put(StructuredPostal.POSTCODE, "100") - .put(StructuredPostal.COUNTRY, "Country") - .put(StructuredPostal.FORMATTED_ADDRESS, "Formatted Address") - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK); - // adr-value = 0*6(text-value ";") text-value - // ; PO Box, Extended Address, Street, Locality, Region, Postal Code, - // ; Country Name - // - // The NEIGHBORHOOD field is appended after the CITY field. - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("ADR", - Arrays.asList("Pobox", "", "Street", "City Neighborhood", - "Region", "100", "Country"), new TypeSet("WORK")); - } - - public void testPostalAddressV21() { - testPostalAddressCommon(V21); - } - - public void testPostalAddressV30() { - testPostalAddressCommon(V30); - } - - private void testPostalAddressNonNeighborhood(int vcardType) { - mVerifier.initForExportTest(vcardType); - mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.CITY, "City"); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("ADR", - Arrays.asList("", "", "", "City", "", "", ""), new TypeSet("HOME")); - } - - public void testPostalAddressNonNeighborhoodV21() { - testPostalAddressNonNeighborhood(V21); - } - - public void testPostalAddressNonNeighborhoodV30() { - testPostalAddressNonNeighborhood(V30); - } - - private void testPostalAddressNonCity(int vcardType) { - mVerifier.initForExportTest(vcardType); - mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.NEIGHBORHOOD, "Neighborhood"); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("ADR", - Arrays.asList("", "", "", "Neighborhood", "", "", ""), new TypeSet("HOME")); - } - - public void testPostalAddressNonCityV21() { - testPostalAddressNonCity(V21); - } - - public void testPostalAddressNonCityV30() { - testPostalAddressNonCity(V30); - } - - private void testPostalOnlyWithFormattedAddressCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.REGION, "") // Must be ignored. - .put(StructuredPostal.FORMATTED_ADDRESS, - "Formatted address CA 123-334 United Statue"); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNodeWithOrder("ADR", ";Formatted address CA 123-334 United Statue;;;;;", - Arrays.asList("", "Formatted address CA 123-334 United Statue", - "", "", "", "", ""), new TypeSet("HOME")); - } - - public void testPostalOnlyWithFormattedAddressV21() { - testPostalOnlyWithFormattedAddressCommon(V21); - } - - public void testPostalOnlyWithFormattedAddressV30() { - testPostalOnlyWithFormattedAddressCommon(V30); - } - - /** - * Tests that the vCard composer honors formatted data when it is available - * even when it is partial. - */ - private void testPostalWithBothStructuredAndFormattedCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.POBOX, "Pobox") - .put(StructuredPostal.COUNTRY, "Country") - .put(StructuredPostal.FORMATTED_ADDRESS, - "Formatted address CA 123-334 United Statue"); // Should be ignored - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("ADR", "Pobox;;;;;;Country", - Arrays.asList("Pobox", "", "", "", "", "", "Country"), - new TypeSet("HOME")); - } - - public void testPostalWithBothStructuredAndFormattedV21() { - testPostalWithBothStructuredAndFormattedCommon(V21); - } - - public void testPostalWithBothStructuredAndFormattedV30() { - testPostalWithBothStructuredAndFormattedCommon(V30); - } - - private void testOrganizationCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Organization.CONTENT_ITEM_TYPE) - .put(Organization.COMPANY, "CompanyX") - .put(Organization.DEPARTMENT, "DepartmentY") - .put(Organization.TITLE, "TitleZ") - .put(Organization.JOB_DESCRIPTION, "Description Rambda") // Ignored. - .put(Organization.OFFICE_LOCATION, "Mountain View") // Ignored. - .put(Organization.PHONETIC_NAME, "PhoneticName!") // Ignored - .put(Organization.SYMBOL, "(^o^)/~~"); // Ignore him (her). - entry.addContentValues(Organization.CONTENT_ITEM_TYPE) - .putNull(Organization.COMPANY) - .put(Organization.DEPARTMENT, "DepartmentXX") - .putNull(Organization.TITLE); - entry.addContentValues(Organization.CONTENT_ITEM_TYPE) - .put(Organization.COMPANY, "CompanyXYZ") - .putNull(Organization.DEPARTMENT) - .put(Organization.TITLE, "TitleXYZYX"); - // Currently we do not use group but depend on the order. - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNodeWithOrder("ORG", "CompanyX;DepartmentY", - Arrays.asList("CompanyX", "DepartmentY")) - .addExpectedNodeWithOrder("TITLE", "TitleZ") - .addExpectedNodeWithOrder("ORG", "DepartmentXX") - .addExpectedNodeWithOrder("ORG", "CompanyXYZ") - .addExpectedNodeWithOrder("TITLE", "TitleXYZYX"); - } - - public void testOrganizationV21() { - testOrganizationCommon(V21); - } - - public void testOrganizationV30() { - testOrganizationCommon(V30); - } - - private void testImVariousTypeSupportCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Im.CONTENT_ITEM_TYPE) - .put(Im.PROTOCOL, Im.PROTOCOL_AIM) - .put(Im.DATA, "aim"); - entry.addContentValues(Im.CONTENT_ITEM_TYPE) - .put(Im.PROTOCOL, Im.PROTOCOL_MSN) - .put(Im.DATA, "msn"); - entry.addContentValues(Im.CONTENT_ITEM_TYPE) - .put(Im.PROTOCOL, Im.PROTOCOL_YAHOO) - .put(Im.DATA, "yahoo"); - entry.addContentValues(Im.CONTENT_ITEM_TYPE) - .put(Im.PROTOCOL, Im.PROTOCOL_SKYPE) - .put(Im.DATA, "skype"); - entry.addContentValues(Im.CONTENT_ITEM_TYPE) - .put(Im.PROTOCOL, Im.PROTOCOL_QQ) - .put(Im.DATA, "qq"); - entry.addContentValues(Im.CONTENT_ITEM_TYPE) - .put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK) - .put(Im.DATA, "google talk"); - entry.addContentValues(Im.CONTENT_ITEM_TYPE) - .put(Im.PROTOCOL, Im.PROTOCOL_ICQ) - .put(Im.DATA, "icq"); - entry.addContentValues(Im.CONTENT_ITEM_TYPE) - .put(Im.PROTOCOL, Im.PROTOCOL_JABBER) - .put(Im.DATA, "jabber"); - entry.addContentValues(Im.CONTENT_ITEM_TYPE) - .put(Im.PROTOCOL, Im.PROTOCOL_NETMEETING) - .put(Im.DATA, "netmeeting"); - - // No determined way to express unknown type... - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("X-JABBER", "jabber") - .addExpectedNode("X-ICQ", "icq") - .addExpectedNode("X-GOOGLE-TALK", "google talk") - .addExpectedNode("X-QQ", "qq") - .addExpectedNode("X-SKYPE-USERNAME", "skype") - .addExpectedNode("X-YAHOO", "yahoo") - .addExpectedNode("X-MSN", "msn") - .addExpectedNode("X-NETMEETING", "netmeeting") - .addExpectedNode("X-AIM", "aim"); - } - - public void testImBasiV21() { - testImVariousTypeSupportCommon(V21); - } - - public void testImBasicV30() { - testImVariousTypeSupportCommon(V30); - } - - private void testImPrefHandlingCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Im.CONTENT_ITEM_TYPE) - .put(Im.PROTOCOL, Im.PROTOCOL_AIM) - .put(Im.DATA, "aim1"); - entry.addContentValues(Im.CONTENT_ITEM_TYPE) - .put(Im.PROTOCOL, Im.PROTOCOL_AIM) - .put(Im.DATA, "aim2") - .put(Im.TYPE, Im.TYPE_HOME) - .put(Im.IS_PRIMARY, 1); - - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("X-AIM", "aim1") - .addExpectedNode("X-AIM", "aim2", new TypeSet("HOME", "PREF")); - } - - public void testImPrefHandlingV21() { - testImPrefHandlingCommon(V21); - } - - public void testImPrefHandlingV30() { - testImPrefHandlingCommon(V30); - } - - private void testWebsiteCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Website.CONTENT_ITEM_TYPE) - .put(Website.URL, "http://website.example.android.com/index.html") - .put(Website.TYPE, Website.TYPE_BLOG); - entry.addContentValues(Website.CONTENT_ITEM_TYPE) - .put(Website.URL, "ftp://ftp.example.android.com/index.html") - .put(Website.TYPE, Website.TYPE_FTP); - - // We drop TYPE information since vCard (especially 3.0) does not allow us to emit it. - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("URL", "ftp://ftp.example.android.com/index.html") - .addExpectedNode("URL", "http://website.example.android.com/index.html"); - } - - public void testWebsiteV21() { - testWebsiteCommon(V21); - } - - public void testWebsiteV30() { - testWebsiteCommon(V30); - } - - private String getAndroidPropValue(final String mimeType, String value, Integer type) { - return getAndroidPropValue(mimeType, value, type, null); - } - - private String getAndroidPropValue(final String mimeType, String value, - Integer type, String label) { - return (mimeType + ";" + value + ";" - + (type != null ? type : "") + ";" - + (label != null ? label : "") + ";;;;;;;;;;;;"); - } - - private void testEventCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Event.CONTENT_ITEM_TYPE) - .put(Event.TYPE, Event.TYPE_ANNIVERSARY) - .put(Event.START_DATE, "1982-06-16"); - entry.addContentValues(Event.CONTENT_ITEM_TYPE) - .put(Event.TYPE, Event.TYPE_BIRTHDAY) - .put(Event.START_DATE, "2008-10-22"); - entry.addContentValues(Event.CONTENT_ITEM_TYPE) - .put(Event.TYPE, Event.TYPE_OTHER) - .put(Event.START_DATE, "2018-03-12"); - entry.addContentValues(Event.CONTENT_ITEM_TYPE) - .put(Event.TYPE, Event.TYPE_CUSTOM) - .put(Event.LABEL, "The last day") - .put(Event.START_DATE, "When the Tower of Hanoi with 64 rings is completed."); - entry.addContentValues(Event.CONTENT_ITEM_TYPE) - .put(Event.TYPE, Event.TYPE_BIRTHDAY) - .put(Event.START_DATE, "2009-05-19"); // Should be ignored. - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("BDAY", "2008-10-22") - .addExpectedNode("X-ANDROID-CUSTOM", - getAndroidPropValue( - Event.CONTENT_ITEM_TYPE, "1982-06-16", Event.TYPE_ANNIVERSARY)) - .addExpectedNode("X-ANDROID-CUSTOM", - getAndroidPropValue( - Event.CONTENT_ITEM_TYPE, "2018-03-12", Event.TYPE_OTHER)) - .addExpectedNode("X-ANDROID-CUSTOM", - getAndroidPropValue( - Event.CONTENT_ITEM_TYPE, - "When the Tower of Hanoi with 64 rings is completed.", - Event.TYPE_CUSTOM, "The last day")); - } - - public void testEventV21() { - testEventCommon(V21); - } - - public void testEventV30() { - testEventCommon(V30); - } - - private void testNoteCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Note.CONTENT_ITEM_TYPE) - .put(Note.NOTE, "note1"); - entry.addContentValues(Note.CONTENT_ITEM_TYPE) - .put(Note.NOTE, "note2") - .put(Note.IS_PRIMARY, 1); // Just ignored. - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNodeWithOrder("NOTE", "note1") - .addExpectedNodeWithOrder("NOTE", "note2"); - } - - public void testNoteV21() { - testNoteCommon(V21); - } - - public void testNoteV30() { - testNoteCommon(V30); - } - - private void testPhotoCommon(int vcardType) { - final boolean isV30 = vcardType == V30; - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "PhotoTest"); - entry.addContentValues(Photo.CONTENT_ITEM_TYPE) - .put(Photo.PHOTO, sPhotoByteArray); - - ContentValues contentValuesForPhoto = new ContentValues(); - contentValuesForPhoto.put("ENCODING", (isV30 ? "b" : "BASE64")); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNode("FN", "PhotoTest") - .addExpectedNode("N", "PhotoTest;;;;", - Arrays.asList("PhotoTest", "", "", "", "")) - .addExpectedNodeWithOrder("PHOTO", null, null, sPhotoByteArray, - contentValuesForPhoto, new TypeSet("JPEG"), null); - } - - public void testPhotoV21() { - testPhotoCommon(V21); - } - - public void testPhotoV30() { - testPhotoCommon(V30); - } - - private void testRelationCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - mVerifier.addInputEntry().addContentValues(Relation.CONTENT_ITEM_TYPE) - .put(Relation.TYPE, Relation.TYPE_MOTHER) - .put(Relation.NAME, "Ms. Mother"); - mVerifier.addContentValuesVerifierElem().addExpected(Relation.CONTENT_ITEM_TYPE) - .put(Relation.TYPE, Relation.TYPE_MOTHER) - .put(Relation.NAME, "Ms. Mother"); - } - - public void testRelationV21() { - testRelationCommon(V21); - } - - public void testRelationV30() { - testRelationCommon(V30); - } - - public void testV30HandleEscape() { - mVerifier.initForExportTest(V30); - mVerifier.addInputEntry().addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "\\") - .put(StructuredName.GIVEN_NAME, ";") - .put(StructuredName.MIDDLE_NAME, ",") - .put(StructuredName.PREFIX, "\n") - .put(StructuredName.DISPLAY_NAME, "[<{Unescaped:Asciis}>]"); - // Verifies the vCard String correctly escapes each character which must be escaped. - mVerifier.addLineVerifierElem() - .addExpected("N:\\\\;\\;;\\,;\\n;") - .addExpected("FN:[<{Unescaped:Asciis}>]"); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNode("FN", "[<{Unescaped:Asciis}>]") - .addExpectedNode("N", Arrays.asList("\\", ";", ",", "\n", "")); - } - - /** - * There's no "NICKNAME" property in vCard 2.1, while there is in vCard 3.0. - * We use Android-specific "X-ANDROID-CUSTOM" property. - * This test verifies the functionality. - */ - public void testNickNameV21() { - mVerifier.initForExportTest(V21); - mVerifier.addInputEntry().addContentValues(Nickname.CONTENT_ITEM_TYPE) - .put(Nickname.NAME, "Nicky"); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("X-ANDROID-CUSTOM", - Nickname.CONTENT_ITEM_TYPE + ";Nicky;;;;;;;;;;;;;;"); - mVerifier.addContentValuesVerifierElem().addExpected(Nickname.CONTENT_ITEM_TYPE) - .put(Nickname.NAME, "Nicky"); - } - - public void testTolerateBrokenPhoneNumberEntryV21() { - mVerifier.initForExportTest(V21); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_HOME) - .put(Phone.NUMBER, "111-222-3333 (Miami)\n444-5555-666 (Tokyo);" - + "777-888-9999 (Chicago);111-222-3333 (Miami)"); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("TEL", "111-222-3333", new TypeSet("HOME")) - .addExpectedNode("TEL", "444-555-5666", new TypeSet("HOME")) - .addExpectedNode("TEL", "777-888-9999", new TypeSet("HOME")); - } - - private void testPickUpNonEmptyContentValuesCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.IS_PRIMARY, 1); // Empty name. Should be ignored. - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "family1"); // Not primary. Should be ignored. - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.IS_PRIMARY, 1) - .put(StructuredName.FAMILY_NAME, "family2"); // This entry is what we want. - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.IS_PRIMARY, 1) - .put(StructuredName.FAMILY_NAME, "family3"); - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "family4"); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNode("N", Arrays.asList("family2", "", "", "", "")) - .addExpectedNode("FN", "family2"); - } - - public void testPickUpNonEmptyContentValuesV21() { - testPickUpNonEmptyContentValuesCommon(V21); - } - - public void testPickUpNonEmptyContentValuesV30() { - testPickUpNonEmptyContentValuesCommon(V30); - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/VCardImporterTests.java b/core/tests/coretests/src/android/pim/vcard/VCardImporterTests.java deleted file mode 100644 index ea2ac6a..0000000 --- a/core/tests/coretests/src/android/pim/vcard/VCardImporterTests.java +++ /dev/null @@ -1,1008 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard; - -import android.content.ContentValues; -import android.pim.vcard.test_utils.ContentValuesVerifier; -import android.pim.vcard.test_utils.ContentValuesVerifierElem; -import android.pim.vcard.test_utils.PropertyNodesVerifierElem.TypeSet; -import android.provider.ContactsContract.Data; -import android.provider.ContactsContract.CommonDataKinds.Email; -import android.provider.ContactsContract.CommonDataKinds.Event; -import android.provider.ContactsContract.CommonDataKinds.Note; -import android.provider.ContactsContract.CommonDataKinds.Organization; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.Photo; -import android.provider.ContactsContract.CommonDataKinds.StructuredName; -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; -import android.provider.ContactsContract.CommonDataKinds.Website; - -import com.android.frameworks.coretests.R; - -import java.util.Arrays; - -public class VCardImporterTests extends VCardTestsBase { - // Push data into int array at first since values like 0x80 are - // interpreted as int by the compiler and casting all of them is - // cumbersome... - private static final int[] sPhotoIntArrayForComplicatedCase = { - 0xff, 0xd8, 0xff, 0xe1, 0x0a, 0x0f, 0x45, 0x78, 0x69, 0x66, 0x00, - 0x00, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, - 0x01, 0x0e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, - 0xaa, 0x01, 0x0f, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x00, 0xba, 0x01, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x00, 0xc2, 0x01, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x1b, 0x00, 0x05, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0xd0, 0x01, 0x28, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x31, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x32, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xe6, 0x02, 0x13, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x82, - 0x98, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xfa, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x84, 0xc4, 0xa5, 0x00, 0x07, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, - 0x01, 0x08, 0x00, 0x00, 0x04, 0x1e, 0x32, 0x30, 0x30, 0x38, 0x31, - 0x30, 0x32, 0x39, 0x31, 0x33, 0x35, 0x35, 0x33, 0x31, 0x00, 0x00, - 0x44, 0x6f, 0x43, 0x6f, 0x4d, 0x6f, 0x00, 0x00, 0x44, 0x39, 0x30, - 0x35, 0x69, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x44, 0x39, 0x30, - 0x35, 0x69, 0x20, 0x56, 0x65, 0x72, 0x31, 0x2e, 0x30, 0x30, 0x00, - 0x32, 0x30, 0x30, 0x38, 0x3a, 0x31, 0x30, 0x3a, 0x32, 0x39, 0x20, - 0x31, 0x33, 0x3a, 0x35, 0x35, 0x3a, 0x34, 0x37, 0x00, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x00, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x49, 0x4d, 0x00, 0x30, 0x33, - 0x30, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x14, 0x00, - 0x14, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x34, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x09, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x0f, 0x0b, 0x00, - 0x00, 0x27, 0x10, 0x00, 0x00, 0x05, 0x97, 0x00, 0x00, 0x27, 0x10, - 0x00, 0x00, 0x08, 0xb0, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x1c, - 0x01, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x02, 0x5e, 0x00, 0x00, - 0x27, 0x10, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x27, 0x10, 0x00, - 0x00, 0x03, 0xcb, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x1b, 0xe5, - 0x00, 0x00, 0x27, 0x10, 0x00, 0x28, 0x82, 0x9a, 0x00, 0x05, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x6a, 0x82, 0x9d, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x72, 0x88, 0x22, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x90, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x30, 0x32, 0x32, 0x30, 0x90, - 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x03, 0x7a, - 0x90, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x03, - 0x8e, 0x91, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x01, 0x02, - 0x03, 0x00, 0x91, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x03, 0xa2, 0x92, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x03, 0xaa, 0x92, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x03, 0xb2, 0x92, 0x04, 0x00, 0x0a, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x03, 0xba, 0x92, 0x05, 0x00, 0x05, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xc2, 0x92, 0x07, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x92, 0x08, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x92, 0x09, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x92, - 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xca, - 0x92, 0x7c, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x92, 0x86, 0x00, 0x07, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, - 0x03, 0xd2, 0xa0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x30, - 0x31, 0x30, 0x30, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x60, 0x00, 0x00, 0xa0, 0x03, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0xa0, 0x05, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x0e, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xe8, 0xa2, 0x0f, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xf0, 0xa2, 0x10, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0xa2, - 0x17, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, - 0xa3, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, - 0x00, 0xa3, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, - 0x00, 0x00, 0xa4, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0xa4, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x04, 0x00, 0x05, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x03, 0xf8, 0xa4, 0x05, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x1d, 0x00, 0x00, 0xa4, 0x06, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x07, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x08, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, - 0x09, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0xa4, 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0xa4, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, - 0x00, 0x27, 0x10, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x00, 0x00, 0x64, - 0x32, 0x30, 0x30, 0x38, 0x3a, 0x31, 0x30, 0x3a, 0x32, 0x39, 0x20, - 0x31, 0x33, 0x3a, 0x35, 0x35, 0x3a, 0x33, 0x31, 0x00, 0x32, 0x30, - 0x30, 0x38, 0x3a, 0x31, 0x30, 0x3a, 0x32, 0x39, 0x20, 0x31, 0x33, - 0x3a, 0x35, 0x35, 0x3a, 0x34, 0x37, 0x00, 0x00, 0x00, 0x29, 0x88, - 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x02, 0xb2, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x25, 0x00, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0e, 0x92, 0x00, 0x00, 0x03, 0xe8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x30, 0x30, - 0x38, 0x31, 0x30, 0x32, 0x39, 0x31, 0x33, 0x35, 0x35, 0x33, 0x31, - 0x00, 0x00, 0x20, 0x2a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x2a, - 0xe2, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x04, 0x52, 0x39, 0x38, 0x00, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x04, 0x30, 0x31, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x01, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, - 0x00, 0x00, 0x01, 0x1a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x04, 0x6c, 0x01, 0x1b, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x04, 0x74, 0x01, 0x28, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x02, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x04, 0x7c, 0x02, 0x02, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x8b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x00, 0x01, 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, - 0x00, 0x20, 0x16, 0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c, 0x1a, 0x1c, - 0x24, 0x22, 0x20, 0x26, 0x30, 0x50, 0x34, 0x30, 0x2c, 0x2c, 0x30, - 0x62, 0x46, 0x4a, 0x3a, 0x50, 0x74, 0x66, 0x7a, 0x78, 0x72, 0x66, - 0x70, 0x6e, 0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88, 0xae, 0x8a, 0x6e, - 0x70, 0xa0, 0xda, 0xa2, 0xae, 0xbe, 0xc4, 0xce, 0xd0, 0xce, 0x7c, - 0x9a, 0xe2, 0xf2, 0xe0, 0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6, 0x01, - 0x22, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34, 0x34, 0x5e, 0xc6, - 0x84, 0x70, 0x84, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xff, 0xc0, - 0x00, 0x11, 0x08, 0x00, 0x78, 0x00, 0xa0, 0x03, 0x01, 0x21, 0x00, - 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x01, 0xa2, 0x00, - 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, - 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, - 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, - 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, - 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, - 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, - 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, - 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, - 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, - 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, - 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, - 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01, 0x00, - 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, - 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, - 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, - 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, - 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, - 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, - 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, - 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, - 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, - 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, - 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, - 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, - 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, - 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xda, 0x00, - 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, - 0x14, 0x54, 0xaa, 0x2a, 0x46, 0x48, 0xa2, 0xa4, 0x55, 0xa6, 0x04, - 0x8a, 0x29, 0xe0, 0x53, 0x10, 0xe0, 0x29, 0xc0, 0x50, 0x03, 0xb1, - 0x46, 0x29, 0x80, 0x84, 0x52, 0x11, 0x40, 0x0d, 0x22, 0x9a, 0x45, - 0x20, 0x23, 0x61, 0x51, 0x30, 0xa0, 0x08, 0xc8, 0xa8, 0xd8, 0x52, - 0x02, 0x26, 0x15, 0x0b, 0x0a, 0x00, 0xb4, 0xa2, 0xa5, 0x5a, 0x00, - 0x91, 0x45, 0x4a, 0xa2, 0x81, 0x92, 0x01, 0x4e, 0x02, 0x98, 0x87, - 0x0a, 0x70, 0xa0, 0x07, 0x62, 0x8c, 0x50, 0x21, 0x0d, 0x25, 0x00, - 0x34, 0x8a, 0x61, 0x14, 0x0c, 0x63, 0x0a, 0x89, 0x85, 0x00, 0x46, - 0xd5, 0x1b, 0x52, 0x02, 0x16, 0xa8, 0x98, 0x50, 0x05, 0x94, 0xa9, - 0x16, 0x80, 0x25, 0x5a, 0x95, 0x68, 0x18, 0xf1, 0x4f, 0x14, 0xc4, - 0x3b, 0xb5, 0x22, 0xb6, 0x38, 0x34, 0x00, 0xe3, 0x22, 0x8e, 0xf4, - 0x79, 0x8a, 0x7b, 0xd1, 0x71, 0x03, 0x30, 0xc7, 0x14, 0x83, 0xa5, - 0x00, 0x06, 0x98, 0x68, 0x01, 0x8d, 0x51, 0x35, 0x03, 0x22, 0x6a, - 0x8d, 0xa9, 0x01, 0x13, 0x54, 0x4d, 0x40, 0x13, 0xa5, 0x4a, 0x28, - 0x02, 0x45, 0x35, 0x2a, 0x9a, 0x00, 0x78, 0x34, 0xf0, 0x69, 0x80, - 0x34, 0x81, 0x45, 0x40, 0xce, 0x58, 0xe6, 0xa2, 0x4c, 0x06, 0xe4, - 0xfa, 0xd1, 0x93, 0x50, 0x21, 0xca, 0xe4, 0x55, 0x84, 0x90, 0x30, - 0xab, 0x8b, 0x18, 0xa6, 0x9a, 0x6a, 0xc4, 0x31, 0xaa, 0x26, 0xa0, - 0x64, 0x4d, 0x51, 0xb5, 0x20, 0x23, 0x6a, 0x89, 0xa8, 0x02, 0x44, - 0x35, 0x2a, 0x9a, 0x00, 0x95, 0x4d, 0x48, 0xa6, 0x80, 0x24, 0x53, - 0x4e, 0xce, 0x05, 0x30, 0x2b, 0x3b, 0xee, 0x6a, 0x91, 0x5d, 0x76, - 0x63, 0xbd, 0x65, 0x7d, 0x40, 0x66, 0x68, 0xa9, 0x02, 0x45, 0x2b, - 0xb3, 0x9e, 0xb4, 0xc5, 0x6d, 0xad, 0x9a, 0xa0, 0x2c, 0x06, 0xc8, - 0xcd, 0x04, 0xd6, 0xa2, 0x23, 0x63, 0x51, 0xb1, 0xa0, 0x64, 0x4d, - 0x51, 0x93, 0x48, 0x08, 0xda, 0xa2, 0x6a, 0x00, 0x72, 0x1a, 0x99, - 0x4d, 0x00, 0x48, 0xa6, 0xa4, 0x53, 0x4c, 0x07, 0x86, 0x03, 0xbd, - 0x2b, 0x9c, 0xa7, 0x14, 0x98, 0x10, 0x85, 0x34, 0xe0, 0xa6, 0xb3, - 0xb0, 0x0b, 0xb5, 0xa8, 0x0a, 0xd4, 0x58, 0x42, 0xed, 0x3e, 0x94, - 0xd2, 0xa6, 0x8b, 0x01, 0x34, 0x44, 0xed, 0xe6, 0x9c, 0x4d, 0x6a, - 0x80, 0x8d, 0x8d, 0x46, 0xc6, 0x80, 0x23, 0x63, 0x51, 0x9a, 0x06, - 0x46, 0xd5, 0x13, 0x52, 0x01, 0x54, 0xd4, 0xaa, 0x68, 0x02, 0x40, - 0x6a, 0x40, 0x78, 0xa0, 0x08, 0x59, 0xce, 0xee, 0xb5, 0x2a, 0x39, - 0xd9, 0x59, 0xa7, 0xa8, 0x00, 0x73, 0xeb, 0x4e, 0x0e, 0x7d, 0x69, - 0x5c, 0x05, 0xf3, 0x0f, 0xad, 0x1e, 0x61, 0xf5, 0xa7, 0x71, 0x0b, - 0xe6, 0x35, 0x21, 0x90, 0xd3, 0xb8, 0x0e, 0x32, 0x10, 0x95, 0x10, - 0x91, 0xb3, 0xd6, 0x9b, 0x60, 0x4b, 0x9c, 0x8a, 0x63, 0x1a, 0xb0, - 0x18, 0x4d, 0x46, 0xc6, 0x80, 0x22, 0x6a, 0x61, 0xa4, 0x31, 0xaa, - 0x6a, 0x55, 0x34, 0x01, 0x2a, 0x9a, 0x7e, 0x78, 0xa0, 0x08, 0x09, - 0xf9, 0xaa, 0x58, 0xcf, 0xca, 0x6b, 0x3e, 0xa0, 0x00, 0xd3, 0x81, - 0xa9, 0x01, 0x73, 0x46, 0x69, 0x80, 0xb9, 0xa4, 0xcd, 0x00, 0x2b, - 0x1f, 0x92, 0xa3, 0x07, 0x9a, 0x6f, 0x70, 0x26, 0xcf, 0x14, 0xd2, - 0x6b, 0x51, 0x0c, 0x63, 0x51, 0xb1, 0xa0, 0x08, 0xda, 0x98, 0x69, - 0x0c, 0x8d, 0x4d, 0x4a, 0xa6, 0x80, 0x24, 0x53, 0x52, 0x03, 0xc5, - 0x02, 0x21, 0x27, 0xe6, 0xa9, 0x23, 0x3f, 0x29, 0xac, 0xfa, 0x8c, - 0x01, 0xe6, 0x9c, 0x0d, 0x48, 0x0a, 0x0d, 0x2e, 0x68, 0x01, 0x73, - 0x49, 0x9a, 0x60, 0x2b, 0x1f, 0x92, 0x98, 0x3a, 0xd3, 0x7b, 0x81, - 0x36, 0x78, 0xa6, 0x93, 0x5a, 0x88, 0x8c, 0x9a, 0x63, 0x1a, 0x00, - 0x8c, 0xd3, 0x0d, 0x21, 0x91, 0x29, 0xa9, 0x14, 0xd0, 0x04, 0x8a, - 0x69, 0xe0, 0xd3, 0x11, 0x1b, 0x1e, 0x6a, 0x48, 0xcf, 0xca, 0x6b, - 0x3e, 0xa3, 0x10, 0x1a, 0x70, 0x35, 0x20, 0x38, 0x1a, 0x5c, 0xd2, - 0x01, 0x73, 0x49, 0x9a, 0x60, 0x39, 0x8f, 0xca, 0x29, 0x8b, 0xf7, - 0xaa, 0xba, 0x88, 0x96, 0x9a, 0x6b, 0x40, 0x18, 0xc6, 0xa3, 0x26, - 0x80, 0x18, 0x69, 0xa6, 0x90, 0xc8, 0x14, 0xd4, 0x8a, 0x69, 0x80, - 0xf0, 0x6a, 0x40, 0x68, 0x10, 0xbb, 0x41, 0xa7, 0xe3, 0x0b, 0xc5, - 0x2b, 0x01, 0x10, 0xa7, 0x03, 0x59, 0x0c, 0x76, 0x69, 0x73, 0x40, - 0x0b, 0x9a, 0x28, 0x11, 0x28, 0x19, 0x5e, 0x69, 0x02, 0x81, 0x5a, - 0xd8, 0x00, 0xd3, 0x4d, 0x50, 0x0c, 0x6a, 0x8c, 0xd2, 0x01, 0xa6, - 0x98, 0x69, 0x0c, 0xae, 0xa6, 0xa4, 0x06, 0x80, 0x1e, 0xa6, 0x9e, - 0x0d, 0x31, 0x12, 0x03, 0x4f, 0x06, 0x80, 0x13, 0x60, 0x34, 0xd3, - 0xc1, 0xa8, 0x92, 0x01, 0xf1, 0x8d, 0xdd, 0x69, 0xcc, 0xa1, 0x69, - 0x5b, 0x4b, 0x80, 0x83, 0x93, 0x52, 0x04, 0x14, 0xe2, 0xae, 0x03, - 0xa9, 0x0d, 0x68, 0x03, 0x4d, 0x34, 0xd0, 0x03, 0x0d, 0x30, 0xd2, - 0x01, 0x86, 0x9a, 0x68, 0x19, 0x58, 0x1a, 0x78, 0xa4, 0x04, 0x8a, - 0x69, 0xe0, 0xd3, 0x10, 0xe0, 0x69, 0xe0, 0xd0, 0x03, 0xc1, 0xa8, - 0xdb, 0xad, 0x4c, 0x81, 0x12, 0x45, 0xd6, 0x9d, 0x25, 0x1d, 0x00, - 0x6a, 0xf5, 0xa9, 0xe8, 0x80, 0x31, 0x29, 0x0d, 0x58, 0x08, 0x69, - 0x86, 0x80, 0x1a, 0x69, 0x86, 0x90, 0x0c, 0x34, 0xd3, 0x48, 0x65, - 0x51, 0x4f, 0x06, 0x98, 0x0f, 0x14, 0xf0, 0x68, 0x10, 0xf0, 0x69, - 0xe0, 0xd0, 0x03, 0x81, 0xa5, 0x2b, 0x9a, 0x1a, 0xb8, 0x87, 0xa8, - 0xdb, 0x4a, 0x46, 0x68, 0xb6, 0x80, 0x2a, 0xa8, 0x14, 0xea, 0x12, - 0xb0, 0x05, 0x21, 0xa6, 0x02, 0x1a, 0x61, 0xa0, 0x06, 0x9a, 0x61, - 0xa4, 0x31, 0x86, 0x9a, 0x69, 0x0c, 0xa8, 0x0d, 0x3c, 0x53, 0x01, - 0xe2, 0x9e, 0x28, 0x10, 0xf1, 0x4e, 0x06, 0x98, 0x0f, 0x06, 0x9e, - 0x0d, 0x02, 0x1c, 0x29, 0xc2, 0x80, 0x16, 0x96, 0x80, 0x0a, 0x4a, - 0x00, 0x43, 0x4d, 0x34, 0x0c, 0x61, 0xa6, 0x1a, 0x40, 0x34, 0xd3, - 0x4d, 0x21, 0x80, 0xff, 0xd9, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0a, - 0x07, 0x07, 0x08, 0x07, 0x06, 0x0a, 0x08, 0x08, 0x08, 0x0b, 0x0a, - 0x0a, 0x0b, 0x0e, 0x18, 0x10, 0x0e, 0x0d, 0x0d, 0x0e, 0x1d, 0x15, - 0x16, 0x11, 0x18, 0x23, 0x1f, 0x25, 0x24, 0x22, 0x1f, 0x22, 0x21, - 0x26, 0x2b, 0x37, 0x2f, 0x26, 0x29, 0x34, 0x29, 0x21, 0x22, 0x30, - 0x41, 0x31, 0x34, 0x39, 0x3b, 0x3e, 0x3e, 0x3e, 0x25, 0x2e, 0x44, - 0x49, 0x43, 0x3c, 0x48, 0x37, 0x3d, 0x3e, 0x3b, 0x01, 0x0a, 0x0b, - 0x0b, 0x0e, 0x0d, 0x0e, 0x1c, 0x10, 0x10, 0x1c, 0x3b, 0x28, 0x22, - 0x28, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xc0, 0x00, 0x11, - 0x08, 0x00, 0x48, 0x00, 0x60, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, - 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, - 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, - 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, - 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, - 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, - 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, - 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, - 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, - 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, - 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, - 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, - 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, - 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, - 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, - 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, - 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, - 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, - 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, - 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, - 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, - 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, - 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, - 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, - 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xda, 0x00, 0x0c, 0x03, - 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x9e, 0xd2, - 0x2e, 0x07, 0x15, 0xaf, 0x6d, 0x08, 0xe2, 0xb3, 0x45, 0x1a, 0xf6, - 0xd0, 0x00, 0x01, 0xc5, 0x68, 0x45, 0x17, 0x4a, 0xb4, 0x22, 0xe4, - 0x70, 0x8c, 0x74, 0xa9, 0x3c, 0xa1, 0x8e, 0x95, 0x48, 0x96, 0x31, - 0xe2, 0x18, 0xe9, 0x55, 0xa5, 0x8c, 0x7a, 0x50, 0x05, 0x0b, 0x88, - 0x86, 0x0f, 0x15, 0x8f, 0x75, 0x1f, 0x26, 0x93, 0x19, 0x91, 0x77, - 0x18, 0xc1, 0xac, 0x4b, 0xc8, 0xfa, 0xd6, 0x63, 0x37, 0x6d, 0x31, - 0xb4, 0x73, 0x5b, 0x36, 0xa0, 0x1c, 0x50, 0x80, 0xd7, 0x83, 0xa0, - 0xab, 0xd1, 0x62, 0xad, 0x09, 0x8f, 0x17, 0x29, 0x03, 0xb2, 0xcc, - 0xe0, 0x77, 0x14, 0xa3, 0x56, 0xb3, 0x27, 0x1e, 0x67, 0xe9, 0x52, - 0xea, 0xc6, 0x3a, 0x36, 0x48, 0xef, 0x3d, 0x27, 0x70, 0x22, 0x60, - 0x47, 0x52, 0x69, 0xb2, 0xe2, 0xad, 0x3b, 0xea, 0x80, 0xa3, 0x38, - 0xe0, 0xd6, 0x3d, 0xd8, 0x1c, 0xd0, 0xca, 0x46, 0x3d, 0xd0, 0x18, - 0x35, 0x89, 0x78, 0xa3, 0x9a, 0xcd, 0x8c, 0xd2, 0xb3, 0x93, 0x2a, - 0x2b, 0x66, 0xd5, 0xf1, 0x8a, 0x10, 0x1a, 0xd6, 0xf2, 0x03, 0x8a, - 0x9e, 0xe6, 0xf4, 0x5a, 0xdb, 0xef, 0xfe, 0x23, 0xc0, 0xa7, 0x27, - 0xcb, 0x16, 0xc4, 0xcc, 0xdd, 0xe2, 0x78, 0x9a, 0x69, 0x66, 0xcc, - 0x99, 0xe1, 0x4d, 0x47, 0xba, 0xbc, 0xd9, 0x6a, 0xee, 0x26, 0x59, - 0x59, 0x4d, 0xac, 0x69, 0x34, 0x52, 0xe5, 0x8f, 0x55, 0xad, 0x58, - 0xae, 0x85, 0xc4, 0x22, 0x41, 0xdf, 0xad, 0x76, 0x61, 0xe5, 0x6f, - 0x74, 0x45, 0x69, 0xdc, 0x00, 0x79, 0xac, 0x8b, 0xa6, 0xc9, 0x35, - 0xd4, 0x34, 0x64, 0xdc, 0x37, 0x06, 0xb1, 0xae, 0x88, 0xc1, 0xac, - 0xd8, 0xc9, 0x2c, 0xa6, 0xe0, 0x73, 0x5b, 0x36, 0xf3, 0x74, 0xe6, - 0x84, 0x05, 0xe3, 0xa9, 0x47, 0x6a, 0x14, 0xb6, 0x49, 0x3d, 0x85, - 0x3a, 0xee, 0xee, 0x2b, 0xa8, 0xe2, 0x6f, 0x30, 0x81, 0xe9, 0x8a, - 0xca, 0xa4, 0xe2, 0xd3, 0x8b, 0x01, 0xb1, 0xf9, 0x04, 0x7f, 0xaf, - 0x23, 0xf0, 0xa9, 0x54, 0x41, 0x9c, 0xfd, 0xa3, 0xf4, 0xae, 0x65, - 0x18, 0xf7, 0x25, 0x8a, 0xe2, 0x02, 0x38, 0xb8, 0xfd, 0x2a, 0x7b, - 0x5b, 0xa8, 0x6d, 0x6d, 0x5d, 0x9a, 0x5d, 0xcb, 0xbb, 0xd2, 0xb6, - 0xa6, 0xa3, 0x19, 0x5e, 0xe2, 0x03, 0x7b, 0x1d, 0xc2, 0x17, 0x8d, - 0xb8, 0xac, 0xfb, 0x89, 0x39, 0x35, 0xd6, 0x9a, 0x6a, 0xe8, 0x66, - 0x55, 0xcb, 0xf5, 0xac, 0x7b, 0x96, 0xeb, 0x50, 0xc6, 0x88, 0x6d, - 0x66, 0xe9, 0xcd, 0x6c, 0xdb, 0x4f, 0xd3, 0x9a, 0x00, 0x2f, 0xe6, - 0xf9, 0xa3, 0xe7, 0xb5, 0x4a, 0x93, 0x7f, 0xa2, 0xc6, 0x73, 0xdc, - 0xd7, 0x15, 0x55, 0xef, 0x48, 0x7d, 0x09, 0x52, 0x6e, 0x3a, 0xd4, - 0xab, 0x2f, 0xbd, 0x61, 0x16, 0x0c, 0x73, 0x49, 0xc5, 0x24, 0x92, - 0x7f, 0xa2, 0x63, 0xfd, 0xaa, 0xd6, 0x2f, 0x71, 0x0e, 0xb1, 0x93, - 0xf7, 0x2d, 0xf5, 0xa4, 0x9e, 0x4e, 0xb5, 0xdd, 0x4b, 0xf8, 0x68, - 0x4c, 0xcb, 0xb9, 0x93, 0xad, 0x65, 0xce, 0xd9, 0x26, 0xa9, 0x8d, - 0x19, 0xf6, 0xf2, 0xf4, 0xe6, 0xb5, 0xad, 0xe7, 0xc6, 0x39, 0xa0, - 0x18, 0xeb, 0xc9, 0x77, 0x6c, 0x35, 0x2a, 0x4b, 0xfe, 0x8a, 0x9c, - 0xff, 0x00, 0x11, 0xae, 0x3a, 0x8b, 0xde, 0x61, 0xd0, 0x9e, 0x39, - 0xb8, 0xeb, 0x53, 0xac, 0xb9, 0xae, 0x5b, 0x00, 0xf3, 0x27, 0x14, - 0x92, 0xc9, 0xfe, 0x8a, 0x3f, 0xde, 0x35, 0xac, 0x3a, 0x88, 0x92, - 0xcd, 0xb1, 0x6e, 0x7d, 0xcd, 0x32, 0x67, 0xeb, 0xcd, 0x7a, 0x14, - 0xfe, 0x04, 0x26, 0x66, 0xce, 0xf9, 0x26, 0xb3, 0xe6, 0x6e, 0xb4, - 0xd9, 0x48, 0xc8, 0x82, 0x4e, 0x07, 0x35, 0xa7, 0x6f, 0x2f, 0x02, - 0x9a, 0x06, 0x5f, 0x8c, 0xa4, 0x83, 0x0e, 0x32, 0x2a, 0x69, 0xe3, - 0xdd, 0x12, 0x08, 0x97, 0x85, 0xec, 0x2a, 0x2a, 0x42, 0xf1, 0x76, - 0x26, 0xe4, 0x6a, 0x59, 0x0e, 0x18, 0x10, 0x6a, 0xd2, 0x89, 0x02, - 0x6e, 0x2a, 0x71, 0xeb, 0x5c, 0x1c, 0x8c, 0xa6, 0x48, 0xbb, 0xdc, - 0x61, 0x41, 0x35, 0x72, 0x28, 0x87, 0xd9, 0xf6, 0x4a, 0xb9, 0xe7, - 0x38, 0xae, 0x8c, 0x3d, 0x36, 0xdd, 0xde, 0xc4, 0xb0, 0x21, 0x51, - 0x76, 0xa8, 0xc0, 0xaa, 0x93, 0x31, 0xe6, 0xbb, 0x2d, 0x65, 0x61, - 0x19, 0xd3, 0x1e, 0xb5, 0x46, 0x5a, 0x96, 0x5a, 0x30, 0xa0, 0x7e, - 0x05, 0x69, 0x5b, 0xc9, 0xc6, 0x28, 0x40, 0xcd, 0x08, 0x64, 0x3c, - 0x73, 0x57, 0xe1, 0x94, 0xf1, 0xcd, 0x5a, 0x21, 0x8c, 0xb9, 0x63, - 0xe7, 0x67, 0x1d, 0xab, 0x40, 0xb1, 0xfb, 0x00, 0x1d, 0xf0, 0x2b, - 0x99, 0x2d, 0x66, 0x3e, 0x88, 0x75, 0x81, 0x3f, 0x31, 0xf6, 0xab, - 0x64, 0xd6, 0xb4, 0x17, 0xee, 0xd0, 0x9e, 0xe4, 0x32, 0x1a, 0xa7, - 0x31, 0xad, 0x18, 0x14, 0x26, 0xef, 0x54, 0xa5, 0xa8, 0x65, 0xa3, - 0x9c, 0x81, 0xfa, 0x56, 0x8c, 0x2d, 0xce, 0x68, 0x40, 0xcb, 0xf1, - 0x37, 0xbd, 0x5e, 0x85, 0xea, 0xd1, 0x0c, 0xbb, 0x19, 0x56, 0x23, - 0x20, 0x1f, 0xad, 0x5c, 0x42, 0x08, 0x03, 0xb5, 0x55, 0x91, 0x04, - 0xc9, 0x80, 0x38, 0x00, 0x0a, 0x71, 0x34, 0x6c, 0x32, 0x27, 0xe9, - 0x55, 0x25, 0x15, 0x2c, 0x68, 0xa3, 0x30, 0xeb, 0x54, 0xa5, 0x15, - 0x0c, 0xd1, 0x00, 0xff, 0xd9}; - - /* package */ static final byte[] sPhotoByteArrayForComplicatedCase; - - static { - final int length = sPhotoIntArrayForComplicatedCase.length; - sPhotoByteArrayForComplicatedCase = new byte[length]; - for (int i = 0; i < length; i++) { - sPhotoByteArrayForComplicatedCase[i] = (byte)sPhotoIntArrayForComplicatedCase[i]; - } - } - - public void testV21SimpleCase1_Parsing() { - mVerifier.initForImportTest(V21, R.raw.v21_simple_1); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("N", "Ando;Roid;", Arrays.asList("Ando", "Roid", "")); - } - - public void testV21SimpleCase1_Type_Generic() { - mVerifier.initForImportTest(VCardConfig.VCARD_TYPE_V21_GENERIC, R.raw.v21_simple_1); - mVerifier.addContentValuesVerifierElem() - .addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "Ando") - .put(StructuredName.GIVEN_NAME, "Roid") - .put(StructuredName.DISPLAY_NAME, "Roid Ando"); - } - - public void testV21SimpleCase1_Type_Japanese() { - mVerifier.initForImportTest(VCardConfig.VCARD_TYPE_V21_JAPANESE, R.raw.v21_simple_1); - mVerifier.addContentValuesVerifierElem() - .addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "Ando") - .put(StructuredName.GIVEN_NAME, "Roid") - // If name-related strings only contains printable Ascii, - // the order is remained to be US's: - // "Prefix Given Middle Family Suffix" - .put(StructuredName.DISPLAY_NAME, "Roid Ando"); - } - - public void testV21SimpleCase2() { - mVerifier.initForImportTest(VCardConfig.VCARD_TYPE_V21_JAPANESE, R.raw.v21_simple_2); - mVerifier.addContentValuesVerifierElem() - .addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.DISPLAY_NAME, "Ando Roid"); - } - - public void testV21SimpleCase3() { - mVerifier.initForImportTest(V21, R.raw.v21_simple_3); - mVerifier.addContentValuesVerifierElem() - .addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "Ando") - .put(StructuredName.GIVEN_NAME, "Roid") - // "FN" field should be prefered since it should contain the original - // order intended by the author of the file. - .put(StructuredName.DISPLAY_NAME, "Ando Roid"); - } - - /** - * Tests ';' is properly handled by VCardParser implementation. - */ - public void testV21BackslashCase_Parsing() { - mVerifier.initForImportTest(V21, R.raw.v21_backslash); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("VERSION", "2.1") - .addExpectedNodeWithOrder("N", ";A;B\\;C\\;;D;:E;\\\\;", - Arrays.asList("", "A;B\\", "C\\;", "D", ":E", "\\\\", "")) - .addExpectedNodeWithOrder("FN", "A;B\\C\\;D:E\\\\"); - - } - - /** - * Tests ContactStruct correctly ignores redundant fields in "N" property values and - * inserts name related data. - */ - public void testV21BackslashCase() { - mVerifier.initForImportTest(V21, R.raw.v21_backslash); - mVerifier.addContentValuesVerifierElem() - .addExpected(StructuredName.CONTENT_ITEM_TYPE) - // FAMILY_NAME is empty and removed in this test... - .put(StructuredName.GIVEN_NAME, "A;B\\") - .put(StructuredName.MIDDLE_NAME, "C\\;") - .put(StructuredName.PREFIX, "D") - .put(StructuredName.SUFFIX, ":E") - .put(StructuredName.DISPLAY_NAME, "A;B\\C\\;D:E\\\\"); - } - - public void testOrgBeforTitle() { - mVerifier.initForImportTest(V21, R.raw.v21_org_before_title); - ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.DISPLAY_NAME, "Normal Guy"); - elem.addExpected(Organization.CONTENT_ITEM_TYPE) - .put(Organization.COMPANY, "Company") - .put(Organization.DEPARTMENT, "Organization Devision Room Sheet No.") - .put(Organization.TITLE, "Excellent Janitor") - .put(Organization.TYPE, Organization.TYPE_WORK); - } - - public void testTitleBeforOrg() { - mVerifier.initForImportTest(V21, R.raw.v21_title_before_org); - ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.DISPLAY_NAME, "Nice Guy"); - elem.addExpected(Organization.CONTENT_ITEM_TYPE) - .put(Organization.COMPANY, "Marverous") - .put(Organization.DEPARTMENT, "Perfect Great Good Bad Poor") - .put(Organization.TITLE, "Cool Title") - .put(Organization.TYPE, Organization.TYPE_WORK); - } - - /** - * Verifies that vCard importer correctly interpret "PREF" attribute to IS_PRIMARY. - * The data contain three cases: one "PREF", no "PREF" and multiple "PREF", in each type. - */ - public void testV21PrefToIsPrimary() { - mVerifier.initForImportTest(V21, R.raw.v21_pref_handling); - ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.DISPLAY_NAME, "Smith"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "1") - .put(Phone.TYPE, Phone.TYPE_HOME); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "2") - .put(Phone.TYPE, Phone.TYPE_WORK) - .put(Phone.IS_PRIMARY, 1); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "3") - .put(Phone.TYPE, Phone.TYPE_ISDN); - elem.addExpected(Email.CONTENT_ITEM_TYPE) - .put(Email.DATA, "test@example.com") - .put(Email.TYPE, Email.TYPE_HOME) - .put(Email.IS_PRIMARY, 1); - elem.addExpected(Email.CONTENT_ITEM_TYPE) - .put(Email.DATA, "test2@examination.com") - .put(Email.TYPE, Email.TYPE_MOBILE) - .put(Email.IS_PRIMARY, 1); - elem.addExpected(Organization.CONTENT_ITEM_TYPE) - .put(Organization.COMPANY, "Company") - .put(Organization.TITLE, "Engineer") - .put(Organization.TYPE, Organization.TYPE_WORK); - elem.addExpected(Organization.CONTENT_ITEM_TYPE) - .put(Organization.COMPANY, "Mystery") - .put(Organization.TITLE, "Blogger") - .put(Organization.TYPE, Organization.TYPE_WORK); - elem.addExpected(Organization.CONTENT_ITEM_TYPE) - .put(Organization.COMPANY, "Poetry") - .put(Organization.TITLE, "Poet") - .put(Organization.TYPE, Organization.TYPE_WORK); - } - - /** - * Tests all the properties in a complicated vCard are correctly parsed by the VCardParser. - */ - public void testV21ComplicatedCase_Parsing() { - mVerifier.initForImportTest(V21, R.raw.v21_complicated); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("VERSION", "2.1") - .addExpectedNodeWithOrder("N", "Gump;Forrest;Hoge;Pos;Tao", - Arrays.asList("Gump", "Forrest", "Hoge", "Pos", "Tao")) - .addExpectedNodeWithOrder("FN", "Joe Due") - .addExpectedNodeWithOrder("ORG", "Gump Shrimp Co.;Sales Dept.;Manager;Fish keeper", - Arrays.asList("Gump Shrimp Co.", "Sales Dept.;Manager", "Fish keeper")) - .addExpectedNodeWithOrder("ROLE", "Fish Cake Keeper!") - .addExpectedNodeWithOrder("TITLE", "Shrimp Man") - .addExpectedNodeWithOrder("X-CLASS", "PUBLIC") - .addExpectedNodeWithOrder("TEL", "(111) 555-1212", new TypeSet("WORK", "VOICE")) - .addExpectedNodeWithOrder("TEL", "(404) 555-1212", new TypeSet("HOME", "VOICE")) - .addExpectedNodeWithOrder("TEL", "0311111111", new TypeSet("CELL")) - .addExpectedNodeWithOrder("TEL", "0322222222", new TypeSet("VIDEO")) - .addExpectedNodeWithOrder("TEL", "0333333333", new TypeSet("VOICE")) - .addExpectedNodeWithOrder("ADR", - ";;100 Waters Edge;Baytown;LA;30314;United States of America", - Arrays.asList("", "", "100 Waters Edge", "Baytown", - "LA", "30314", "United States of America"), - null, null, new TypeSet("WORK"), null) - .addExpectedNodeWithOrder("LABEL", - "100 Waters Edge\r\nBaytown, LA 30314\r\nUnited States of America", - null, null, mContentValuesForQP, new TypeSet("WORK"), null) - .addExpectedNodeWithOrder("ADR", - ";;42 Plantation St.;Baytown;LA;30314;United States of America", - Arrays.asList("", "", "42 Plantation St.", "Baytown", - "LA", "30314", "United States of America"), null, null, - new TypeSet("HOME"), null) - .addExpectedNodeWithOrder("LABEL", - "42 Plantation St.\r\nBaytown, LA 30314\r\nUnited States of America", - null, null, mContentValuesForQP, - new TypeSet("HOME"), null) - .addExpectedNodeWithOrder("EMAIL", "forrestgump@walladalla.com", - new TypeSet("PREF", "INTERNET")) - .addExpectedNodeWithOrder("EMAIL", "cell@example.com", new TypeSet("CELL")) - .addExpectedNodeWithOrder("NOTE", "The following note is the example from RFC 2045.") - .addExpectedNodeWithOrder("NOTE", - "Now's the time for all folk to come to the aid of their country.", - null, null, mContentValuesForQP, null, null) - .addExpectedNodeWithOrder("PHOTO", null, - null, sPhotoByteArrayForComplicatedCase, mContentValuesForBase64V21, - new TypeSet("JPEG"), null) - .addExpectedNodeWithOrder("X-ATTRIBUTE", "Some String") - .addExpectedNodeWithOrder("BDAY", "19800101") - .addExpectedNodeWithOrder("GEO", "35.6563854,139.6994233") - .addExpectedNodeWithOrder("URL", "http://www.example.com/") - .addExpectedNodeWithOrder("REV", "20080424T195243Z"); - } - - /** - * Checks ContactStruct correctly inserts values in a complicated vCard - * into ContentResolver. - */ - public void testV21ComplicatedCase() { - mVerifier.initForImportTest(V21, R.raw.v21_complicated); - ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "Gump") - .put(StructuredName.GIVEN_NAME, "Forrest") - .put(StructuredName.MIDDLE_NAME, "Hoge") - .put(StructuredName.PREFIX, "Pos") - .put(StructuredName.SUFFIX, "Tao") - .put(StructuredName.DISPLAY_NAME, "Joe Due"); - elem.addExpected(Organization.CONTENT_ITEM_TYPE) - .put(Organization.TYPE, Organization.TYPE_WORK) - .put(Organization.COMPANY, "Gump Shrimp Co.") - .put(Organization.DEPARTMENT, "Sales Dept.;Manager Fish keeper") - .put(Organization.TITLE, "Shrimp Man"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_WORK) - // Phone number is expected to be formated with NAMP format in default. - .put(Phone.NUMBER, "111-555-1212"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_HOME) - .put(Phone.NUMBER, "404-555-1212"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_MOBILE) - .put(Phone.NUMBER, "031-111-1111"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "VIDEO") - .put(Phone.NUMBER, "032-222-2222"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "VOICE") - .put(Phone.NUMBER, "033-333-3333"); - elem.addExpected(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK) - .put(StructuredPostal.COUNTRY, "United States of America") - .put(StructuredPostal.POSTCODE, "30314") - .put(StructuredPostal.REGION, "LA") - .put(StructuredPostal.CITY, "Baytown") - .put(StructuredPostal.STREET, "100 Waters Edge") - .put(StructuredPostal.FORMATTED_ADDRESS, - "100 Waters Edge Baytown LA 30314 United States of America"); - elem.addExpected(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME) - .put(StructuredPostal.COUNTRY, "United States of America") - .put(StructuredPostal.POSTCODE, "30314") - .put(StructuredPostal.REGION, "LA") - .put(StructuredPostal.CITY, "Baytown") - .put(StructuredPostal.STREET, "42 Plantation St.") - .put(StructuredPostal.FORMATTED_ADDRESS, - "42 Plantation St. Baytown LA 30314 United States of America"); - elem.addExpected(Email.CONTENT_ITEM_TYPE) - // "TYPE=INTERNET" -> TYPE_CUSTOM + the label "INTERNET" - .put(Email.TYPE, Email.TYPE_CUSTOM) - .put(Email.LABEL, "INTERNET") - .put(Email.DATA, "forrestgump@walladalla.com") - .put(Email.IS_PRIMARY, 1); - elem.addExpected(Email.CONTENT_ITEM_TYPE) - .put(Email.TYPE, Email.TYPE_MOBILE) - .put(Email.DATA, "cell@example.com"); - elem.addExpected(Note.CONTENT_ITEM_TYPE) - .put(Note.NOTE, "The following note is the example from RFC 2045."); - elem.addExpected(Note.CONTENT_ITEM_TYPE) - .put(Note.NOTE, - "Now's the time for all folk to come to the aid of their country."); - elem.addExpected(Photo.CONTENT_ITEM_TYPE) - // No information about its image format can be inserted. - .put(Photo.PHOTO, sPhotoByteArrayForComplicatedCase); - elem.addExpected(Event.CONTENT_ITEM_TYPE) - .put(Event.START_DATE, "19800101") - .put(Event.TYPE, Event.TYPE_BIRTHDAY); - elem.addExpected(Website.CONTENT_ITEM_TYPE) - .put(Website.URL, "http://www.example.com/") - .put(Website.TYPE, Website.TYPE_HOMEPAGE); - } - - public void testV30Simple_Parsing() { - mVerifier.initForImportTest(V30, R.raw.v30_simple); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("VERSION", "3.0") - .addExpectedNodeWithOrder("FN", "And Roid") - .addExpectedNodeWithOrder("N", "And;Roid;;;", Arrays.asList("And", "Roid", "", "", "")) - .addExpectedNodeWithOrder("ORG", "Open;Handset; Alliance", - Arrays.asList("Open", "Handset", " Alliance")) - .addExpectedNodeWithOrder("SORT-STRING", "android") - .addExpectedNodeWithOrder("TEL", "0300000000", new TypeSet("PREF", "VOICE")) - .addExpectedNodeWithOrder("CLASS", "PUBLIC") - .addExpectedNodeWithOrder("X-GNO", "0") - .addExpectedNodeWithOrder("X-GN", "group0") - .addExpectedNodeWithOrder("X-REDUCTION", "0") - .addExpectedNodeWithOrder("REV", "20081031T065854Z"); - } - - public void testV30Simple() { - mVerifier.initForImportTest(V30, R.raw.v30_simple); - ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "And") - .put(StructuredName.GIVEN_NAME, "Roid") - .put(StructuredName.DISPLAY_NAME, "And Roid") - .put(StructuredName.PHONETIC_GIVEN_NAME, "android"); - elem.addExpected(Organization.CONTENT_ITEM_TYPE) - .put(Organization.COMPANY, "Open") - .put(Organization.DEPARTMENT, "Handset Alliance") - .put(Organization.TYPE, Organization.TYPE_WORK); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "VOICE") - .put(Phone.NUMBER, "030-000-0000") - .put(Phone.IS_PRIMARY, 1); - } - - public void testV21Japanese1_Parsing() { - // Though Japanese careers append ";;;;" at the end of the value of "SOUND", - // vCard 2.1/3.0 specification does not allow multiple values. - // Do not need to handle it as multiple values. - mVerifier.initForImportTest(VCardConfig.VCARD_TYPE_V21_JAPANESE, R.raw.v21_japanese_1); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("VERSION", "2.1", null, null, null, null, null) - .addExpectedNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9;;;;", - Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9", "", "", "", ""), - null, mContentValuesForSJis, null, null) - .addExpectedNodeWithOrder("SOUND", - "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E;;;;", - null, null, mContentValuesForSJis, - new TypeSet("X-IRMC-N"), null) - .addExpectedNodeWithOrder("TEL", "0300000000", null, null, null, - new TypeSet("VOICE", "PREF"), null); - } - - private void testV21Japanese1Common(int resId, int vcardType, boolean japanese) { - mVerifier.initForImportTest(vcardType, resId); - ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9") - .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9") - // While vCard parser does not split "SOUND" property values, - // ContactStruct care it. - .put(StructuredName.PHONETIC_GIVEN_NAME, - "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - // Phone number formatting is different. - .put(Phone.NUMBER, (japanese ? "03-0000-0000" : "030-000-0000")) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "VOICE") - .put(Phone.IS_PRIMARY, 1); - } - - /** - * Verifies vCard with Japanese can be parsed correctly with - * {@link android.pim.vcard.VCardConfig#VCARD_TYPE_V21_GENERIC}. - */ - public void testV21Japanese1_Type_Generic_Utf8() { - testV21Japanese1Common( - R.raw.v21_japanese_1, VCardConfig.VCARD_TYPE_V21_GENERIC, false); - } - - /** - * Verifies vCard with Japanese can be parsed correctly with - * {@link android.pim.vcard.VCardConfig#VCARD_TYPE_V21_JAPANESE}. - */ - public void testV21Japanese1_Type_Japanese_Sjis() { - testV21Japanese1Common( - R.raw.v21_japanese_1, VCardConfig.VCARD_TYPE_V21_JAPANESE, true); - } - - /** - * Verifies vCard with Japanese can be parsed correctly with - * {@link android.pim.vcard.VCardConfig#VCARD_TYPE_V21_JAPANESE}. - * since vCard 2.1 specifies the charset of each line if it contains non-Ascii. - */ - public void testV21Japanese1_Type_Japanese_Utf8() { - testV21Japanese1Common( - R.raw.v21_japanese_1, VCardConfig.VCARD_TYPE_V21_JAPANESE, true); - } - - public void testV21Japanese2_Parsing() { - mVerifier.initForImportTest(VCardConfig.VCARD_TYPE_V21_JAPANESE, R.raw.v21_japanese_2); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("VERSION", "2.1") - .addExpectedNodeWithOrder("N", "\u5B89\u85E4;\u30ED\u30A4\u30C9\u0031;;;", - Arrays.asList("\u5B89\u85E4", "\u30ED\u30A4\u30C9\u0031", - "", "", ""), - null, mContentValuesForSJis, null, null) - .addExpectedNodeWithOrder("FN", "\u5B89\u85E4\u0020\u30ED\u30A4\u30C9\u0020\u0031", - null, null, mContentValuesForSJis, null, null) - .addExpectedNodeWithOrder("SOUND", - "\uFF71\uFF9D\uFF84\uFF9E\uFF73;\uFF9B\uFF72\uFF84\uFF9E\u0031;;;", - null, null, mContentValuesForSJis, - new TypeSet("X-IRMC-N"), null) - .addExpectedNodeWithOrder("ADR", - ";\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" + - "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" + - "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC\u0036" + - "\u968E;;;;150-8512;", - Arrays.asList("", - "\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" + - "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" + - "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC" + - "\u0036\u968E", "", "", "", "150-8512", ""), - null, mContentValuesForQPAndSJis, new TypeSet("HOME"), null) - .addExpectedNodeWithOrder("NOTE", "\u30E1\u30E2", null, null, - mContentValuesForQPAndSJis, null, null); - } - - public void testV21Japanese2_Type_Generic_Utf8() { - mVerifier.initForImportTest(V21, R.raw.v21_japanese_2); - ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4") - .put(StructuredName.GIVEN_NAME, "\u30ED\u30A4\u30C9\u0031") - .put(StructuredName.DISPLAY_NAME, - "\u5B89\u85E4\u0020\u30ED\u30A4\u30C9\u0020\u0031") - // ContactStruct should correctly split "SOUND" property into several elements, - // even though VCardParser side does not care it. - .put(StructuredName.PHONETIC_FAMILY_NAME, "\uFF71\uFF9D\uFF84\uFF9E\uFF73") - .put(StructuredName.PHONETIC_GIVEN_NAME, "\uFF9B\uFF72\uFF84\uFF9E\u0031"); - elem.addExpected(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.POSTCODE, "150-8512") - .put(StructuredPostal.STREET, - "\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" + - "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" + - "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC" + - "\u0036\u968E") - .put(StructuredPostal.FORMATTED_ADDRESS, - "\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" + - "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" + - "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC" + - "\u0036\u968E 150-8512") - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME); - elem.addExpected(Note.CONTENT_ITEM_TYPE) - .put(Note.NOTE, "\u30E1\u30E2"); - } - - public void testV21MultipleEntryCase_Parse() { - mVerifier.initForImportTest(VCardConfig.VCARD_TYPE_V21_JAPANESE, R.raw.v21_multiple_entry); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("VERSION", "2.1") - .addExpectedNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0033;;;;", - Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0033", "", "", "", ""), - null, mContentValuesForSJis, null, null) - .addExpectedNodeWithOrder("SOUND", - "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0033;;;;", - null, null, mContentValuesForSJis, - new TypeSet("X-IRMC-N"), null) - .addExpectedNodeWithOrder("TEL", "9", new TypeSet("X-NEC-SECRET")) - .addExpectedNodeWithOrder("TEL", "10", new TypeSet("X-NEC-HOTEL")) - .addExpectedNodeWithOrder("TEL", "11", new TypeSet("X-NEC-SCHOOL")) - .addExpectedNodeWithOrder("TEL", "12", new TypeSet("FAX", "HOME")); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("VERSION", "2.1") - .addExpectedNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0034;;;;", - Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0034", "", "", "", ""), - null, mContentValuesForSJis, null, null) - .addExpectedNodeWithOrder("SOUND", - "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0034;;;;", - null, null, mContentValuesForSJis, - new TypeSet("X-IRMC-N"), null) - .addExpectedNodeWithOrder("TEL", "13", new TypeSet("MODEM")) - .addExpectedNodeWithOrder("TEL", "14", new TypeSet("PAGER")) - .addExpectedNodeWithOrder("TEL", "15", new TypeSet("X-NEC-FAMILY")) - .addExpectedNodeWithOrder("TEL", "16", new TypeSet("X-NEC-GIRL")); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("VERSION", "2.1") - .addExpectedNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0035;;;;", - Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0035", "", "", "", ""), - null, mContentValuesForSJis, null, null) - .addExpectedNodeWithOrder("SOUND", - "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0035;;;;", - null, null, mContentValuesForSJis, - new TypeSet("X-IRMC-N"), null) - .addExpectedNodeWithOrder("TEL", "17", new TypeSet("X-NEC-BOY")) - .addExpectedNodeWithOrder("TEL", "18", new TypeSet("X-NEC-FRIEND")) - .addExpectedNodeWithOrder("TEL", "19", new TypeSet("X-NEC-PHS")) - .addExpectedNodeWithOrder("TEL", "20", new TypeSet("X-NEC-RESTAURANT")); - } - - public void testV21MultipleEntryCase() { - mVerifier.initForImportTest(VCardConfig.VCARD_TYPE_V21_JAPANESE, R.raw.v21_multiple_entry); - ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0033") - .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0033") - .put(StructuredName.PHONETIC_GIVEN_NAME, - "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0033"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "NEC-SECRET") - .put(Phone.NUMBER, "9"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "NEC-HOTEL") - .put(Phone.NUMBER, "10"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "NEC-SCHOOL") - .put(Phone.NUMBER, "11"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_FAX_HOME) - .put(Phone.NUMBER, "12"); - - elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0034") - .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0034") - .put(StructuredName.PHONETIC_GIVEN_NAME, - "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0034"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "MODEM") - .put(Phone.NUMBER, "13"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_PAGER) - .put(Phone.NUMBER, "14"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "NEC-FAMILY") - .put(Phone.NUMBER, "15"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "NEC-GIRL") - .put(Phone.NUMBER, "16"); - - elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0035") - .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0035") - .put(StructuredName.PHONETIC_GIVEN_NAME, - "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0035"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "NEC-BOY") - .put(Phone.NUMBER, "17"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "NEC-FRIEND") - .put(Phone.NUMBER, "18"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "NEC-PHS") - .put(Phone.NUMBER, "19"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_CUSTOM) - .put(Phone.LABEL, "NEC-RESTAURANT") - .put(Phone.NUMBER, "20"); - } - - public void testIgnoreAgentV21_Parse() { - mVerifier.initForImportTest(V21, R.raw.v21_winmo_65); - ContentValues contentValuesForValue = new ContentValues(); - contentValuesForValue.put("VALUE", "DATE"); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("VERSION", "2.1") - .addExpectedNodeWithOrder("N", Arrays.asList("Example", "", "", "", "")) - .addExpectedNodeWithOrder("FN", "Example") - .addExpectedNodeWithOrder("ANNIVERSARY", "20091010", contentValuesForValue) - .addExpectedNodeWithOrder("AGENT", "") - .addExpectedNodeWithOrder("X-CLASS", "PUBLIC") - .addExpectedNodeWithOrder("X-REDUCTION", "") - .addExpectedNodeWithOrder("X-NO", ""); - } - - public void testIgnoreAgentV21() { - mVerifier.initForImportTest(V21, R.raw.v21_winmo_65); - ContentValuesVerifier verifier = new ContentValuesVerifier(); - ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "Example") - .put(StructuredName.DISPLAY_NAME, "Example"); - } - - public void testTolerateInvalidCommentLikeLineV21() { - mVerifier.initForImportTest(V21, R.raw.v21_invalid_comment_line); - ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.GIVEN_NAME, "Conference Call") - .put(StructuredName.DISPLAY_NAME, "Conference Call"); - elem.addExpected(Note.CONTENT_ITEM_TYPE) - .put(Note.NOTE, "This is an (sharp ->#<- sharp) example. " - + "This message must NOT be ignored."); - } - - public void testPagerV30_Parse() { - mVerifier.initForImportTest(V30, R.raw.v30_comma_separated); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNodeWithOrder("VERSION", "3.0") - .addExpectedNodeWithOrder("N", Arrays.asList("F", "G", "M", "", "")) - .addExpectedNodeWithOrder("TEL", "6101231234@pagersample.com", - new TypeSet("WORK", "MSG", "PAGER")); - } - - public void testPagerV30() { - mVerifier.initForImportTest(V30, R.raw.v30_comma_separated); - ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); - elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "F") - .put(StructuredName.MIDDLE_NAME, "M") - .put(StructuredName.GIVEN_NAME, "G") - .put(StructuredName.DISPLAY_NAME, "G M F"); - elem.addExpected(Phone.CONTENT_ITEM_TYPE) - .put(Phone.TYPE, Phone.TYPE_PAGER) - .put(Phone.NUMBER, "6101231234@pagersample.com"); - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/VCardJapanizationTests.java b/core/tests/coretests/src/android/pim/vcard/VCardJapanizationTests.java deleted file mode 100644 index 17ee322..0000000 --- a/core/tests/coretests/src/android/pim/vcard/VCardJapanizationTests.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.pim.vcard; - -import android.content.ContentValues; -import android.pim.vcard.test_utils.ContactEntry; -import android.pim.vcard.test_utils.ContentValuesBuilder; -import android.pim.vcard.test_utils.PropertyNodesVerifierElem; -import android.pim.vcard.test_utils.PropertyNodesVerifierElem.TypeSet; -import android.provider.ContactsContract.CommonDataKinds.Nickname; -import android.provider.ContactsContract.CommonDataKinds.Note; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.StructuredName; -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; - -import java.util.Arrays; - -public class VCardJapanizationTests extends VCardTestsBase { - private void testNameUtf8Common(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "\u3075\u308B\u3069") - .put(StructuredName.GIVEN_NAME, "\u3091\u308A\u304B") - .put(StructuredName.MIDDLE_NAME, "B") - .put(StructuredName.PREFIX, "Dr.") - .put(StructuredName.SUFFIX, "Ph.D"); - ContentValues contentValues = - (VCardConfig.isV30(vcardType) ? null : mContentValuesForQPAndUtf8); - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNode("FN", "Dr. \u3075\u308B\u3069 B \u3091\u308A\u304B Ph.D", - contentValues) - .addExpectedNode("N", "\u3075\u308B\u3069;\u3091\u308A\u304B;B;Dr.;Ph.D", - Arrays.asList( - "\u3075\u308B\u3069", "\u3091\u308A\u304B", "B", "Dr.", "Ph.D"), - null, contentValues, null, null); - } - - public void testNameUtf8V21() { - testNameUtf8Common(VCardConfig.VCARD_TYPE_V21_JAPANESE); - } - - public void testNameUtf8V30() { - testNameUtf8Common(VCardConfig.VCARD_TYPE_V30_JAPANESE); - } - - public void testNameShiftJis() { - mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_V30_JAPANESE, "Shift_JIS"); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "\u3075\u308B\u3069") - .put(StructuredName.GIVEN_NAME, "\u3091\u308A\u304B") - .put(StructuredName.MIDDLE_NAME, "B") - .put(StructuredName.PREFIX, "Dr.") - .put(StructuredName.SUFFIX, "Ph.D"); - - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNode("FN", "Dr. \u3075\u308B\u3069 B \u3091\u308A\u304B Ph.D", - mContentValuesForSJis) - .addExpectedNode("N", "\u3075\u308B\u3069;\u3091\u308A\u304B;B;Dr.;Ph.D", - Arrays.asList( - "\u3075\u308B\u3069", "\u3091\u308A\u304B", "B", "Dr.", "Ph.D"), - null, mContentValuesForSJis, null, null); - } - - /** - * DoCoMo phones require all name elements should be in "family name" field. - */ - public void testNameDoCoMo() { - mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_DOCOMO, "Shift_JIS"); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.FAMILY_NAME, "\u3075\u308B\u3069") - .put(StructuredName.GIVEN_NAME, "\u3091\u308A\u304B") - .put(StructuredName.MIDDLE_NAME, "B") - .put(StructuredName.PREFIX, "Dr.") - .put(StructuredName.SUFFIX, "Ph.D"); - - final String fullName = "Dr. \u3075\u308B\u3069 B \u3091\u308A\u304B Ph.D"; - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNode("N", fullName + ";;;;", - Arrays.asList(fullName, "", "", "", ""), - null, mContentValuesForSJis, null, null) - .addExpectedNode("FN", fullName, mContentValuesForSJis) - .addExpectedNode("SOUND", ";;;;", new TypeSet("X-IRMC-N")) - .addExpectedNode("TEL", "", new TypeSet("HOME")) - .addExpectedNode("EMAIL", "", new TypeSet("HOME")) - .addExpectedNode("ADR", "", new TypeSet("HOME")) - .addExpectedNode("X-CLASS", "PUBLIC") - .addExpectedNode("X-REDUCTION", "") - .addExpectedNode("X-NO", "") - .addExpectedNode("X-DCM-HMN-MODE", ""); - } - - private void testPhoneticNameCommon(int vcardType, String charset) { - mVerifier.initForExportTest(vcardType, charset); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.PHONETIC_FAMILY_NAME, "\u3084\u307E\u3060") - .put(StructuredName.PHONETIC_MIDDLE_NAME, "\u30DF\u30C9\u30EB\u30CD\u30FC\u30E0") - .put(StructuredName.PHONETIC_GIVEN_NAME, "\u305F\u308D\u3046"); - - final ContentValues contentValues = - ("SHIFT_JIS".equalsIgnoreCase(charset) ? - (VCardConfig.isV30(vcardType) ? mContentValuesForSJis : - mContentValuesForQPAndSJis) : - (VCardConfig.isV30(vcardType) ? null : mContentValuesForQPAndUtf8)); - PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElemWithEmptyName(); - elem.addExpectedNode("X-PHONETIC-LAST-NAME", "\u3084\u307E\u3060", - contentValues) - .addExpectedNode("X-PHONETIC-MIDDLE-NAME", - "\u30DF\u30C9\u30EB\u30CD\u30FC\u30E0", - contentValues) - .addExpectedNode("X-PHONETIC-FIRST-NAME", "\u305F\u308D\u3046", - contentValues); - if (VCardConfig.isV30(vcardType)) { - elem.addExpectedNode("SORT-STRING", - "\u3084\u307E\u3060 \u30DF\u30C9\u30EB\u30CD\u30FC\u30E0 \u305F\u308D\u3046", - contentValues); - } - ContentValuesBuilder builder = mVerifier.addContentValuesVerifierElem() - .addExpected(StructuredName.CONTENT_ITEM_TYPE); - builder.put(StructuredName.PHONETIC_FAMILY_NAME, "\u3084\u307E\u3060") - .put(StructuredName.PHONETIC_MIDDLE_NAME, "\u30DF\u30C9\u30EB\u30CD\u30FC\u30E0") - .put(StructuredName.PHONETIC_GIVEN_NAME, "\u305F\u308D\u3046") - .put(StructuredName.DISPLAY_NAME, - "\u3084\u307E\u3060 \u30DF\u30C9\u30EB\u30CD\u30FC\u30E0 " + - "\u305F\u308D\u3046"); - } - - public void testPhoneticNameForJapaneseV21Utf8() { - testPhoneticNameCommon(VCardConfig.VCARD_TYPE_V21_JAPANESE, null); - } - - public void testPhoneticNameForJapaneseV21Sjis() { - testPhoneticNameCommon(VCardConfig.VCARD_TYPE_V21_JAPANESE, "Shift_JIS"); - } - - public void testPhoneticNameForJapaneseV30Utf8() { - testPhoneticNameCommon(VCardConfig.VCARD_TYPE_V30_JAPANESE, null); - } - - public void testPhoneticNameForJapaneseV30SJis() { - testPhoneticNameCommon(VCardConfig.VCARD_TYPE_V30_JAPANESE, "Shift_JIS"); - } - - public void testPhoneticNameForMobileV21_1() { - mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_V21_JAPANESE_MOBILE, "Shift_JIS"); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.PHONETIC_FAMILY_NAME, "\u3084\u307E\u3060") - .put(StructuredName.PHONETIC_MIDDLE_NAME, "\u30DF\u30C9\u30EB\u30CD\u30FC\u30E0") - .put(StructuredName.PHONETIC_GIVEN_NAME, "\u305F\u308D\u3046"); - - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNode("SOUND", - "\uFF94\uFF8F\uFF80\uFF9E \uFF90\uFF84\uFF9E\uFF99\uFF88\uFF70\uFF91 " + - "\uFF80\uFF9B\uFF73;;;;", - mContentValuesForSJis, new TypeSet("X-IRMC-N")); - ContentValuesBuilder builder = mVerifier.addContentValuesVerifierElem() - .addExpected(StructuredName.CONTENT_ITEM_TYPE); - builder.put(StructuredName.PHONETIC_FAMILY_NAME, "\uFF94\uFF8F\uFF80\uFF9E") - .put(StructuredName.PHONETIC_MIDDLE_NAME, - "\uFF90\uFF84\uFF9E\uFF99\uFF88\uFF70\uFF91") - .put(StructuredName.PHONETIC_GIVEN_NAME, "\uFF80\uFF9B\uFF73") - .put(StructuredName.DISPLAY_NAME, - "\uFF94\uFF8F\uFF80\uFF9E \uFF90\uFF84\uFF9E\uFF99\uFF88\uFF70\uFF91 " + - "\uFF80\uFF9B\uFF73"); - } - - public void testPhoneticNameForMobileV21_2() { - mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_V21_JAPANESE_MOBILE, "Shift_JIS"); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE) - .put(StructuredName.PHONETIC_FAMILY_NAME, "\u3084\u307E\u3060") - .put(StructuredName.PHONETIC_GIVEN_NAME, "\u305F\u308D\u3046"); - - mVerifier.addPropertyNodesVerifierElem() - .addExpectedNode("SOUND", "\uFF94\uFF8F\uFF80\uFF9E \uFF80\uFF9B\uFF73;;;;", - mContentValuesForSJis, new TypeSet("X-IRMC-N")); - ContentValuesBuilder builder = mVerifier.addContentValuesVerifierElem() - .addExpected(StructuredName.CONTENT_ITEM_TYPE); - builder.put(StructuredName.PHONETIC_FAMILY_NAME, "\uFF94\uFF8F\uFF80\uFF9E") - .put(StructuredName.PHONETIC_GIVEN_NAME, "\uFF80\uFF9B\uFF73") - .put(StructuredName.DISPLAY_NAME, "\uFF94\uFF8F\uFF80\uFF9E \uFF80\uFF9B\uFF73"); - } - - private void testPostalAddressWithJapaneseCommon(int vcardType, String charset) { - mVerifier.initForExportTest(vcardType, charset); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.POBOX, "\u79C1\u66F8\u7BB107") - .put(StructuredPostal.STREET, "\u96DB\u898B\u6CA2\u6751") - .put(StructuredPostal.CITY, "\u9E7F\u9AA8\u5E02") - .put(StructuredPostal.REGION, "\u00D7\u00D7\u770C") - .put(StructuredPostal.POSTCODE, "494-1313") - .put(StructuredPostal.COUNTRY, "\u65E5\u672C") - .put(StructuredPostal.FORMATTED_ADDRESS, - "\u3053\u3093\u306A\u3068\u3053\u308D\u3092\u898B" - + "\u308B\u306A\u3093\u3066\u6687\u4EBA\u3067\u3059\u304B\uFF1F") - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM) - .put(StructuredPostal.LABEL, "\u304A\u3082\u3061\u304B\u3048\u308A"); - - ContentValues contentValues = ("UTF-8".equalsIgnoreCase(charset) ? - (VCardConfig.isV30(vcardType) ? mContentValuesForSJis : - mContentValuesForQPAndSJis) : - (VCardConfig.isV30(vcardType) ? mContentValuesForUtf8 : - mContentValuesForQPAndUtf8)); - - PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElemWithEmptyName(); - // LABEL must be ignored in vCard 2.1. As for vCard 3.0, the current behavior is - // same as that in vCard 3.0, which can be changed in the future. - elem.addExpectedNode("ADR", Arrays.asList("\u79C1\u66F8\u7BB107", - "", "\u96DB\u898B\u6CA2\u6751", "\u9E7F\u9AA8\u5E02", "\u00D7\u00D7\u770C", - "494-1313", "\u65E5\u672C"), - contentValues); - mVerifier.addContentValuesVerifierElem().addExpected(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.POBOX, "\u79C1\u66F8\u7BB107") - .put(StructuredPostal.STREET, "\u96DB\u898B\u6CA2\u6751") - .put(StructuredPostal.CITY, "\u9E7F\u9AA8\u5E02") - .put(StructuredPostal.REGION, "\u00D7\u00D7\u770C") - .put(StructuredPostal.POSTCODE, "494-1313") - .put(StructuredPostal.COUNTRY, "\u65E5\u672C") - .put(StructuredPostal.FORMATTED_ADDRESS, - "\u65E5\u672C 494-1313 \u00D7\u00D7\u770C \u9E7F\u9AA8\u5E02 " + - "\u96DB\u898B\u6CA2\u6751 " + "\u79C1\u66F8\u7BB107") - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME); - } - public void testPostalAddresswithJapaneseV21() { - testPostalAddressWithJapaneseCommon(VCardConfig.VCARD_TYPE_V21_JAPANESE, "Shift_JIS"); - } - - /** - * Verifies that only one address field is emitted toward DoCoMo phones. - * Prefered type must (should?) be: HOME > WORK > OTHER > CUSTOM - */ - public void testPostalAdrressForDoCoMo_1() { - mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_DOCOMO, "Shift_JIS"); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK) - .put(StructuredPostal.POBOX, "1"); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_OTHER) - .put(StructuredPostal.POBOX, "2"); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME) - .put(StructuredPostal.POBOX, "3"); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM) - .put(StructuredPostal.LABEL, "custom") - .put(StructuredPostal.POBOX, "4"); - - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("TEL", "", new TypeSet("HOME")) - .addExpectedNode("EMAIL", "", new TypeSet("HOME")) - .addExpectedNode("X-CLASS", "PUBLIC") - .addExpectedNode("X-REDUCTION", "") - .addExpectedNode("X-NO", "") - .addExpectedNode("X-DCM-HMN-MODE", "") - .addExpectedNode("ADR", - Arrays.asList("3", "", "", "", "", "", ""), new TypeSet("HOME")); - } - - public void testPostalAdrressForDoCoMo_2() { - mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_DOCOMO, "Shift_JIS"); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_OTHER) - .put(StructuredPostal.POBOX, "1"); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK) - .put(StructuredPostal.POBOX, "2"); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM) - .put(StructuredPostal.LABEL, "custom") - .put(StructuredPostal.POBOX, "3"); - - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("TEL", "", new TypeSet("HOME")) - .addExpectedNode("EMAIL", "", new TypeSet("HOME")) - .addExpectedNode("X-CLASS", "PUBLIC") - .addExpectedNode("X-REDUCTION", "") - .addExpectedNode("X-NO", "") - .addExpectedNode("X-DCM-HMN-MODE", "") - .addExpectedNode("ADR", - Arrays.asList("2", "", "", "", "", "", ""), new TypeSet("WORK")); - } - - public void testPostalAdrressForDoCoMo_3() { - mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_DOCOMO, "Shift_JIS"); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM) - .put(StructuredPostal.LABEL, "custom1") - .put(StructuredPostal.POBOX, "1"); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_OTHER) - .put(StructuredPostal.POBOX, "2"); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM) - .put(StructuredPostal.LABEL, "custom2") - .put(StructuredPostal.POBOX, "3"); - - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("TEL", "", new TypeSet("HOME")) - .addExpectedNode("EMAIL", "", new TypeSet("HOME")) - .addExpectedNode("X-CLASS", "PUBLIC") - .addExpectedNode("X-REDUCTION", "") - .addExpectedNode("X-NO", "") - .addExpectedNode("X-DCM-HMN-MODE", "") - .addExpectedNode("ADR", Arrays.asList("2", "", "", "", "", "", "")); - } - - /** - * Verifies the vCard exporter tolerates null TYPE. - */ - public void testPostalAdrressForDoCoMo_4() { - mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_DOCOMO, "Shift_JIS"); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.POBOX, "1"); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_OTHER) - .put(StructuredPostal.POBOX, "2"); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME) - .put(StructuredPostal.POBOX, "3"); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK) - .put(StructuredPostal.POBOX, "4"); - entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) - .put(StructuredPostal.POBOX, "5"); - - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("TEL", "", new TypeSet("HOME")) - .addExpectedNode("EMAIL", "", new TypeSet("HOME")) - .addExpectedNode("X-CLASS", "PUBLIC") - .addExpectedNode("X-REDUCTION", "") - .addExpectedNode("X-NO", "") - .addExpectedNode("X-DCM-HMN-MODE", "") - .addExpectedNode("ADR", - Arrays.asList("3", "", "", "", "", "", ""), new TypeSet("HOME")); - } - - private void testJapanesePhoneNumberCommon(int vcardType) { - mVerifier.initForExportTest(vcardType); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "0312341234") - .put(Phone.TYPE, Phone.TYPE_HOME); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "09012341234") - .put(Phone.TYPE, Phone.TYPE_MOBILE); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("TEL", "03-1234-1234", new TypeSet("HOME")) - .addExpectedNode("TEL", "090-1234-1234", new TypeSet("CELL")); - } - - public void testJapanesePhoneNumberV21_1() { - testJapanesePhoneNumberCommon(VCardConfig.VCARD_TYPE_V21_JAPANESE); - } - - public void testJapanesePhoneNumberV30() { - testJapanesePhoneNumberCommon(VCardConfig.VCARD_TYPE_V30_JAPANESE); - } - - public void testJapanesePhoneNumberDoCoMo() { - mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_DOCOMO, "Shift_JIS"); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "0312341234") - .put(Phone.TYPE, Phone.TYPE_HOME); - entry.addContentValues(Phone.CONTENT_ITEM_TYPE) - .put(Phone.NUMBER, "09012341234") - .put(Phone.TYPE, Phone.TYPE_MOBILE); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("EMAIL", "", new TypeSet("HOME")) - .addExpectedNode("X-CLASS", "PUBLIC") - .addExpectedNode("X-REDUCTION", "") - .addExpectedNode("X-NO", "") - .addExpectedNode("X-DCM-HMN-MODE", "") - .addExpectedNode("ADR", "", new TypeSet("HOME")) - .addExpectedNode("TEL", "03-1234-1234", new TypeSet("HOME")) - .addExpectedNode("TEL", "090-1234-1234", new TypeSet("CELL")); - } - - public void testNoteDoCoMo() { - mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_DOCOMO, "Shift_JIS"); - ContactEntry entry = mVerifier.addInputEntry(); - entry.addContentValues(Note.CONTENT_ITEM_TYPE) - .put(Note.NOTE, "note1"); - entry.addContentValues(Note.CONTENT_ITEM_TYPE) - .put(Note.NOTE, "note2"); - entry.addContentValues(Note.CONTENT_ITEM_TYPE) - .put(Note.NOTE, "note3"); - - // More than one note fields must be aggregated into one note. - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("TEL", "", new TypeSet("HOME")) - .addExpectedNode("EMAIL", "", new TypeSet("HOME")) - .addExpectedNode("X-CLASS", "PUBLIC") - .addExpectedNode("X-REDUCTION", "") - .addExpectedNode("X-NO", "") - .addExpectedNode("X-DCM-HMN-MODE", "") - .addExpectedNode("ADR", "", new TypeSet("HOME")) - .addExpectedNode("NOTE", "note1\nnote2\nnote3", mContentValuesForQP); - } - - public void testAndroidCustomV21() { - mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_V21_GENERIC); - mVerifier.addInputEntry().addContentValues(Nickname.CONTENT_ITEM_TYPE) - .put(Nickname.NAME, "\u304D\u3083\u30FC\u30A8\u30C3\u30C1\u30FC"); - mVerifier.addPropertyNodesVerifierElemWithEmptyName() - .addExpectedNode("X-ANDROID-CUSTOM", - Arrays.asList(Nickname.CONTENT_ITEM_TYPE, - "\u304D\u3083\u30FC\u30A8\u30C3\u30C1\u30FC", - "", "", "", "", "", "", "", "", "", "", "", "", "", ""), - mContentValuesForQPAndUtf8); - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/VCardTestsBase.java b/core/tests/coretests/src/android/pim/vcard/VCardTestsBase.java deleted file mode 100644 index 383a9af..0000000 --- a/core/tests/coretests/src/android/pim/vcard/VCardTestsBase.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.pim.vcard; - -import android.content.ContentValues; -import android.pim.vcard.test_utils.VCardVerifier; -import android.test.AndroidTestCase; - -/** - * BaseClass for vCard unit tests with utility classes. - * Please do not add each unit test here. - */ -/* package */ class VCardTestsBase extends AndroidTestCase { - public static final int V21 = VCardConfig.VCARD_TYPE_V21_GENERIC; - public static final int V30 = VCardConfig.VCARD_TYPE_V30_GENERIC; - - // Do not modify these during tests. - protected final ContentValues mContentValuesForQP; - protected final ContentValues mContentValuesForSJis; - protected final ContentValues mContentValuesForUtf8; - protected final ContentValues mContentValuesForQPAndSJis; - protected final ContentValues mContentValuesForQPAndUtf8; - protected final ContentValues mContentValuesForBase64V21; - protected final ContentValues mContentValuesForBase64V30; - - protected VCardVerifier mVerifier; - private boolean mSkipVerification; - - public VCardTestsBase() { - super(); - // Not using constants in vCard code since it may be wrong. - mContentValuesForQP = new ContentValues(); - mContentValuesForQP.put("ENCODING", "QUOTED-PRINTABLE"); - mContentValuesForSJis = new ContentValues(); - mContentValuesForSJis.put("CHARSET", "SHIFT_JIS"); - mContentValuesForUtf8 = new ContentValues(); - mContentValuesForUtf8.put("CHARSET", "UTF-8"); - mContentValuesForQPAndSJis = new ContentValues(); - mContentValuesForQPAndSJis.put("ENCODING", "QUOTED-PRINTABLE"); - mContentValuesForQPAndSJis.put("CHARSET", "SHIFT_JIS"); - mContentValuesForQPAndUtf8 = new ContentValues(); - mContentValuesForQPAndUtf8.put("ENCODING", "QUOTED-PRINTABLE"); - mContentValuesForQPAndUtf8.put("CHARSET", "UTF-8"); - mContentValuesForBase64V21 = new ContentValues(); - mContentValuesForBase64V21.put("ENCODING", "BASE64"); - mContentValuesForBase64V30 = new ContentValues(); - mContentValuesForBase64V30.put("ENCODING", "b"); - } - - @Override - public void testAndroidTestCaseSetupProperly() { - super.testAndroidTestCaseSetupProperly(); - mSkipVerification = true; - } - - @Override - public void setUp() throws Exception{ - super.setUp(); - mVerifier = new VCardVerifier(this); - mSkipVerification = false; - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - if (!mSkipVerification) { - mVerifier.verify(); - } - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/VCardUtilsTests.java b/core/tests/coretests/src/android/pim/vcard/VCardUtilsTests.java deleted file mode 100644 index 59299f9..0000000 --- a/core/tests/coretests/src/android/pim/vcard/VCardUtilsTests.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.pim.vcard; - -import android.pim.vcard.VCardUtils; - -import junit.framework.TestCase; - -import java.util.List; - -public class VCardUtilsTests extends TestCase { - public void testContainsOnlyPrintableAscii() { - assertTrue(VCardUtils.containsOnlyPrintableAscii((String)null)); - assertTrue(VCardUtils.containsOnlyPrintableAscii((String[])null)); - assertTrue(VCardUtils.containsOnlyPrintableAscii((List<String>)null)); - assertTrue(VCardUtils.containsOnlyPrintableAscii("")); - assertTrue(VCardUtils.containsOnlyPrintableAscii("abcdefghijklmnopqrstuvwxyz")); - assertTrue(VCardUtils.containsOnlyPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); - StringBuilder builder = new StringBuilder(); - for (int i = 0x20; i < 0x7F; i++) { - builder.append((char)i); - } - assertTrue(VCardUtils.containsOnlyPrintableAscii(builder.toString())); - assertTrue(VCardUtils.containsOnlyPrintableAscii("\r\n")); - assertFalse(VCardUtils.containsOnlyPrintableAscii("\u0019")); - assertFalse(VCardUtils.containsOnlyPrintableAscii("\u007F")); - } - - public void testContainsOnlyNonCrLfPrintableAscii() { - assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii((String)null)); - assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii((String[])null)); - assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii((List<String>)null)); - assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("")); - assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("abcdefghijklmnopqrstuvwxyz")); - assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); - StringBuilder builder = new StringBuilder(); - for (int i = 0x20; i < 0x7F; i++) { - builder.append((char)i); - } - assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii(builder.toString())); - assertFalse(VCardUtils.containsOnlyNonCrLfPrintableAscii("\u0019")); - assertFalse(VCardUtils.containsOnlyNonCrLfPrintableAscii("\u007F")); - assertFalse(VCardUtils.containsOnlyNonCrLfPrintableAscii("\r")); - assertFalse(VCardUtils.containsOnlyNonCrLfPrintableAscii("\n")); - } - - public void testContainsOnlyAlphaDigitHyphen() { - assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen((String)null)); - assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen((String[])null)); - assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen((List<String>)null)); - assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen("")); - assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("abcdefghijklmnopqrstuvwxyz")); - assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); - assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("0123456789-")); - for (int i = 0; i < 0x30; i++) { - if (i == 0x2D) { // - - continue; - } - assertFalse(VCardUtils.containsOnlyAlphaDigitHyphen(String.valueOf((char)i))); - } - for (int i = 0x3A; i < 0x41; i++) { - assertFalse(VCardUtils.containsOnlyAlphaDigitHyphen(String.valueOf((char)i))); - } - for (int i = 0x5B; i < 0x61; i++) { - assertFalse(VCardUtils.containsOnlyAlphaDigitHyphen(String.valueOf((char)i))); - } - for (int i = 0x7B; i < 0x100; i++) { - assertFalse(VCardUtils.containsOnlyAlphaDigitHyphen(String.valueOf((char)i))); - } - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/ContactEntry.java b/core/tests/coretests/src/android/pim/vcard/test_utils/ContactEntry.java deleted file mode 100644 index 843750e..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/ContactEntry.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android.pim.vcard.test_utils; - -import android.content.ContentValues; -import android.provider.ContactsContract.Data; - -import java.util.ArrayList; -import java.util.List; - -/** - * <p> - * The class representing one contact, which should contain multiple ContentValues like - * StructuredName, Email, etc. - * </p> - */ -public final class ContactEntry { - private final List<ContentValues> mContentValuesList = new ArrayList<ContentValues>(); - - public ContentValuesBuilder addContentValues(String mimeType) { - ContentValues contentValues = new ContentValues(); - contentValues.put(Data.MIMETYPE, mimeType); - mContentValuesList.add(contentValues); - return new ContentValuesBuilder(contentValues); - } - - public List<ContentValues> getList() { - return mContentValuesList; - } -}
\ No newline at end of file diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesBuilder.java b/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesBuilder.java deleted file mode 100644 index 5c24186..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesBuilder.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.test_utils; - -import android.content.ContentValues; - -/** - * ContentValues-like class which enables users to chain put() methods and restricts - * the other methods. - */ -public class ContentValuesBuilder { - private final ContentValues mContentValues; - - public ContentValuesBuilder(final ContentValues contentValues) { - mContentValues = contentValues; - } - - public ContentValuesBuilder put(String key, String value) { - mContentValues.put(key, value); - return this; - } - - public ContentValuesBuilder put(String key, Byte value) { - mContentValues.put(key, value); - return this; - } - - public ContentValuesBuilder put(String key, Short value) { - mContentValues.put(key, value); - return this; - } - - public ContentValuesBuilder put(String key, Integer value) { - mContentValues.put(key, value); - return this; - } - - public ContentValuesBuilder put(String key, Long value) { - mContentValues.put(key, value); - return this; - } - - public ContentValuesBuilder put(String key, Float value) { - mContentValues.put(key, value); - return this; - } - - public ContentValuesBuilder put(String key, Double value) { - mContentValues.put(key, value); - return this; - } - - public ContentValuesBuilder put(String key, Boolean value) { - mContentValues.put(key, value); - return this; - } - - public ContentValuesBuilder put(String key, byte[] value) { - mContentValues.put(key, value); - return this; - } - - public ContentValuesBuilder putNull(String key) { - mContentValues.putNull(key); - return this; - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifier.java b/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifier.java deleted file mode 100644 index f2516ed..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifier.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.test_utils; - -import android.pim.vcard.VCardConfig; -import android.pim.vcard.VCardEntry; -import android.pim.vcard.VCardEntryConstructor; -import android.pim.vcard.VCardEntryHandler; -import android.pim.vcard.VCardParser; -import android.pim.vcard.VCardParser_V21; -import android.pim.vcard.VCardParser_V30; -import android.pim.vcard.exception.VCardException; -import android.test.AndroidTestCase; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -public class ContentValuesVerifier implements VCardEntryHandler { - private AndroidTestCase mTestCase; - private List<ContentValuesVerifierElem> mContentValuesVerifierElemList = - new ArrayList<ContentValuesVerifierElem>(); - private int mIndex; - - public ContentValuesVerifierElem addElem(AndroidTestCase androidTestCase) { - mTestCase = androidTestCase; - ContentValuesVerifierElem importVerifier = new ContentValuesVerifierElem(androidTestCase); - mContentValuesVerifierElemList.add(importVerifier); - return importVerifier; - } - - public void verify(int resId, int vCardType) throws IOException, VCardException { - verify(mTestCase.getContext().getResources().openRawResource(resId), vCardType); - } - - public void verify(int resId, int vCardType, final VCardParser vCardParser) - throws IOException, VCardException { - verify(mTestCase.getContext().getResources().openRawResource(resId), - vCardType, vCardParser); - } - - public void verify(InputStream is, int vCardType) throws IOException, VCardException { - final VCardParser vCardParser; - if (VCardConfig.isV30(vCardType)) { - vCardParser = new VCardParser_V30(); - } else { - vCardParser = new VCardParser_V21(); - } - verify(is, vCardType, vCardParser); - } - - public void verify(InputStream is, int vCardType, final VCardParser vCardParser) - throws IOException, VCardException { - VCardEntryConstructor builder = - new VCardEntryConstructor(vCardType, null, null, false); - builder.addEntryHandler(this); - try { - vCardParser.parse(is, builder); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - } - } - } - } - - public void onStart() { - for (ContentValuesVerifierElem elem : mContentValuesVerifierElemList) { - elem.onParsingStart(); - } - } - - public void onEntryCreated(VCardEntry entry) { - mTestCase.assertTrue(mIndex < mContentValuesVerifierElemList.size()); - mContentValuesVerifierElemList.get(mIndex).onEntryCreated(entry); - mIndex++; - } - - public void onEnd() { - for (ContentValuesVerifierElem elem : mContentValuesVerifierElemList) { - elem.onParsingEnd(); - elem.verifyResolver(); - } - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifierElem.java b/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifierElem.java deleted file mode 100644 index 66d69b3..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/ContentValuesVerifierElem.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.test_utils; - -import android.content.ContentValues; -import android.pim.vcard.VCardConfig; -import android.pim.vcard.VCardEntry; -import android.pim.vcard.VCardEntryCommitter; -import android.pim.vcard.VCardEntryConstructor; -import android.pim.vcard.VCardEntryHandler; -import android.pim.vcard.VCardParser; -import android.pim.vcard.VCardParser_V21; -import android.pim.vcard.VCardParser_V30; -import android.pim.vcard.exception.VCardException; -import android.provider.ContactsContract.Data; -import android.test.AndroidTestCase; - -import java.io.IOException; -import java.io.InputStream; - -public class ContentValuesVerifierElem { - private final AndroidTestCase mTestCase; - private final ImportTestResolver mResolver; - private final VCardEntryHandler mHandler; - - public ContentValuesVerifierElem(AndroidTestCase androidTestCase) { - mTestCase = androidTestCase; - mResolver = new ImportTestResolver(androidTestCase); - mHandler = new VCardEntryCommitter(mResolver); - } - - public ContentValuesBuilder addExpected(String mimeType) { - ContentValues contentValues = new ContentValues(); - contentValues.put(Data.MIMETYPE, mimeType); - mResolver.addExpectedContentValues(contentValues); - return new ContentValuesBuilder(contentValues); - } - - public void verify(int resId, int vCardType) - throws IOException, VCardException { - verify(mTestCase.getContext().getResources().openRawResource(resId), vCardType); - } - - public void verify(InputStream is, int vCardType) throws IOException, VCardException { - final VCardParser vCardParser; - if (VCardConfig.isV30(vCardType)) { - vCardParser = new VCardParser_V30(); - } else { - vCardParser = new VCardParser_V21(); - } - VCardEntryConstructor builder = - new VCardEntryConstructor(vCardType, null, null, false); - builder.addEntryHandler(mHandler); - try { - vCardParser.parse(is, builder); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - } - } - } - verifyResolver(); - } - - public void verifyResolver() { - mResolver.verify(); - } - - public void onParsingStart() { - mHandler.onStart(); - } - - public void onEntryCreated(VCardEntry entry) { - mHandler.onEntryCreated(entry); - } - - public void onParsingEnd() { - mHandler.onEnd(); - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/ExportTestProvider.java b/core/tests/coretests/src/android/pim/vcard/test_utils/ExportTestProvider.java deleted file mode 100644 index 0fbd9bb..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/ExportTestProvider.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android.pim.vcard.test_utils; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Entity; -import android.content.EntityIterator; -import android.database.Cursor; -import android.net.Uri; -import android.pim.vcard.VCardComposer; -import android.provider.ContactsContract.Contacts; -import android.provider.ContactsContract.Data; -import android.provider.ContactsContract.RawContacts; -import android.test.mock.MockContentProvider; -import android.test.mock.MockCursor; - -import junit.framework.TestCase; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/* package */ class ExportTestProvider extends MockContentProvider { - final private TestCase mTestCase; - final private ArrayList<ContactEntry> mContactEntryList = new ArrayList<ContactEntry>(); - - private static class MockEntityIterator implements EntityIterator { - List<Entity> mEntityList; - Iterator<Entity> mIterator; - - public MockEntityIterator(List<ContentValues> contentValuesList) { - mEntityList = new ArrayList<Entity>(); - Entity entity = new Entity(new ContentValues()); - for (ContentValues contentValues : contentValuesList) { - entity.addSubValue(Data.CONTENT_URI, contentValues); - } - mEntityList.add(entity); - mIterator = mEntityList.iterator(); - } - - public boolean hasNext() { - return mIterator.hasNext(); - } - - public Entity next() { - return mIterator.next(); - } - - public void remove() { - throw new UnsupportedOperationException("remove not supported"); - } - - public void reset() { - mIterator = mEntityList.iterator(); - } - - public void close() { - } - } - - public ExportTestProvider(TestCase testCase) { - mTestCase = testCase; - } - - public ContactEntry buildInputEntry() { - ContactEntry contactEntry = new ContactEntry(); - mContactEntryList.add(contactEntry); - return contactEntry; - } - - /** - * <p> - * An old method which had existed but was removed from ContentResolver. - * </p> - * <p> - * We still keep using this method since we don't have a propeer way to know - * which value in the ContentValue corresponds to the entry in Contacts database. - * </p> - */ - public EntityIterator queryEntities(Uri uri, - String selection, String[] selectionArgs, String sortOrder) { - mTestCase.assertTrue(uri != null); - mTestCase.assertTrue(ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())); - final String authority = uri.getAuthority(); - mTestCase.assertTrue(RawContacts.CONTENT_URI.getAuthority().equals(authority)); - mTestCase.assertTrue((Data.CONTACT_ID + "=?").equals(selection)); - mTestCase.assertEquals(1, selectionArgs.length); - final int id = Integer.parseInt(selectionArgs[0]); - mTestCase.assertTrue(id >= 0 && id < mContactEntryList.size()); - - return new MockEntityIterator(mContactEntryList.get(id).getList()); - } - - @Override - public Cursor query(Uri uri,String[] projection, - String selection, String[] selectionArgs, String sortOrder) { - mTestCase.assertTrue(VCardComposer.CONTACTS_TEST_CONTENT_URI.equals(uri)); - // In this test, following arguments are not supported. - mTestCase.assertNull(selection); - mTestCase.assertNull(selectionArgs); - mTestCase.assertNull(sortOrder); - - return new MockCursor() { - int mCurrentPosition = -1; - - @Override - public int getCount() { - return mContactEntryList.size(); - } - - @Override - public boolean moveToFirst() { - mCurrentPosition = 0; - return true; - } - - @Override - public boolean moveToNext() { - if (mCurrentPosition < mContactEntryList.size()) { - mCurrentPosition++; - return true; - } else { - return false; - } - } - - @Override - public boolean isBeforeFirst() { - return mCurrentPosition < 0; - } - - @Override - public boolean isAfterLast() { - return mCurrentPosition >= mContactEntryList.size(); - } - - @Override - public int getColumnIndex(String columnName) { - mTestCase.assertEquals(Contacts._ID, columnName); - return 0; - } - - @Override - public int getInt(int columnIndex) { - mTestCase.assertEquals(0, columnIndex); - mTestCase.assertTrue(mCurrentPosition >= 0 - && mCurrentPosition < mContactEntryList.size()); - return mCurrentPosition; - } - - @Override - public String getString(int columnIndex) { - return String.valueOf(getInt(columnIndex)); - } - - @Override - public void close() { - } - }; - } -}
\ No newline at end of file diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/ExportTestResolver.java b/core/tests/coretests/src/android/pim/vcard/test_utils/ExportTestResolver.java deleted file mode 100644 index 97e1e38..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/ExportTestResolver.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android.pim.vcard.test_utils; - -import android.pim.vcard.VCardComposer; -import android.provider.ContactsContract.RawContacts; -import android.test.mock.MockContentResolver; - -import junit.framework.TestCase; - -/* package */ class ExportTestResolver extends MockContentResolver { - private final ExportTestProvider mProvider; - public ExportTestResolver(TestCase testCase) { - mProvider = new ExportTestProvider(testCase); - addProvider(VCardComposer.VCARD_TEST_AUTHORITY, mProvider); - addProvider(RawContacts.CONTENT_URI.getAuthority(), mProvider); - } - - public ContactEntry addInputContactEntry() { - return mProvider.buildInputEntry(); - } - - public ExportTestProvider getProvider() { - return mProvider; - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/ImportTestProvider.java b/core/tests/coretests/src/android/pim/vcard/test_utils/ImportTestProvider.java deleted file mode 100644 index ffbf95d..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/ImportTestProvider.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.test_utils; - -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; -import android.content.ContentValues; -import android.net.Uri; -import android.provider.ContactsContract.Data; -import android.provider.ContactsContract.RawContacts; -import android.provider.ContactsContract.CommonDataKinds.Email; -import android.provider.ContactsContract.CommonDataKinds.Event; -import android.provider.ContactsContract.CommonDataKinds.GroupMembership; -import android.provider.ContactsContract.CommonDataKinds.Im; -import android.provider.ContactsContract.CommonDataKinds.Nickname; -import android.provider.ContactsContract.CommonDataKinds.Note; -import android.provider.ContactsContract.CommonDataKinds.Organization; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.Photo; -import android.provider.ContactsContract.CommonDataKinds.Relation; -import android.provider.ContactsContract.CommonDataKinds.StructuredName; -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; -import android.provider.ContactsContract.CommonDataKinds.Website; -import android.test.mock.MockContentProvider; -import android.text.TextUtils; - -import junit.framework.TestCase; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.Map.Entry; - -/* package */ class ImportTestProvider extends MockContentProvider { - private static final Set<String> sKnownMimeTypeSet = - new HashSet<String>(Arrays.asList(StructuredName.CONTENT_ITEM_TYPE, - Nickname.CONTENT_ITEM_TYPE, Phone.CONTENT_ITEM_TYPE, - Email.CONTENT_ITEM_TYPE, StructuredPostal.CONTENT_ITEM_TYPE, - Im.CONTENT_ITEM_TYPE, Organization.CONTENT_ITEM_TYPE, - Event.CONTENT_ITEM_TYPE, Photo.CONTENT_ITEM_TYPE, - Note.CONTENT_ITEM_TYPE, Website.CONTENT_ITEM_TYPE, - Relation.CONTENT_ITEM_TYPE, Event.CONTENT_ITEM_TYPE, - GroupMembership.CONTENT_ITEM_TYPE)); - - final Map<String, Collection<ContentValues>> mMimeTypeToExpectedContentValues; - - private final TestCase mTestCase; - - public ImportTestProvider(TestCase testCase) { - mTestCase = testCase; - mMimeTypeToExpectedContentValues = - new HashMap<String, Collection<ContentValues>>(); - for (String acceptanbleMimeType : sKnownMimeTypeSet) { - // Do not use HashSet since the current implementation changes the content of - // ContentValues after the insertion, which make the result of hashCode() - // changes... - mMimeTypeToExpectedContentValues.put( - acceptanbleMimeType, new ArrayList<ContentValues>()); - } - } - - public void addExpectedContentValues(ContentValues expectedContentValues) { - final String mimeType = expectedContentValues.getAsString(Data.MIMETYPE); - if (!sKnownMimeTypeSet.contains(mimeType)) { - mTestCase.fail(String.format( - "Unknow MimeType %s in the test code. Test code should be broken.", - mimeType)); - } - - final Collection<ContentValues> contentValuesCollection = - mMimeTypeToExpectedContentValues.get(mimeType); - contentValuesCollection.add(expectedContentValues); - } - - @Override - public ContentProviderResult[] applyBatch( - ArrayList<ContentProviderOperation> operations) { - if (operations == null) { - mTestCase.fail("There is no operation."); - } - - final int size = operations.size(); - ContentProviderResult[] fakeResultArray = new ContentProviderResult[size]; - for (int i = 0; i < size; i++) { - Uri uri = Uri.withAppendedPath(RawContacts.CONTENT_URI, String.valueOf(i)); - fakeResultArray[i] = new ContentProviderResult(uri); - } - - for (int i = 0; i < size; i++) { - ContentProviderOperation operation = operations.get(i); - ContentValues contentValues = operation.resolveValueBackReferences( - fakeResultArray, i); - } - for (int i = 0; i < size; i++) { - ContentProviderOperation operation = operations.get(i); - ContentValues actualContentValues = operation.resolveValueBackReferences( - fakeResultArray, i); - final Uri uri = operation.getUri(); - if (uri.equals(RawContacts.CONTENT_URI)) { - mTestCase.assertNull(actualContentValues.get(RawContacts.ACCOUNT_NAME)); - mTestCase.assertNull(actualContentValues.get(RawContacts.ACCOUNT_TYPE)); - } else if (uri.equals(Data.CONTENT_URI)) { - final String mimeType = actualContentValues.getAsString(Data.MIMETYPE); - if (!sKnownMimeTypeSet.contains(mimeType)) { - mTestCase.fail(String.format( - "Unknown MimeType %s. Probably added after developing this test", - mimeType)); - } - // Remove data meaningless in this unit tests. - // Specifically, Data.DATA1 - DATA7 are set to null or empty String - // regardless of the input, but it may change depending on how - // resolver-related code handles it. - // Here, we ignore these implementation-dependent specs and - // just check whether vCard importer correctly inserts rellevent data. - Set<String> keyToBeRemoved = new HashSet<String>(); - for (Entry<String, Object> entry : actualContentValues.valueSet()) { - Object value = entry.getValue(); - if (value == null || TextUtils.isEmpty(value.toString())) { - keyToBeRemoved.add(entry.getKey()); - } - } - for (String key: keyToBeRemoved) { - actualContentValues.remove(key); - } - /* for testing - Log.d("@@@", - String.format("MimeType: %s, data: %s", - mimeType, actualContentValues.toString())); */ - // Remove RAW_CONTACT_ID entry just for safety, since we do not care - // how resolver-related code handles the entry in this unit test, - if (actualContentValues.containsKey(Data.RAW_CONTACT_ID)) { - actualContentValues.remove(Data.RAW_CONTACT_ID); - } - final Collection<ContentValues> contentValuesCollection = - mMimeTypeToExpectedContentValues.get(mimeType); - if (contentValuesCollection.isEmpty()) { - mTestCase.fail("ContentValues for MimeType " + mimeType - + " is not expected at all (" + actualContentValues + ")"); - } - boolean checked = false; - for (ContentValues expectedContentValues : contentValuesCollection) { - /*for testing - Log.d("@@@", "expected: " - + convertToEasilyReadableString(expectedContentValues)); - Log.d("@@@", "actual : " - + convertToEasilyReadableString(actualContentValues));*/ - if (equalsForContentValues(expectedContentValues, - actualContentValues)) { - mTestCase.assertTrue(contentValuesCollection.remove(expectedContentValues)); - checked = true; - break; - } - } - if (!checked) { - final StringBuilder builder = new StringBuilder(); - builder.append("Unexpected: "); - builder.append(convertToEasilyReadableString(actualContentValues)); - builder.append("\nExpected: "); - for (ContentValues expectedContentValues : contentValuesCollection) { - builder.append(convertToEasilyReadableString(expectedContentValues)); - } - mTestCase.fail(builder.toString()); - } - } else { - mTestCase.fail("Unexpected Uri has come: " + uri); - } - } // for (int i = 0; i < size; i++) { - return fakeResultArray; - } - - public void verify() { - StringBuilder builder = new StringBuilder(); - for (Collection<ContentValues> contentValuesCollection : - mMimeTypeToExpectedContentValues.values()) { - for (ContentValues expectedContentValues: contentValuesCollection) { - builder.append(convertToEasilyReadableString(expectedContentValues)); - builder.append("\n"); - } - } - if (builder.length() > 0) { - final String failMsg = - "There is(are) remaining expected ContentValues instance(s): \n" - + builder.toString(); - mTestCase.fail(failMsg); - } - } - - /** - * Utility method to print ContentValues whose content is printed with sorted keys. - */ - private String convertToEasilyReadableString(ContentValues contentValues) { - if (contentValues == null) { - return "null"; - } - String mimeTypeValue = ""; - SortedMap<String, String> sortedMap = new TreeMap<String, String>(); - for (Entry<String, Object> entry : contentValues.valueSet()) { - final String key = entry.getKey(); - final Object value = entry.getValue(); - final String valueString = (value != null ? value.toString() : null); - if (Data.MIMETYPE.equals(key)) { - mimeTypeValue = valueString; - } else { - mTestCase.assertNotNull(key); - sortedMap.put(key, valueString); - } - } - StringBuilder builder = new StringBuilder(); - builder.append(Data.MIMETYPE); - builder.append('='); - builder.append(mimeTypeValue); - for (Entry<String, String> entry : sortedMap.entrySet()) { - final String key = entry.getKey(); - final String value = entry.getValue(); - builder.append(' '); - builder.append(key); - builder.append("=\""); - builder.append(value); - builder.append('"'); - } - return builder.toString(); - } - - private static boolean equalsForContentValues( - ContentValues expected, ContentValues actual) { - if (expected == actual) { - return true; - } else if (expected == null || actual == null || expected.size() != actual.size()) { - return false; - } - - for (Entry<String, Object> entry : expected.valueSet()) { - final String key = entry.getKey(); - final Object value = entry.getValue(); - if (!actual.containsKey(key)) { - return false; - } - if (value instanceof byte[]) { - Object actualValue = actual.get(key); - if (!Arrays.equals((byte[])value, (byte[])actualValue)) { - return false; - } - } else if (!value.equals(actual.get(key))) { - return false; - } - } - return true; - } -}
\ No newline at end of file diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/ImportTestResolver.java b/core/tests/coretests/src/android/pim/vcard/test_utils/ImportTestResolver.java deleted file mode 100644 index 29738c6..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/ImportTestResolver.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.test_utils; - -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; -import android.content.ContentValues; -import android.provider.ContactsContract.RawContacts; -import android.test.mock.MockContentResolver; - -import junit.framework.TestCase; - -import java.util.ArrayList; - -/* package */ class ImportTestResolver extends MockContentResolver { - private final ImportTestProvider mProvider; - - public ImportTestResolver(TestCase testCase) { - mProvider = new ImportTestProvider(testCase); - } - - @Override - public ContentProviderResult[] applyBatch(String authority, - ArrayList<ContentProviderOperation> operations) { - equalsString(authority, RawContacts.CONTENT_URI.toString()); - return mProvider.applyBatch(operations); - } - - public void addExpectedContentValues(ContentValues expectedContentValues) { - mProvider.addExpectedContentValues(expectedContentValues); - } - - public void verify() { - mProvider.verify(); - } - - private static boolean equalsString(String a, String b) { - if (a == null || a.length() == 0) { - return b == null || b.length() == 0; - } else { - return a.equals(b); - } - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/LineVerifier.java b/core/tests/coretests/src/android/pim/vcard/test_utils/LineVerifier.java deleted file mode 100644 index 3edec67..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/LineVerifier.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.test_utils; - -import android.content.Context; -import android.pim.vcard.VCardComposer; - -import junit.framework.TestCase; - -import java.util.ArrayList; - -public class LineVerifier implements VCardComposer.OneEntryHandler { - private final TestCase mTestCase; - private final ArrayList<LineVerifierElem> mLineVerifierElemList; - private int mVCardType; - private int index; - - public LineVerifier(TestCase testCase, int vcardType) { - mTestCase = testCase; - mLineVerifierElemList = new ArrayList<LineVerifierElem>(); - mVCardType = vcardType; - } - - public LineVerifierElem addLineVerifierElem() { - LineVerifierElem lineVerifier = new LineVerifierElem(mTestCase, mVCardType); - mLineVerifierElemList.add(lineVerifier); - return lineVerifier; - } - - public void verify(String vcard) { - if (index >= mLineVerifierElemList.size()) { - mTestCase.fail("Insufficient number of LineVerifier (" + index + ")"); - } - - LineVerifierElem lineVerifier = mLineVerifierElemList.get(index); - lineVerifier.verify(vcard); - - index++; - } - - public boolean onEntryCreated(String vcard) { - verify(vcard); - return true; - } - - public boolean onInit(Context context) { - return true; - } - - public void onTerminate() { - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/LineVerifierElem.java b/core/tests/coretests/src/android/pim/vcard/test_utils/LineVerifierElem.java deleted file mode 100644 index 4f7a9cf..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/LineVerifierElem.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android.pim.vcard.test_utils; - -import android.pim.vcard.VCardConfig; -import android.text.TextUtils; - -import junit.framework.TestCase; - -import java.util.ArrayList; -import java.util.List; - -public class LineVerifierElem { - private final TestCase mTestCase; - private final List<String> mExpectedLineList = new ArrayList<String>(); - private final boolean mIsV30; - - public LineVerifierElem(TestCase testCase, int vcardType) { - mTestCase = testCase; - mIsV30 = VCardConfig.isV30(vcardType); - } - - public LineVerifierElem addExpected(final String line) { - if (!TextUtils.isEmpty(line)) { - mExpectedLineList.add(line); - } - return this; - } - - public void verify(final String vcard) { - final String[] lineArray = vcard.split("\\r?\\n"); - final int length = lineArray.length; - boolean beginExists = false; - boolean endExists = false; - boolean versionExists = false; - - for (int i = 0; i < length; i++) { - final String line = lineArray[i]; - if (TextUtils.isEmpty(line)) { - continue; - } - - if ("BEGIN:VCARD".equalsIgnoreCase(line)) { - if (beginExists) { - mTestCase.fail("Multiple \"BEGIN:VCARD\" line found"); - } else { - beginExists = true; - continue; - } - } else if ("END:VCARD".equalsIgnoreCase(line)) { - if (endExists) { - mTestCase.fail("Multiple \"END:VCARD\" line found"); - } else { - endExists = true; - continue; - } - } else if ((mIsV30 ? "VERSION:3.0" : "VERSION:2.1").equalsIgnoreCase(line)) { - if (versionExists) { - mTestCase.fail("Multiple VERSION line + found"); - } else { - versionExists = true; - continue; - } - } - - if (!beginExists) { - mTestCase.fail("Property other than BEGIN came before BEGIN property: " - + line); - } else if (endExists) { - mTestCase.fail("Property other than END came after END property: " - + line); - } - - final int index = mExpectedLineList.indexOf(line); - if (index >= 0) { - mExpectedLineList.remove(index); - } else { - mTestCase.fail("Unexpected line: " + line); - } - } - - if (!mExpectedLineList.isEmpty()) { - StringBuffer buffer = new StringBuffer(); - for (String expectedLine : mExpectedLineList) { - buffer.append(expectedLine); - buffer.append("\n"); - } - - mTestCase.fail("Expected line(s) not found:" + buffer.toString()); - } - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/PropertyNode.java b/core/tests/coretests/src/android/pim/vcard/test_utils/PropertyNode.java deleted file mode 100644 index de7ad8e..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/PropertyNode.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.test_utils; - -import android.content.ContentValues; -import android.pim.vcard.VCardEntry; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * <p> - * The class representing one property (e.g. "N;ENCODING=UTF-8:family:given:middle:prefix:suffix"). - * </p> - * <p> - * Previously used in main vCard handling code but now exists only for testing. - * </p> - * <p> - * Especially useful for testing parser code (VCardParser), since all properties can be - * 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 - * {@link VCardEntry} is wrong without this class. - * </p> - */ -public class PropertyNode { - public String propName; - public String propValue; - public List<String> propValue_vector; - - /** Store value as byte[],after decode. - * Used when propValue is encoded by something like BASE64, QUOTED-PRINTABLE, etc. - */ - public byte[] propValue_bytes; - - /** - * param store: key=paramType, value=paramValue - * Note that currently PropertyNode class does not support multiple param-values - * defined in vCard 3.0 (See also RFC 2426). multiple-values are stored as - * one String value like "A,B", not ["A", "B"]... - * TODO: fix this. - */ - public ContentValues paramMap; - - /** Only for TYPE=??? param store. */ - public Set<String> paramMap_TYPE; - - /** Store group values. Used only in VCard. */ - public Set<String> propGroupSet; - - public PropertyNode() { - propName = ""; - propValue = ""; - propValue_vector = new ArrayList<String>(); - paramMap = new ContentValues(); - paramMap_TYPE = new HashSet<String>(); - propGroupSet = new HashSet<String>(); - } - - public PropertyNode( - String propName, String propValue, List<String> propValue_vector, - byte[] propValue_bytes, ContentValues paramMap, Set<String> paramMap_TYPE, - Set<String> propGroupSet) { - if (propName != null) { - this.propName = propName; - } else { - this.propName = ""; - } - if (propValue != null) { - this.propValue = propValue; - } else { - this.propValue = ""; - } - if (propValue_vector != null) { - this.propValue_vector = propValue_vector; - } else { - this.propValue_vector = new ArrayList<String>(); - } - this.propValue_bytes = propValue_bytes; - if (paramMap != null) { - this.paramMap = paramMap; - } else { - this.paramMap = new ContentValues(); - } - if (paramMap_TYPE != null) { - this.paramMap_TYPE = paramMap_TYPE; - } else { - this.paramMap_TYPE = new HashSet<String>(); - } - if (propGroupSet != null) { - this.propGroupSet = propGroupSet; - } else { - this.propGroupSet = new HashSet<String>(); - } - } - - @Override - public int hashCode() { - // vCard may contain more than one same line in one entry, while HashSet or any other - // library which utilize hashCode() does not honor that, so intentionally throw an - // Exception. - throw new UnsupportedOperationException( - "PropertyNode does not provide hashCode() implementation intentionally."); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof PropertyNode)) { - return false; - } - - PropertyNode node = (PropertyNode)obj; - - if (propName == null || !propName.equals(node.propName)) { - return false; - } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) { - return false; - } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) { - return false; - } else if (!propGroupSet.equals(node.propGroupSet)) { - return false; - } - - if (propValue_bytes != null && Arrays.equals(propValue_bytes, node.propValue_bytes)) { - return true; - } else { - if (!propValue.equals(node.propValue)) { - return false; - } - - // The value in propValue_vector is not decoded even if it should be - // decoded by BASE64 or QUOTED-PRINTABLE. When the size of propValue_vector - // is 1, the encoded value is stored in propValue, so we do not have to - // check it. - return (propValue_vector.equals(node.propValue_vector) || - propValue_vector.size() == 1 || - node.propValue_vector.size() == 1); - } - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("propName: "); - builder.append(propName); - builder.append(", paramMap: "); - builder.append(paramMap.toString()); - builder.append(", paramMap_TYPE: ["); - boolean first = true; - for (String elem : paramMap_TYPE) { - if (first) { - first = false; - } else { - builder.append(", "); - } - builder.append('"'); - builder.append(elem); - builder.append('"'); - } - builder.append("]"); - if (!propGroupSet.isEmpty()) { - builder.append(", propGroupSet: ["); - first = true; - 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) { - builder.append(", propValue_vector size: "); - builder.append(propValue_vector.size()); - } - if (propValue_bytes != null) { - builder.append(", propValue_bytes size: "); - builder.append(propValue_bytes.length); - } - builder.append(", propValue: \""); - builder.append(propValue); - builder.append("\""); - return builder.toString(); - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/PropertyNodesVerifier.java b/core/tests/coretests/src/android/pim/vcard/test_utils/PropertyNodesVerifier.java deleted file mode 100644 index 5c8215f..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/PropertyNodesVerifier.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.test_utils; - -import android.pim.vcard.VCardConfig; -import android.pim.vcard.VCardParser; -import android.pim.vcard.VCardParser_V21; -import android.pim.vcard.VCardParser_V30; -import android.pim.vcard.exception.VCardException; -import android.test.AndroidTestCase; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -public class PropertyNodesVerifier extends VNodeBuilder { - private final List<PropertyNodesVerifierElem> mPropertyNodesVerifierElemList; - private final AndroidTestCase mAndroidTestCase; - private int mIndex; - - public PropertyNodesVerifier(AndroidTestCase testCase) { - super(); - mPropertyNodesVerifierElemList = new ArrayList<PropertyNodesVerifierElem>(); - mAndroidTestCase = testCase; - } - - public PropertyNodesVerifierElem addPropertyNodesVerifierElem() { - PropertyNodesVerifierElem elem = new PropertyNodesVerifierElem(mAndroidTestCase); - mPropertyNodesVerifierElemList.add(elem); - return elem; - } - - public void verify(int resId, int vCardType) - throws IOException, VCardException { - verify(mAndroidTestCase.getContext().getResources().openRawResource(resId), vCardType); - } - - public void verify(int resId, int vCardType, final VCardParser vCardParser) - throws IOException, VCardException { - verify(mAndroidTestCase.getContext().getResources().openRawResource(resId), - vCardType, vCardParser); - } - - public void verify(InputStream is, int vCardType) throws IOException, VCardException { - final VCardParser vCardParser; - if (VCardConfig.isV30(vCardType)) { - vCardParser = new VCardParser_V30(); - } else { - vCardParser = new VCardParser_V21(); - } - verify(is, vCardType, vCardParser); - } - - public void verify(InputStream is, int vCardType, final VCardParser vCardParser) - throws IOException, VCardException { - try { - vCardParser.parse(is, this); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - } - } - } - } - - @Override - public void endEntry() { - super.endEntry(); - mAndroidTestCase.assertTrue(mIndex < mPropertyNodesVerifierElemList.size()); - mAndroidTestCase.assertTrue(mIndex < vNodeList.size()); - mPropertyNodesVerifierElemList.get(mIndex).verify(vNodeList.get(mIndex)); - mIndex++; - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/PropertyNodesVerifierElem.java b/core/tests/coretests/src/android/pim/vcard/test_utils/PropertyNodesVerifierElem.java deleted file mode 100644 index 8c6c734..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/PropertyNodesVerifierElem.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.test_utils; - -import android.content.ContentValues; - -import junit.framework.TestCase; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; - -/** - * Utility class which verifies input VNode. - * - * This class first checks whether each propertyNode in the VNode is in the - * "ordered expected property list". - * If the node does not exist in the "ordered list", the class refers to - * "unorderd expected property set" and checks the node is expected somewhere. - */ -public class PropertyNodesVerifierElem { - public static class TypeSet extends HashSet<String> { - public TypeSet(String ... array) { - super(Arrays.asList(array)); - } - } - - public static class GroupSet extends HashSet<String> { - public GroupSet(String ... array) { - super(Arrays.asList(array)); - } - } - - private final HashMap<String, List<PropertyNode>> mOrderedNodeMap; - // Intentionally use ArrayList instead of Set, assuming there may be more than one - // exactly same objects. - private final ArrayList<PropertyNode> mUnorderedNodeList; - private final TestCase mTestCase; - - public PropertyNodesVerifierElem(TestCase testCase) { - mOrderedNodeMap = new HashMap<String, List<PropertyNode>>(); - mUnorderedNodeList = new ArrayList<PropertyNode>(); - mTestCase = testCase; - } - - // WithOrder - - public PropertyNodesVerifierElem addExpectedNodeWithOrder(String propName, String propValue) { - return addExpectedNodeWithOrder(propName, propValue, null, null, null, null, null); - } - - public PropertyNodesVerifierElem addExpectedNodeWithOrder( - String propName, String propValue, ContentValues contentValues) { - return addExpectedNodeWithOrder(propName, propValue, null, - null, contentValues, null, null); - } - - public PropertyNodesVerifierElem addExpectedNodeWithOrder( - String propName, List<String> propValueList, ContentValues contentValues) { - return addExpectedNodeWithOrder(propName, null, propValueList, - null, contentValues, null, null); - } - - public PropertyNodesVerifierElem addExpectedNodeWithOrder( - String propName, String propValue, List<String> propValueList) { - return addExpectedNodeWithOrder(propName, propValue, propValueList, null, - null, null, null); - } - - public PropertyNodesVerifierElem addExpectedNodeWithOrder( - String propName, List<String> propValueList) { - final String propValue = concatinateListWithSemiColon(propValueList); - return addExpectedNodeWithOrder(propName, propValue.toString(), propValueList, - null, null, null, null); - } - - public PropertyNodesVerifierElem addExpectedNodeWithOrder(String propName, String propValue, - TypeSet paramMap_TYPE) { - return addExpectedNodeWithOrder(propName, propValue, null, - null, null, paramMap_TYPE, null); - } - - public PropertyNodesVerifierElem addExpectedNodeWithOrder(String propName, - List<String> propValueList, TypeSet paramMap_TYPE) { - return addExpectedNodeWithOrder(propName, null, propValueList, null, null, - paramMap_TYPE, null); - } - - public PropertyNodesVerifierElem addExpectedNodeWithOrder(String propName, String propValue, - ContentValues paramMap, TypeSet paramMap_TYPE) { - return addExpectedNodeWithOrder(propName, propValue, null, null, - paramMap, paramMap_TYPE, null); - } - - public PropertyNodesVerifierElem addExpectedNodeWithOrder(String propName, String propValue, - List<String> propValueList, TypeSet paramMap_TYPE) { - return addExpectedNodeWithOrder(propName, propValue, propValueList, null, null, - paramMap_TYPE, null); - } - - public PropertyNodesVerifierElem addExpectedNodeWithOrder(String propName, String propValue, - List<String> propValueList, byte[] propValue_bytes, - ContentValues paramMap, TypeSet paramMap_TYPE, GroupSet propGroupSet) { - if (propValue == null && propValueList != null) { - propValue = concatinateListWithSemiColon(propValueList); - } - PropertyNode propertyNode = new PropertyNode(propName, - propValue, propValueList, propValue_bytes, - paramMap, paramMap_TYPE, propGroupSet); - List<PropertyNode> expectedNodeList = mOrderedNodeMap.get(propName); - if (expectedNodeList == null) { - expectedNodeList = new ArrayList<PropertyNode>(); - mOrderedNodeMap.put(propName, expectedNodeList); - } - expectedNodeList.add(propertyNode); - return this; - } - - // WithoutOrder - - public PropertyNodesVerifierElem addExpectedNode(String propName, String propValue) { - return addExpectedNode(propName, propValue, null, null, null, null, null); - } - - public PropertyNodesVerifierElem addExpectedNode(String propName, String propValue, - ContentValues contentValues) { - return addExpectedNode(propName, propValue, null, null, contentValues, null, null); - } - - public PropertyNodesVerifierElem addExpectedNode(String propName, - List<String> propValueList, ContentValues contentValues) { - return addExpectedNode(propName, null, - propValueList, null, contentValues, null, null); - } - - public PropertyNodesVerifierElem addExpectedNode(String propName, String propValue, - List<String> propValueList) { - return addExpectedNode(propName, propValue, propValueList, null, null, null, null); - } - - public PropertyNodesVerifierElem addExpectedNode(String propName, - List<String> propValueList) { - return addExpectedNode(propName, null, propValueList, - null, null, null, null); - } - - public PropertyNodesVerifierElem addExpectedNode(String propName, String propValue, - TypeSet paramMap_TYPE) { - return addExpectedNode(propName, propValue, null, null, null, paramMap_TYPE, null); - } - - public PropertyNodesVerifierElem addExpectedNode(String propName, - List<String> propValueList, TypeSet paramMap_TYPE) { - final String propValue = concatinateListWithSemiColon(propValueList); - return addExpectedNode(propName, propValue, propValueList, null, null, - paramMap_TYPE, null); - } - - public PropertyNodesVerifierElem addExpectedNode(String propName, String propValue, - List<String> propValueList, TypeSet paramMap_TYPE) { - return addExpectedNode(propName, propValue, propValueList, null, null, - paramMap_TYPE, null); - } - - public PropertyNodesVerifierElem addExpectedNode(String propName, String propValue, - ContentValues paramMap, TypeSet paramMap_TYPE) { - return addExpectedNode(propName, propValue, null, null, - paramMap, paramMap_TYPE, null); - } - - public PropertyNodesVerifierElem addExpectedNode(String propName, String propValue, - List<String> propValueList, byte[] propValue_bytes, - ContentValues paramMap, TypeSet paramMap_TYPE, GroupSet propGroupSet) { - if (propValue == null && propValueList != null) { - propValue = concatinateListWithSemiColon(propValueList); - } - mUnorderedNodeList.add(new PropertyNode(propName, propValue, - propValueList, propValue_bytes, paramMap, paramMap_TYPE, propGroupSet)); - return this; - } - - public void verify(VNode vnode) { - for (PropertyNode actualNode : vnode.propList) { - verifyNode(actualNode.propName, actualNode); - } - if (!mOrderedNodeMap.isEmpty() || !mUnorderedNodeList.isEmpty()) { - List<String> expectedProps = new ArrayList<String>(); - for (List<PropertyNode> nodes : mOrderedNodeMap.values()) { - for (PropertyNode node : nodes) { - if (!expectedProps.contains(node.propName)) { - expectedProps.add(node.propName); - } - } - } - for (PropertyNode node : mUnorderedNodeList) { - if (!expectedProps.contains(node.propName)) { - expectedProps.add(node.propName); - } - } - mTestCase.fail("Expected property " + Arrays.toString(expectedProps.toArray()) - + " was not found."); - } - } - - private void verifyNode(final String propName, final PropertyNode actualNode) { - List<PropertyNode> expectedNodeList = mOrderedNodeMap.get(propName); - final int size = (expectedNodeList != null ? expectedNodeList.size() : 0); - if (size > 0) { - for (int i = 0; i < size; i++) { - PropertyNode expectedNode = expectedNodeList.get(i); - List<PropertyNode> expectedButDifferentValueList = new ArrayList<PropertyNode>(); - if (expectedNode.propName.equals(propName)) { - if (expectedNode.equals(actualNode)) { - expectedNodeList.remove(i); - if (expectedNodeList.size() == 0) { - mOrderedNodeMap.remove(propName); - } - return; - } else { - expectedButDifferentValueList.add(expectedNode); - } - } - - // "actualNode" is not in ordered expected list. - // Try looking over unordered expected list. - if (tryFoundExpectedNodeFromUnorderedList(actualNode, - expectedButDifferentValueList)) { - return; - } - - if (!expectedButDifferentValueList.isEmpty()) { - // Same propName exists but with different value(s). - failWithExpectedNodeList(propName, actualNode, - expectedButDifferentValueList); - } else { - // There's no expected node with same propName. - mTestCase.fail("Unexpected property \"" + propName + "\" exists."); - } - } - } else { - List<PropertyNode> expectedButDifferentValueList = - new ArrayList<PropertyNode>(); - if (tryFoundExpectedNodeFromUnorderedList(actualNode, expectedButDifferentValueList)) { - return; - } else { - if (!expectedButDifferentValueList.isEmpty()) { - // Same propName exists but with different value(s). - failWithExpectedNodeList(propName, actualNode, - expectedButDifferentValueList); - } else { - // There's no expected node with same propName. - mTestCase.fail("Unexpected property \"" + propName + "\" exists."); - } - } - } - } - - private String concatinateListWithSemiColon(List<String> array) { - StringBuffer buffer = new StringBuffer(); - boolean first = true; - for (String propValueElem : array) { - if (first) { - first = false; - } else { - buffer.append(';'); - } - buffer.append(propValueElem); - } - - return buffer.toString(); - } - - private boolean tryFoundExpectedNodeFromUnorderedList(PropertyNode actualNode, - List<PropertyNode> expectedButDifferentValueList) { - final String propName = actualNode.propName; - int unorderedListSize = mUnorderedNodeList.size(); - for (int i = 0; i < unorderedListSize; i++) { - PropertyNode unorderedExpectedNode = mUnorderedNodeList.get(i); - if (unorderedExpectedNode.propName.equals(propName)) { - if (unorderedExpectedNode.equals(actualNode)) { - mUnorderedNodeList.remove(i); - return true; - } - expectedButDifferentValueList.add(unorderedExpectedNode); - } - } - return false; - } - - private void failWithExpectedNodeList(String propName, PropertyNode actualNode, - List<PropertyNode> expectedNodeList) { - StringBuilder builder = new StringBuilder(); - for (PropertyNode expectedNode : expectedNodeList) { - builder.append("expected: "); - builder.append(expectedNode.toString()); - builder.append("\n"); - } - mTestCase.fail("Property \"" + propName + "\" has wrong value.\n" - + builder.toString() - + " actual: " + actualNode.toString()); - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/VCardVerifier.java b/core/tests/coretests/src/android/pim/vcard/test_utils/VCardVerifier.java deleted file mode 100644 index 5fb2942..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/VCardVerifier.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android.pim.vcard.test_utils; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.EntityIterator; -import android.net.Uri; -import android.pim.vcard.VCardComposer; -import android.pim.vcard.VCardConfig; -import android.pim.vcard.VCardEntryConstructor; -import android.pim.vcard.VCardInterpreter; -import android.pim.vcard.VCardInterpreterCollection; -import android.pim.vcard.VCardParser; -import android.pim.vcard.VCardParser_V21; -import android.pim.vcard.VCardParser_V30; -import android.pim.vcard.exception.VCardException; -import android.test.AndroidTestCase; -import android.test.mock.MockContext; -import android.text.TextUtils; -import android.util.Log; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.util.Arrays; - -/** - * <p> - * The class lets users checks that given expected vCard data are same as given actual vCard data. - * Able to verify both vCard importer/exporter. - * </p> - * <p> - * First a user has to initialize the object by calling either - * {@link #initForImportTest(int, int)} or {@link #initForExportTest(int)}. - * "Round trip test" (import -> export -> import, or export -> import -> export) is not supported. - * </p> - */ -public class VCardVerifier { - private static final String LOG_TAG = "VCardVerifier"; - - private static class CustomMockContext extends MockContext { - final ContentResolver mResolver; - public CustomMockContext(ContentResolver resolver) { - mResolver = resolver; - } - - @Override - public ContentResolver getContentResolver() { - return mResolver; - } - } - - private class VCardVerifierInternal implements VCardComposer.OneEntryHandler { - public boolean onInit(Context context) { - return true; - } - public boolean onEntryCreated(String vcard) { - verifyOneVCard(vcard); - return true; - } - public void onTerminate() { - } - } - - private final AndroidTestCase mTestCase; - private final VCardVerifierInternal mVCardVerifierInternal; - private int mVCardType; - private boolean mIsV30; - private boolean mIsDoCoMo; - - // Only one of them must be non-empty. - private ExportTestResolver mExportTestResolver; - private InputStream mInputStream; - - // To allow duplication, use list instead of set. - // When null, we don't need to do the verification. - private PropertyNodesVerifier mPropertyNodesVerifier; - private LineVerifier mLineVerifier; - private ContentValuesVerifier mContentValuesVerifier; - private boolean mInitialized; - private boolean mVerified = false; - private String mCharset; - - // Called by VCardTestsBase - public VCardVerifier(AndroidTestCase testCase) { - mTestCase = testCase; - mVCardVerifierInternal = new VCardVerifierInternal(); - mExportTestResolver = null; - mInputStream = null; - mInitialized = false; - mVerified = false; - } - - // Should be called at the beginning of each import test. - public void initForImportTest(int vcardType, int resId) { - if (mInitialized) { - mTestCase.fail("Already initialized"); - } - mVCardType = vcardType; - mIsV30 = VCardConfig.isV30(vcardType); - mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); - setInputResourceId(resId); - mInitialized = true; - } - - // Should be called at the beginning of each export test. - public void initForExportTest(int vcardType) { - initForExportTest(vcardType, "UTF-8"); - } - - public void initForExportTest(int vcardType, String charset) { - if (mInitialized) { - mTestCase.fail("Already initialized"); - } - mExportTestResolver = new ExportTestResolver(mTestCase); - mVCardType = vcardType; - mIsV30 = VCardConfig.isV30(vcardType); - mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); - mInitialized = true; - if (TextUtils.isEmpty(charset)) { - mCharset = "UTF-8"; - } else { - mCharset = charset; - } - } - - private void setInputResourceId(int resId) { - InputStream inputStream = mTestCase.getContext().getResources().openRawResource(resId); - if (inputStream == null) { - mTestCase.fail("Wrong resId: " + resId); - } - setInputStream(inputStream); - } - - private void setInputStream(InputStream inputStream) { - if (mExportTestResolver != null) { - mTestCase.fail("addInputEntry() is called."); - } else if (mInputStream != null) { - mTestCase.fail("InputStream is already set"); - } - mInputStream = inputStream; - } - - public ContactEntry addInputEntry() { - if (!mInitialized) { - mTestCase.fail("Not initialized"); - } - if (mInputStream != null) { - mTestCase.fail("setInputStream is called"); - } - return mExportTestResolver.addInputContactEntry(); - } - - public PropertyNodesVerifierElem addPropertyNodesVerifierElem() { - if (!mInitialized) { - mTestCase.fail("Not initialized"); - } - if (mPropertyNodesVerifier == null) { - mPropertyNodesVerifier = new PropertyNodesVerifier(mTestCase); - } - PropertyNodesVerifierElem elem = - mPropertyNodesVerifier.addPropertyNodesVerifierElem(); - elem.addExpectedNodeWithOrder("VERSION", (mIsV30 ? "3.0" : "2.1")); - - return elem; - } - - public PropertyNodesVerifierElem addPropertyNodesVerifierElemWithEmptyName() { - if (!mInitialized) { - mTestCase.fail("Not initialized"); - } - PropertyNodesVerifierElem elem = addPropertyNodesVerifierElem(); - if (mIsV30) { - elem.addExpectedNodeWithOrder("N", "").addExpectedNodeWithOrder("FN", ""); - } else if (mIsDoCoMo) { - elem.addExpectedNodeWithOrder("N", ""); - } - return elem; - } - - public LineVerifierElem addLineVerifierElem() { - if (!mInitialized) { - mTestCase.fail("Not initialized"); - } - if (mLineVerifier == null) { - mLineVerifier = new LineVerifier(mTestCase, mVCardType); - } - return mLineVerifier.addLineVerifierElem(); - } - - public ContentValuesVerifierElem addContentValuesVerifierElem() { - if (!mInitialized) { - mTestCase.fail("Not initialized"); - } - if (mContentValuesVerifier == null) { - mContentValuesVerifier = new ContentValuesVerifier(); - } - - return mContentValuesVerifier.addElem(mTestCase); - } - - private void verifyOneVCard(final String vcard) { - Log.d(LOG_TAG, vcard); - final VCardInterpreter builder; - if (mContentValuesVerifier != null) { - final VNodeBuilder vnodeBuilder = mPropertyNodesVerifier; - final VCardEntryConstructor vcardDataBuilder = - new VCardEntryConstructor(mVCardType); - vcardDataBuilder.addEntryHandler(mContentValuesVerifier); - if (mPropertyNodesVerifier != null) { - builder = new VCardInterpreterCollection(Arrays.asList( - mPropertyNodesVerifier, vcardDataBuilder)); - } else { - builder = vnodeBuilder; - } - } else { - if (mPropertyNodesVerifier != null) { - builder = mPropertyNodesVerifier; - } else { - return; - } - } - - InputStream is = null; - try { - // Note: we must not specify charset toward vCard parsers. This code checks whether - // those parsers are able to encode given binary without any extra information for - // charset. - final VCardParser parser = (mIsV30 ? - new VCardParser_V30(mVCardType) : new VCardParser_V21(mVCardType)); - is = new ByteArrayInputStream(vcard.getBytes(mCharset)); - parser.parse(is, builder); - } catch (IOException e) { - mTestCase.fail("Unexpected IOException: " + e.getMessage()); - } catch (VCardException e) { - mTestCase.fail("Unexpected VCardException: " + e.getMessage()); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - mTestCase.fail("Unexpected IOException: " + e.getMessage()); - } - } - } - } - - public void verify() { - if (!mInitialized) { - mTestCase.fail("Not initialized."); - } - if (mVerified) { - mTestCase.fail("verify() was called twice."); - } - if (mInputStream != null) { - try { - verifyForImportTest(); - } catch (IOException e) { - mTestCase.fail("IOException was thrown: " + e.getMessage()); - } catch (VCardException e) { - mTestCase.fail("VCardException was thrown: " + e.getMessage()); - } - } else if (mExportTestResolver != null){ - verifyForExportTest(); - } else { - mTestCase.fail("No input is determined"); - } - mVerified = true; - } - - private void verifyForImportTest() throws IOException, VCardException { - if (mLineVerifier != null) { - mTestCase.fail("Not supported now."); - } - if (mContentValuesVerifier != null) { - mContentValuesVerifier.verify(mInputStream, mVCardType); - } - } - - public static EntityIterator mockGetEntityIteratorMethod( - final ContentResolver resolver, - final Uri uri, final String selection, - final String[] selectionArgs, final String sortOrder) { - if (ExportTestResolver.class.equals(resolver.getClass())) { - return ((ExportTestResolver)resolver).getProvider().queryEntities( - uri, selection, selectionArgs, sortOrder); - } - - Log.e(LOG_TAG, "Unexpected provider given."); - return null; - } - - private Method getMockGetEntityIteratorMethod() - throws SecurityException, NoSuchMethodException { - return this.getClass().getMethod("mockGetEntityIteratorMethod", - ContentResolver.class, Uri.class, String.class, String[].class, String.class); - } - - private void verifyForExportTest() { - final VCardComposer composer = - new VCardComposer(new CustomMockContext(mExportTestResolver), mVCardType, mCharset); - composer.addHandler(mLineVerifier); - composer.addHandler(mVCardVerifierInternal); - if (!composer.init(VCardComposer.CONTACTS_TEST_CONTENT_URI, null, null, null)) { - mTestCase.fail("init() failed. Reason: " + composer.getErrorReason()); - } - mTestCase.assertFalse(composer.isAfterLast()); - try { - while (!composer.isAfterLast()) { - try { - final Method mockGetEntityIteratorMethod = getMockGetEntityIteratorMethod(); - mTestCase.assertNotNull(mockGetEntityIteratorMethod); - mTestCase.assertTrue(composer.createOneEntry(mockGetEntityIteratorMethod)); - } catch (Exception e) { - e.printStackTrace(); - mTestCase.fail(); - } - } - } finally { - composer.terminate(); - } - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/VNode.java b/core/tests/coretests/src/android/pim/vcard/test_utils/VNode.java deleted file mode 100644 index b890e2c..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/VNode.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.test_utils; - -import java.util.ArrayList; - -/** - * Previously used in main vCard handling code but now exists only for testing. - */ -public class VNode { - public String VName; - - public ArrayList<PropertyNode> propList = new ArrayList<PropertyNode>(); - - /** 0:parse over. 1:parsing. */ - public int parseStatus = 1; -} diff --git a/core/tests/coretests/src/android/pim/vcard/test_utils/VNodeBuilder.java b/core/tests/coretests/src/android/pim/vcard/test_utils/VNodeBuilder.java deleted file mode 100644 index 25fb6ac..0000000 --- a/core/tests/coretests/src/android/pim/vcard/test_utils/VNodeBuilder.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.pim.vcard.test_utils; - -import android.content.ContentValues; -import android.pim.vcard.VCardConfig; -import android.pim.vcard.VCardInterpreter; -import android.pim.vcard.VCardUtils; -import android.util.CharsetUtils; -import android.util.Log; - -import org.apache.commons.codec.binary.Base64; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; - -/** - * <p> - * The class storing the parse result to custom datastruct: - * {@link VNode}, and {@link PropertyNode}. - * Maybe several vcard instance, so use vNodeList to store. - * </p> - * <p> - * This is called VNode, not VCardNode, since it was used for expressing vCalendar (iCal). - * </p> - */ -/* package */ class VNodeBuilder implements VCardInterpreter { - static private String LOG_TAG = "VNodeBuilder"; - - public List<VNode> vNodeList = new ArrayList<VNode>(); - private int mNodeListPos = 0; - private VNode mCurrentVNode; - private PropertyNode mCurrentPropNode; - private String mCurrentParamType; - - /** - * The charset using which VParser parses the text. - */ - private String mSourceCharset; - - /** - * The charset with which byte array is encoded to String. - */ - private String mTargetCharset; - - private boolean mStrictLineBreakParsing; - - public VNodeBuilder() { - this(VCardConfig.DEFAULT_INTERMEDIATE_CHARSET, VCardConfig.DEFAULT_IMPORT_CHARSET, false); - } - - public VNodeBuilder(String targetCharset, boolean strictLineBreakParsing) { - this(null, targetCharset, strictLineBreakParsing); - } - - /** - * @hide sourceCharset is temporal. - */ - public VNodeBuilder(String sourceCharset, String targetCharset, - boolean strictLineBreakParsing) { - if (sourceCharset != null) { - mSourceCharset = sourceCharset; - } else { - mSourceCharset = VCardConfig.DEFAULT_INTERMEDIATE_CHARSET; - } - if (targetCharset != null) { - mTargetCharset = targetCharset; - } else { - mTargetCharset = VCardConfig.DEFAULT_IMPORT_CHARSET; - } - mStrictLineBreakParsing = strictLineBreakParsing; - } - - public void start() { - } - - public void end() { - } - - // Note: I guess that this code assumes the Record may nest like this: - // START:VPOS - // ... - // START:VPOS2 - // ... - // END:VPOS2 - // ... - // END:VPOS - // - // However the following code has a bug. - // When error occurs after calling startRecord(), the entry which is probably - // the cause of the error remains to be in vNodeList, while endRecord() is not called. - // - // I leave this code as is since I'm not familiar with vcalendar specification. - // But I believe we should refactor this code in the future. - // Until this, the last entry has to be removed when some error occurs. - public void startEntry() { - VNode vnode = new VNode(); - vnode.parseStatus = 1; - vnode.VName = "VCARD"; - // I feel this should be done in endRecord(), but it cannot be done because of - // the reason above. - vNodeList.add(vnode); - mNodeListPos = vNodeList.size() - 1; - mCurrentVNode = vNodeList.get(mNodeListPos); - } - - public void endEntry() { - VNode endNode = vNodeList.get(mNodeListPos); - endNode.parseStatus = 0; - while(mNodeListPos > 0){ - mNodeListPos--; - if((vNodeList.get(mNodeListPos)).parseStatus == 1) - break; - } - mCurrentVNode = vNodeList.get(mNodeListPos); - } - - public void startProperty() { - mCurrentPropNode = new PropertyNode(); - } - - public void endProperty() { - mCurrentVNode.propList.add(mCurrentPropNode); - } - - public void propertyName(String name) { - mCurrentPropNode.propName = name; - } - - public void propertyGroup(String group) { - mCurrentPropNode.propGroupSet.add(group); - } - - public void propertyParamType(String type) { - mCurrentParamType = type; - } - - public void propertyParamValue(String value) { - if (mCurrentParamType == null || - mCurrentParamType.equalsIgnoreCase("TYPE")) { - mCurrentPropNode.paramMap_TYPE.add(value); - } else { - mCurrentPropNode.paramMap.put(mCurrentParamType, value); - } - - mCurrentParamType = null; - } - - private String encodeString(String originalString, String targetCharset) { - if (mSourceCharset.equalsIgnoreCase(targetCharset)) { - return originalString; - } - Charset charset = Charset.forName(mSourceCharset); - ByteBuffer byteBuffer = charset.encode(originalString); - // byteBuffer.array() "may" return byte array which is larger than - // byteBuffer.remaining(). Here, we keep on the safe side. - byte[] bytes = new byte[byteBuffer.remaining()]; - byteBuffer.get(bytes); - try { - return new String(bytes, targetCharset); - } catch (UnsupportedEncodingException e) { - Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset); - return null; - } - } - - private String handleOneValue(String value, String targetCharset, String encoding) { - if (encoding != null) { - encoding = encoding.toUpperCase(); - if (encoding.equals("BASE64") || encoding.equals("B")) { - // Assume BASE64 is used only when the number of values is 1. - mCurrentPropNode.propValue_bytes = - Base64.decodeBase64(value.getBytes()); - return value; - } else if (encoding.equals("QUOTED-PRINTABLE")) { - return VCardUtils.parseQuotedPrintable( - value, mStrictLineBreakParsing, mSourceCharset, targetCharset); - } - // Unknown encoding. Fall back to default. - } - return encodeString(value, targetCharset); - } - - public void propertyValues(List<String> values) { - if (values == null || values.size() == 0) { - mCurrentPropNode.propValue_bytes = null; - mCurrentPropNode.propValue_vector.clear(); - mCurrentPropNode.propValue_vector.add(""); - mCurrentPropNode.propValue = ""; - return; - } - - ContentValues paramMap = mCurrentPropNode.paramMap; - - String targetCharset = CharsetUtils.nameForDefaultVendor(paramMap.getAsString("CHARSET")); - String encoding = paramMap.getAsString("ENCODING"); - - if (targetCharset == null || targetCharset.length() == 0) { - targetCharset = mTargetCharset; - } - - for (String value : values) { - mCurrentPropNode.propValue_vector.add( - handleOneValue(value, targetCharset, encoding)); - } - - mCurrentPropNode.propValue = listToString(mCurrentPropNode.propValue_vector); - } - - private String listToString(List<String> list){ - int size = list.size(); - if (size > 1) { - StringBuilder typeListB = new StringBuilder(); - for (String type : list) { - typeListB.append(type).append(";"); - } - int len = typeListB.length(); - if (len > 0 && typeListB.charAt(len - 1) == ';') { - return typeListB.substring(0, len - 1); - } - return typeListB.toString(); - } else if (size == 1) { - return list.get(0); - } else { - return ""; - } - } - - public String getResult(){ - throw new RuntimeException("Not supported"); - } -} |