aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2014-11-06 11:12:36 +0000
committerTorne (Richard Coles) <torne@google.com>2014-11-06 11:12:36 +0000
commitbc218bd8b5a06b381ac7a99e1301bb900076bb34 (patch)
treecf43eb4c48540fcc93cdb1fde1536438b0ece281
parentc29dd2308a9beb970579e2a38ff1d02f218565a7 (diff)
parent5074e7546d9b6344ece890f6d1a99c3fd9132272 (diff)
downloadsrc-main.tar.gz
This commit was generated by merge_to_master.py. Change-Id: I07ba5e568405463b1b643a6e88d60d6d35bba2b7
-rw-r--r--.gitignore3
-rw-r--r--.gitmodules6
-rw-r--r--AUTHORS9
-rw-r--r--CONTRIBUTORS20
-rw-r--r--README.md45
-rw-r--r--codereview.settings4
-rw-r--r--cpp/README6
-rw-r--r--cpp/res/messages.grdp24
-rw-r--r--cpp/src/address_ui.cc12
-rw-r--r--cpp/src/region_data_constants.cc59
-rw-r--r--cpp/src/rule.cc50
-rw-r--r--cpp/src/rule.h16
-rw-r--r--cpp/src/util/json.cc2
-rw-r--r--cpp/test/region_data_constants_test.cc2
-rw-r--r--cpp/test/rule_test.cc123
m---------externals/grit0
m---------externals/rapidjson0
-rw-r--r--java/README35
-rw-r--r--java/res/values/address_strings.xml162
-rw-r--r--java/src/AndroidManifest.xml1
-rw-r--r--java/src/com/android/i18n/addressinput/AddressData.java588
-rw-r--r--java/src/com/android/i18n/addressinput/AddressDataKey.java4
-rw-r--r--java/src/com/android/i18n/addressinput/AddressField.java100
-rw-r--r--java/src/com/android/i18n/addressinput/AddressProblemType.java82
-rw-r--r--java/src/com/android/i18n/addressinput/AddressProblems.java68
-rw-r--r--java/src/com/android/i18n/addressinput/AddressUiComponent.java222
-rw-r--r--java/src/com/android/i18n/addressinput/AddressVerificationData.java222
-rw-r--r--java/src/com/android/i18n/addressinput/AddressVerificationNodeData.java48
-rw-r--r--java/src/com/android/i18n/addressinput/AddressWidget.java1309
-rw-r--r--java/src/com/android/i18n/addressinput/AddressWidgetUiComponentProvider.java106
-rw-r--r--java/src/com/android/i18n/addressinput/CacheData.java688
-rw-r--r--java/src/com/android/i18n/addressinput/ClientCacheManager.java12
-rw-r--r--java/src/com/android/i18n/addressinput/ClientData.java452
-rw-r--r--java/src/com/android/i18n/addressinput/DataLoadListener.java6
-rw-r--r--java/src/com/android/i18n/addressinput/DataSource.java4
-rw-r--r--java/src/com/android/i18n/addressinput/FieldVerifier.java552
-rw-r--r--java/src/com/android/i18n/addressinput/FormController.java561
-rw-r--r--java/src/com/android/i18n/addressinput/FormOptions.java428
-rw-r--r--java/src/com/android/i18n/addressinput/FormatInterpreter.java464
-rw-r--r--java/src/com/android/i18n/addressinput/JsoMap.java438
-rw-r--r--java/src/com/android/i18n/addressinput/JsonpRequestBuilder.java174
-rw-r--r--java/src/com/android/i18n/addressinput/LookupKey.java694
-rw-r--r--java/src/com/android/i18n/addressinput/NotifyingListener.java48
-rw-r--r--java/src/com/android/i18n/addressinput/RegionData.java140
-rw-r--r--java/src/com/android/i18n/addressinput/RegionDataConstants.java2540
-rw-r--r--java/src/com/android/i18n/addressinput/SimpleClientCacheManager.java26
-rw-r--r--java/src/com/android/i18n/addressinput/StandardAddressVerifier.java343
-rw-r--r--java/src/com/android/i18n/addressinput/StandardChecks.java64
-rw-r--r--java/src/com/android/i18n/addressinput/Util.java348
-rw-r--r--java/src/com/android/i18n/addressinput/testing/AddressDataMapLoader.java42
-rw-r--r--java/src/com/android/i18n/addressinput/testing/AsyncTestCase.java78
-rw-r--r--java/test/com/android/i18n/addressinput/AddressDataTest.java72
-rw-r--r--java/test/com/android/i18n/addressinput/AddressFieldTest.java12
-rw-r--r--java/test/com/android/i18n/addressinput/AddressProblemsTest.java22
-rw-r--r--java/test/com/android/i18n/addressinput/AddressVerificationDataTest.java144
-rw-r--r--java/test/com/android/i18n/addressinput/AddressWidgetUiComponentProviderTest.java210
-rw-r--r--java/test/com/android/i18n/addressinput/AsyncTestCaseTest.java88
-rw-r--r--java/test/com/android/i18n/addressinput/CacheDataTest.java534
-rw-r--r--java/test/com/android/i18n/addressinput/ClientDataTest.java90
-rw-r--r--java/test/com/android/i18n/addressinput/FieldVerifierTest.java527
-rw-r--r--java/test/com/android/i18n/addressinput/FormControllerTest.java244
-rw-r--r--java/test/com/android/i18n/addressinput/FormOptionsTest.java34
-rw-r--r--java/test/com/android/i18n/addressinput/FormatInterpreterTest.java350
-rw-r--r--java/test/com/android/i18n/addressinput/JsoMapTest.java376
-rw-r--r--java/test/com/android/i18n/addressinput/JsonpRequestBuilderTest.java240
-rw-r--r--java/test/com/android/i18n/addressinput/LookupKeyTest.java386
-rw-r--r--java/test/com/android/i18n/addressinput/RegionDataConstantsTest.java32
-rw-r--r--java/test/com/android/i18n/addressinput/RegionDataTest.java44
-rw-r--r--java/test/com/android/i18n/addressinput/StandardAddressVerifierTest.java462
-rw-r--r--java/test/com/android/i18n/addressinput/UtilTest.java230
70 files changed, 7926 insertions, 7601 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ece194c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.gradle
+cpp/out/
+java/**/build/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..12f8e91
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "externals/grit"]
+ path = externals/grit
+ url = https://chromium.googlesource.com/external/grit-i18n
+[submodule "externals/rapidjson"]
+ path = externals/rapidjson
+ url = https://github.com/miloyip/rapidjson.git
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..c42ee90
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,9 @@
+# This is the official list of libaddressinput authors for copyright purposes.
+# This file is distinct from the CONTRIBUTORS files.
+# See the latter for an explanation.
+
+# Names should be added to this file as:
+# Name or Organization <email address>
+# The email address is not required for organizations.
+
+Google Inc.
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
new file mode 100644
index 0000000..f8840a5
--- /dev/null
+++ b/CONTRIBUTORS
@@ -0,0 +1,20 @@
+# People who have agreed to one of the CLAs and can contribute patches.
+# The AUTHORS file lists the copyright holders; this file
+# lists people. For example, Google employees are listed here
+# but not in AUTHORS, because Google holds the copyright.
+#
+# https://developers.google.com/open-source/cla/individual
+# https://developers.google.com/open-source/cla/corporate
+#
+# Names should be added to this file as:
+# Name <email address>
+
+David Beaumont <dbeaumont@google.com>
+David Yonge-Mallo <davinci@google.com>
+Dong Zhou <dongzhou@google.com>
+Fredrik Roubert <roubert@google.com>
+Jeanine Lilleng <jeanine@google.com>
+Keghani Kouzoujian <keghani@google.com>
+Lara Scheidegger <lararennie@google.com>
+Rouslan Solomakhin <rouslan@chromium.org>
+Shaopeng Jia <shaopengjia@google.com>
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..15b0767
--- /dev/null
+++ b/README.md
@@ -0,0 +1,45 @@
+# ![](https://github.com/googlei18n/libaddressinput/wiki/libaddressinput-icon-70x55.png) libaddressinput
+
+[![Build Status](https://drone.io/github.com/googlei18n/libaddressinput/status.png)](https://drone.io/github.com/googlei18n/libaddressinput/latest)
+
+The _libaddressinput_ project consists of two different libraries (one
+implemented in C++, one implemented in Java for Android) that use
+[address metadata](https://github.com/googlei18n/libaddressinput/wiki/AddressValidationMetadata)
+from
+[Google](https://developers.google.com/)'s
+[I18n Services](https://i18napis.appspot.com/)
+[Address Data Service](https://i18napis.appspot.com/address)
+to assist application developers in collecting and handling _postal addresses_
+from all over the world.
+
+These libraries can provide information about what input fields are required for
+a correct address input form for any country in the world and can validate an
+address to highlight input errors like missing required fields or invalid
+values.
+
+## C++
+
+The C++ library (in very portable C++03) of _libaddressinput_ is the backend for
+[requestAutocomplete()](http://www.html5rocks.com/en/tutorials/forms/requestautocomplete/)
+in [Chromium](http://www.chromium.org/Home). The source code for that is a good
+example of how to use this library to implement a complex feature in a real
+application:
+
+https://src.chromium.org/viewvc/chrome/trunk/src/third_party/libaddressinput/
+https://chromium.googlesource.com/chromium/src/+/master/third_party/libaddressinput/
+
+Video: [Easy International Checkout with Chrome](https://www.youtube.com/watch?v=ljYeHwGgzQk)
+
+## Java
+
+The Java library of _libaddressinput_ is written for use in
+[Android](https://developer.android.com/) and includes an Android UI address
+input widget ready for use, but only the UI parts are tied to Android (all the
+non-UI unit tests can be readily run in Java SE, `ant junit`) and the rest of
+the library could easily be adapted to run in any Java environment.
+
+## Mailing List
+
+Using and developing libaddressinput is discussed on this mailing list:
+
+https://groups.google.com/forum/#!forum/libaddressinput-discuss
diff --git a/codereview.settings b/codereview.settings
deleted file mode 100644
index efe4f4e..0000000
--- a/codereview.settings
+++ /dev/null
@@ -1,4 +0,0 @@
-# This file is used by gcl to get repository specific information.
-CODE_REVIEW_SERVER: codereview.appspot.com
-TRY_ON_UPLOAD: False
-VIEW_VC: http://code.google.com/p/libaddressinput/source/detail?r=
diff --git a/cpp/README b/cpp/README
index 4dc96fe..d6fbf44 100644
--- a/cpp/README
+++ b/cpp/README
@@ -80,9 +80,3 @@ Test
This command will execute the unit tests for the library:
$ out/Default/unit_tests
-
-Discussion
-==========
-
-Do you need help with libaddressinput?
-https://groups.google.com/forum/#!forum/libaddressinput-discuss
diff --git a/cpp/res/messages.grdp b/cpp/res/messages.grdp
index 7ca2000..9ee43fe 100644
--- a/cpp/res/messages.grdp
+++ b/cpp/res/messages.grdp
@@ -29,6 +29,25 @@ limitations under the License.
City
</message>
<message
+ name="IDS_LIBADDRESSINPUT_POST_TOWN"
+ desc="The name of a town through
+ which postal deliveries are routed, present in UK addresses.
+ See: http://en.wikipedia.org/wiki/Post_town">
+ Post Town
+ </message>
+ <message
+ name="IDS_LIBADDRESSINPUT_SUBURB"
+ desc="Smaller part of a city used in some addresses in countries like New
+ Zealand to give a more specific location in a postal address.">
+ Suburb
+ </message>
+ <message
+ name="IDS_LIBADDRESSINPUT_VILLAGE_TOWNSHIP"
+ desc="A unit used in postal addresses in Malaysia, which is smaller than the
+ city/town, and represents a village, township, or precinct.">
+ Village / Township
+ </message>
+ <message
name="IDS_LIBADDRESSINPUT_ADDRESS_LINE_1_LABEL"
desc="E.g., 18th Street, Unit 3.">
Street address
@@ -125,6 +144,11 @@ limitations under the License.
Name
</message>
<message
+ name="IDS_LIBADDRESSINPUT_NEIGHBORHOOD"
+ desc="Label for a neighborhood, shown as part of an address input form.">
+ Neighborhood
+ </message>
+ <message
name="IDS_LIBADDRESSINPUT_MISSING_REQUIRED_FIELD"
desc="Error message shown with a UI field when it is a required field and
the user has not filled it out.">
diff --git a/cpp/src/address_ui.cc b/cpp/src/address_ui.cc
index 33f0797..5df8b3d 100644
--- a/cpp/src/address_ui.cc
+++ b/cpp/src/address_ui.cc
@@ -39,7 +39,9 @@ namespace {
std::string GetLabelForField(const Localization& localization,
AddressField field,
int admin_area_name_message_id,
- int postal_code_name_message_id) {
+ int postal_code_name_message_id,
+ int locality_name_message_id,
+ int sublocality_name_message_id) {
int messageId;
switch (field) {
case SORTING_CODE:
@@ -52,10 +54,10 @@ std::string GetLabelForField(const Localization& localization,
messageId = admin_area_name_message_id;
break;
case LOCALITY:
- messageId = IDS_LIBADDRESSINPUT_LOCALITY_LABEL;
+ messageId = locality_name_message_id;
break;
case DEPENDENT_LOCALITY:
- messageId = IDS_LIBADDRESSINPUT_DISTRICT;
+ messageId = sublocality_name_message_id;
break;
case POSTAL_CODE:
messageId = postal_code_name_message_id;
@@ -132,7 +134,9 @@ std::vector<AddressUiComponent> BuildComponents(
component.name = GetLabelForField(localization,
format_it->GetField(),
rule.GetAdminAreaNameMessageId(),
- rule.GetPostalCodeNameMessageId());
+ rule.GetPostalCodeNameMessageId(),
+ rule.GetLocalityNameMessageId(),
+ rule.GetSublocalityNameMessageId());
result.push_back(component);
}
diff --git a/cpp/src/region_data_constants.cc b/cpp/src/region_data_constants.cc
index e21d4b8..c91e6f8 100644
--- a/cpp/src/region_data_constants.cc
+++ b/cpp/src/region_data_constants.cc
@@ -51,8 +51,6 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"ca\""
"}"));
region_data.insert(std::make_pair("AE", "{"
- "\"fmt\":\"%N%n%O%n%A%n%C\","
- "\"require\":\"AC\","
"\"languages\":\"ar\""
"}"));
region_data.insert(std::make_pair("AF", "{"
@@ -199,9 +197,10 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"es~qu~ay\""
"}"));
region_data.insert(std::make_pair("BR", "{"
- "\"fmt\":\"%O%n%N%n%A%n%C-%S%n%Z\","
+ "\"fmt\":\"%O%n%N%n%A%n%D%n%C-%S%n%Z\","
"\"require\":\"ASCZ\","
"\"state_name_type\":\"state\","
+ "\"sublocality_name_type\":\"neighborhood\","
"\"zipex\":\"40301-110,70002-900\","
"\"posturl\":\"http://www.correios.com.br/servicos/cep/cep_default.cfm\","
"\"languages\":\"pt\""
@@ -224,7 +223,7 @@ std::map<std::string, std::string> InitRegionData() {
"}"));
region_data.insert(std::make_pair("BY", "{"
"\"fmt\":\"%S%n%Z %C %X%n%A%n%O%n%N\","
- "\"zipex\":\"20050,223016,225860,220050\","
+ "\"zipex\":\"223016,225860,220050\","
"\"posturl\":\"http://zip.belpost.by\","
"\"languages\":\"be~ru\""
"}"));
@@ -240,6 +239,7 @@ std::map<std::string, std::string> InitRegionData() {
"}"));
region_data.insert(std::make_pair("CC", "{"
"\"fmt\":\"%O%n%N%n%A%n%C %S %Z\","
+ "\"zipex\":\"6799\","
"\"languages\":\"en\""
"}"));
region_data.insert(std::make_pair("CD", "{"
@@ -264,7 +264,6 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"fr\""
"}"));
region_data.insert(std::make_pair("CK", "{"
- "\"fmt\":\"%N%n%O%n%A%n%C %Z\","
"\"languages\":\"en\""
"}"));
region_data.insert(std::make_pair("CL", "{"
@@ -281,6 +280,7 @@ std::map<std::string, std::string> InitRegionData() {
"\"fmt\":\"%Z%n%S%C%D%n%A%n%O%n%N\","
"\"lfmt\":\"%N%n%O%n%A%n%D%n%C%n%S, %Z\","
"\"require\":\"ACSZ\","
+ "\"sublocality_name_type\":\"district\","
"\"zipex\":\"266033,317204,100096,100808\","
"\"posturl\":\"http://www.cpdc.com.cn/postcdQueryAction.do\?reqCode=gotoQueryPostAddr\","
"\"languages\":\"zh-Hans\""
@@ -305,6 +305,7 @@ std::map<std::string, std::string> InitRegionData() {
"}"));
region_data.insert(std::make_pair("CX", "{"
"\"fmt\":\"%O%n%N%n%A%n%C %S %Z\","
+ "\"zipex\":\"6798\","
"\"languages\":\"en\""
"}"));
region_data.insert(std::make_pair("CY", "{"
@@ -351,12 +352,12 @@ std::map<std::string, std::string> InitRegionData() {
"}"));
region_data.insert(std::make_pair("EC", "{"
"\"fmt\":\"%N%n%O%n%A%n%Z%n%C\","
- "\"zipex\":\"EC090112,090105,H0103C,P0133B,P0133A,P0133V\","
+ "\"zipex\":\"090105,EC090112,H0103C,P0133B,P0133A,P0133V\","
"\"languages\":\"es\""
"}"));
region_data.insert(std::make_pair("EE", "{"
"\"fmt\":\"%N%n%O%n%A%n%Z %C\","
- "\"zipex\":\"69501,11212,1001\","
+ "\"zipex\":\"69501,11212\","
"\"posturl\":\"http://www.post.ee/\?op=sihtnumbriotsing\","
"\"languages\":\"et\""
"}"));
@@ -431,7 +432,8 @@ std::map<std::string, std::string> InitRegionData() {
"\"fmt\":\"%N%n%O%n%A%n%C%n%S%n%Z\","
"\"require\":\"ACZ\","
"\"state_name_type\":\"county\","
- "\"zipex\":\"EC1Y 8SY,GIR 0AA,M2 5BQ,M34 4AB,CR0 2YR,DN16 9AA,W1A 4ZZ,EC1A 1HQ,OX14 4PG,BS18 8HF,NR25 7HG,RH6 OHP,BH23 6AA,B6 5BA,RH6 0HP,SO23 9AP,PO1 3AX,BFPO 61\","
+ "\"locality_name_type\":\"post_town\","
+ "\"zipex\":\"EC1Y 8SY,GIR 0AA,M2 5BQ,M34 4AB,CR0 2YR,DN16 9AA,W1A 4ZZ,EC1A 1HQ,OX14 4PG,BS18 8HF,NR25 7HG,RH6 0NP,BH23 6AA,B6 5BA,SO23 9AP,PO1 3AX,BFPO 61\","
"\"posturl\":\"http://www.royalmail.com/postcode-finder\","
"\"languages\":\"en\""
"}"));
@@ -462,7 +464,7 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"en\""
"}"));
region_data.insert(std::make_pair("GI", "{"
- "\"fmt\":\"%N%n%O%n%A\","
+ "\"fmt\":\"%N%n%O%n%A%nGIBRALTAR%n%Z\","
"\"require\":\"A\","
"\"zipex\":\"GX11 1AA\","
"\"languages\":\"en\""
@@ -527,19 +529,22 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"en\""
"}"));
region_data.insert(std::make_pair("HK", "{"
- "\"fmt\":\"%S%n%A%n%O%n%N\","
- "\"lfmt\":\"%N%n%O%n%A%n%S\","
+ "\"fmt\":\"%S%n%C%n%A%n%O%n%N\","
+ "\"lfmt\":\"%N%n%O%n%A%n%C%n%S\","
"\"require\":\"AS\","
"\"state_name_type\":\"area\","
+ "\"locality_name_type\":\"district\","
"\"languages\":\"zh-Hant~en\""
"}"));
region_data.insert(std::make_pair("HM", "{"
"\"fmt\":\"%O%n%N%n%A%n%C %S %Z\","
+ "\"zipex\":\"7050\","
"\"languages\":\"\""
"}"));
region_data.insert(std::make_pair("HN", "{"
"\"fmt\":\"%N%n%O%n%A%n%C, %S%n%Z\","
"\"require\":\"ACS\","
+ "\"zipex\":\"31301\","
"\"languages\":\"es\""
"}"));
region_data.insert(std::make_pair("HR", "{"
@@ -600,6 +605,7 @@ std::map<std::string, std::string> InitRegionData() {
region_data.insert(std::make_pair("IQ", "{"
"\"fmt\":\"%O%n%N%n%A%n%C, %S%n%Z\","
"\"require\":\"ACS\","
+ "\"zipex\":\"31001\","
"\"languages\":\"ar\""
"}"));
region_data.insert(std::make_pair("IS", "{"
@@ -676,6 +682,7 @@ std::map<std::string, std::string> InitRegionData() {
"\"lfmt\":\"%N%n%O%n%A%n%D%n%C%n%S%n%Z\","
"\"require\":\"ACSZ\","
"\"state_name_type\":\"do_si\","
+ "\"sublocality_name_type\":\"district\","
"\"zipex\":\"110-110,699-800\","
"\"posturl\":\"http://www.epost.go.kr/search/zipcode/search5.jsp\","
"\"languages\":\"ko\""
@@ -686,7 +693,7 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"ar\""
"}"));
region_data.insert(std::make_pair("KY", "{"
- "\"fmt\":\"%N%n%O%n%A%n%S\","
+ "\"fmt\":\"%N%n%O%n%A%n%S %Z\","
"\"require\":\"AS\","
"\"state_name_type\":\"island\","
"\"zipex\":\"KY1-1100,KY1-1702,KY2-2101\","
@@ -864,20 +871,21 @@ std::map<std::string, std::string> InitRegionData() {
"\"fmt\":\"%N%n%O%n%A%n%D%n%Z %C, %S\","
"\"require\":\"ACZ\","
"\"state_name_type\":\"state\","
+ "\"sublocality_name_type\":\"neighborhood\","
"\"zipex\":\"02860,77520,06082\","
"\"posturl\":\"http://www.correosdemexico.gob.mx/ServiciosLinea/Paginas/ccpostales.aspx\","
"\"languages\":\"es\""
"}"));
region_data.insert(std::make_pair("MY", "{"
- "\"fmt\":\"%N%n%O%n%A%n%Z %C, %S\","
+ "\"fmt\":\"%N%n%O%n%A%n%D%n%Z %C%n%S\","
"\"require\":\"ACZ\","
"\"state_name_type\":\"state\","
+ "\"sublocality_name_type\":\"village_township\","
"\"zipex\":\"43000,50754,88990,50670\","
"\"posturl\":\"http://www.pos.com.my/pos/homepage.aspx\","
"\"languages\":\"ms\""
"}"));
region_data.insert(std::make_pair("MZ", "{"
- "\"fmt\":\"%N%n%O%n%A%n%C\","
"\"zipex\":\"1102,1119,3212\","
"\"languages\":\"pt\""
"}"));
@@ -898,6 +906,7 @@ std::map<std::string, std::string> InitRegionData() {
"}"));
region_data.insert(std::make_pair("NF", "{"
"\"fmt\":\"%O%n%N%n%A%n%C %S %Z\","
+ "\"zipex\":\"2899\","
"\"languages\":\"en\""
"}"));
region_data.insert(std::make_pair("NG", "{"
@@ -944,7 +953,7 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"en~niu\""
"}"));
region_data.insert(std::make_pair("NZ", "{"
- "\"fmt\":\"%N%n%O%n%A%n%C %Z\","
+ "\"fmt\":\"%N%n%O%n%A%n%D%n%C %Z\","
"\"require\":\"ACZ\","
"\"zipex\":\"6001,6015,6332,8252,1030\","
"\"posturl\":\"http://www.nzpost.co.nz/Cultures/en-NZ/OnlineTools/PostCodeFinder/\","
@@ -968,6 +977,7 @@ std::map<std::string, std::string> InitRegionData() {
"\"fmt\":\"%N%n%O%n%A%n%Z %C %S\","
"\"require\":\"ACSZ\","
"\"state_name_type\":\"island\","
+ "\"zipex\":\"98709\","
"\"languages\":\"fr~ty\""
"}"));
region_data.insert(std::make_pair("PG", "{"
@@ -977,7 +987,7 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"tpi~en~ho\""
"}"));
region_data.insert(std::make_pair("PH", "{"
- "\"fmt\":\"%N%n%O%n%A%n%Z %C%n%S\","
+ "\"fmt\":\"%N%n%O%n%A%n%D, %C%n%Z %S\","
"\"zipex\":\"1008,1050,1135,1207,2000,1000\","
"\"posturl\":\"http://www.philpost.gov.ph/\","
"\"languages\":\"en\""
@@ -1217,6 +1227,7 @@ std::map<std::string, std::string> InitRegionData() {
region_data.insert(std::make_pair("TR", "{"
"\"fmt\":\"%N%n%O%n%A%n%Z %C/%S\","
"\"require\":\"ACZ\","
+ "\"locality_name_type\":\"district\","
"\"zipex\":\"01960,06101\","
"\"posturl\":\"http://postakodu.ptt.gov.tr/\","
"\"languages\":\"tr\""
@@ -1248,7 +1259,7 @@ std::map<std::string, std::string> InitRegionData() {
"\"state_name_type\":\"oblast\","
"\"zipex\":\"15432,01055,01001\","
"\"posturl\":\"http://services.ukrposhta.com/postindex_new/\","
- "\"languages\":\"uk~ru\""
+ "\"languages\":\"uk\""
"}"));
region_data.insert(std::make_pair("UG", "{"
"\"languages\":\"sw~en\""
@@ -1301,6 +1312,7 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"es\""
"}"));
region_data.insert(std::make_pair("VG", "{"
+ "\"fmt\":\"%N%n%O%n%A%n%C%n%Z\","
"\"require\":\"A\","
"\"zipex\":\"VG1110,VG1150,VG1160\","
"\"languages\":\"en\""
@@ -1315,9 +1327,8 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"en\""
"}"));
region_data.insert(std::make_pair("VN", "{"
- "\"fmt\":\"%N%n%O%n%A%n%C%n%S\","
- "\"lfmt\":\"%N%n%O%n%A%n%C%n%S\","
- "\"require\":\"AC\","
+ "\"fmt\":\"%N%n%O%n%A%n%C%n%S %Z\","
+ "\"lfmt\":\"%N%n%O%n%A%n%C%n%S %Z\","
"\"zipex\":\"119415,136065,720344\","
"\"posturl\":\"http://postcode.vnpost.vn/services/search.aspx\","
"\"languages\":\"vi\""
@@ -1340,7 +1351,6 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"sq~sr-Cyrl~sr-Latn\""
"}"));
region_data.insert(std::make_pair("YE", "{"
- "\"require\":\"AC\","
"\"languages\":\"ar\""
"}"));
region_data.insert(std::make_pair("YT", "{"
@@ -1350,7 +1360,7 @@ std::map<std::string, std::string> InitRegionData() {
"\"languages\":\"fr\""
"}"));
region_data.insert(std::make_pair("ZA", "{"
- "\"fmt\":\"%N%n%O%n%A%n%C%n%Z\","
+ "\"fmt\":\"%N%n%O%n%A%n%D%n%C%n%Z\","
"\"require\":\"ACZ\","
"\"zipex\":\"0083,1451,0001\","
"\"posturl\":\"http://www.postoffice.co.za/tools/postalcode.html\","
@@ -1358,7 +1368,6 @@ std::map<std::string, std::string> InitRegionData() {
"}"));
region_data.insert(std::make_pair("ZM", "{"
"\"fmt\":\"%N%n%O%n%A%n%Z %C\","
- "\"require\":\"AC\","
"\"zipex\":\"50100,50101\","
"\"languages\":\"en\""
"}"));
@@ -1377,7 +1386,9 @@ const std::string& RegionDataConstants::GetDefaultRegionData() {
"\"fmt\":\"%N%n%O%n%A%n%C\","
"\"require\":\"AC\","
"\"zip_name_type\":\"postal\","
- "\"state_name_type\":\"province\""
+ "\"state_name_type\":\"province\","
+ "\"locality_name_type\":\"city\","
+ "\"sublocality_name_type\":\"suburb\""
"}");
return kDefaultRegionData;
}
diff --git a/cpp/src/rule.cc b/cpp/src/rule.cc
index 7ab84e5..12d1c78 100644
--- a/cpp/src/rule.cc
+++ b/cpp/src/rule.cc
@@ -91,6 +91,42 @@ const NameMessageIdMap& GetPostalCodeMessageIds() {
return kPostalCodeMessageIds;
}
+NameMessageIdMap InitLocalityMessageIds() {
+ NameMessageIdMap message_ids;
+ message_ids.insert(std::make_pair(
+ "city", IDS_LIBADDRESSINPUT_LOCALITY_LABEL));
+ message_ids.insert(std::make_pair(
+ "post_town", IDS_LIBADDRESSINPUT_POST_TOWN));
+ message_ids.insert(std::make_pair(
+ "district", IDS_LIBADDRESSINPUT_DISTRICT));
+ return message_ids;
+}
+
+const NameMessageIdMap& GetLocalityMessageIds() {
+ static const NameMessageIdMap kLocalityMessageIds(
+ InitLocalityMessageIds());
+ return kLocalityMessageIds;
+}
+
+NameMessageIdMap InitSublocalityMessageIds() {
+ NameMessageIdMap message_ids;
+ message_ids.insert(std::make_pair(
+ "suburb", IDS_LIBADDRESSINPUT_SUBURB));
+ message_ids.insert(std::make_pair(
+ "district", IDS_LIBADDRESSINPUT_DISTRICT));
+ message_ids.insert(std::make_pair(
+ "neighborhood", IDS_LIBADDRESSINPUT_NEIGHBORHOOD));
+ message_ids.insert(std::make_pair(
+ "village_township", IDS_LIBADDRESSINPUT_VILLAGE_TOWNSHIP));
+ return message_ids;
+}
+
+const NameMessageIdMap& GetSublocalityMessageIds() {
+ static const NameMessageIdMap kSublocalityMessageIds(
+ InitSublocalityMessageIds());
+ return kSublocalityMessageIds;
+}
+
int GetMessageIdFromName(const std::string& name,
const NameMessageIdMap& message_ids) {
NameMessageIdMap::const_iterator it = message_ids.find(name);
@@ -118,6 +154,8 @@ Rule::Rule()
sole_postal_code_(),
admin_area_name_message_id_(INVALID_MESSAGE_ID),
postal_code_name_message_id_(INVALID_MESSAGE_ID),
+ locality_name_message_id_(INVALID_MESSAGE_ID),
+ sublocality_name_message_id_(INVALID_MESSAGE_ID),
name_(),
latin_name_(),
postal_code_example_(),
@@ -153,6 +191,8 @@ void Rule::CopyFrom(const Rule& rule) {
sole_postal_code_ = rule.sole_postal_code_;
admin_area_name_message_id_ = rule.admin_area_name_message_id_;
postal_code_name_message_id_ = rule.postal_code_name_message_id_;
+ locality_name_message_id_ = rule.locality_name_message_id_;
+ sublocality_name_message_id_ = rule.sublocality_name_message_id_;
name_ = rule.name_;
latin_name_ = rule.latin_name_;
postal_code_example_ = rule.postal_code_example_;
@@ -233,6 +273,16 @@ void Rule::ParseJsonRule(const Json& json) {
GetMessageIdFromName(value, GetPostalCodeMessageIds());
}
+ if (json.GetStringValueForKey("locality_name_type", &value)) {
+ locality_name_message_id_ =
+ GetMessageIdFromName(value, GetLocalityMessageIds());
+ }
+
+ if (json.GetStringValueForKey("sublocality_name_type", &value)) {
+ sublocality_name_message_id_ =
+ GetMessageIdFromName(value, GetSublocalityMessageIds());
+ }
+
if (json.GetStringValueForKey("name", &value)) {
name_.swap(value);
}
diff --git a/cpp/src/rule.h b/cpp/src/rule.h
index 1286bcb..87948df 100644
--- a/cpp/src/rule.h
+++ b/cpp/src/rule.h
@@ -15,7 +15,7 @@
// An object to store address metadata, describing the addressing rules for
// regions and sub-regions. The address metadata format is documented here:
//
-// https://code.google.com/p/libaddressinput/wiki/AddressValidationMetadata
+// https://github.com/googlei18n/libaddressinput/wiki/AddressValidationMetadata
#ifndef I18N_ADDRESSINPUT_RULE_H_
#define I18N_ADDRESSINPUT_RULE_H_
@@ -110,6 +110,18 @@ class Rule {
return postal_code_name_message_id_;
}
+ // The message string identifier for locality name. If not set, then
+ // INVALID_MESSAGE_ID.
+ int GetLocalityNameMessageId() const {
+ return locality_name_message_id_;
+ }
+
+ // The message string identifier for sublocality name. If not set, then
+ // INVALID_MESSAGE_ID.
+ int GetSublocalityNameMessageId() const {
+ return sublocality_name_message_id_;
+ }
+
// Returns the name for the most specific place described by this rule, if
// there is one. This is typically set when it differs from the key.
const std::string& GetName() const { return name_; }
@@ -137,6 +149,8 @@ class Rule {
std::string sole_postal_code_;
int admin_area_name_message_id_;
int postal_code_name_message_id_;
+ int locality_name_message_id_;
+ int sublocality_name_message_id_;
std::string name_;
std::string latin_name_;
std::string postal_code_example_;
diff --git a/cpp/src/util/json.cc b/cpp/src/util/json.cc
index 730479c..9d30b66 100644
--- a/cpp/src/util/json.cc
+++ b/cpp/src/util/json.cc
@@ -68,7 +68,7 @@ class Json::JsonImpl {
assert(value != NULL);
Value::ConstMemberIterator member = value_->FindMember(key.c_str());
- if (member == NULL || !member->value.IsString()) {
+ if (member == value_->MemberEnd() || !member->value.IsString()) {
return false;
}
diff --git a/cpp/test/region_data_constants_test.cc b/cpp/test/region_data_constants_test.cc
index 63e6ae2..71d473d 100644
--- a/cpp/test/region_data_constants_test.cc
+++ b/cpp/test/region_data_constants_test.cc
@@ -88,7 +88,7 @@ INSTANTIATE_TEST_CASE_P(
TEST(RegionDataConstantsTest, GetMaxLookupKeyDepth) {
EXPECT_EQ(0, RegionDataConstants::GetMaxLookupKeyDepth("NZ"));
- EXPECT_EQ(1, RegionDataConstants::GetMaxLookupKeyDepth("HK"));
+ EXPECT_EQ(1, RegionDataConstants::GetMaxLookupKeyDepth("KY"));
EXPECT_EQ(2, RegionDataConstants::GetMaxLookupKeyDepth("US"));
EXPECT_EQ(3, RegionDataConstants::GetMaxLookupKeyDepth("CN"));
}
diff --git a/cpp/test/rule_test.cc b/cpp/test/rule_test.cc
index 7c5a0c5..5f61ce4 100644
--- a/cpp/test/rule_test.cc
+++ b/cpp/test/rule_test.cc
@@ -46,21 +46,24 @@ using i18n::addressinput::STREET_ADDRESS;
TEST(RuleTest, CopyOverwritesRule) {
Rule rule;
- ASSERT_TRUE(rule.ParseSerializedRule("{"
- "\"fmt\":\"%S%Z\","
- "\"lfmt\":\"%Z%S\","
- "\"id\":\"data/XA\","
- "\"name\":\"Le Test\","
- "\"lname\":\"Testistan\","
- "\"require\":\"AC\","
- "\"sub_keys\":\"aa~bb~cc\","
- "\"languages\":\"en~fr\","
- "\"zip\":\"\\\\d{3}\","
- "\"state_name_type\":\"area\","
- "\"zip_name_type\":\"postal\","
- "\"zipex\":\"1234\","
- "\"posturl\":\"http://www.testpost.com\""
- "}"));
+ ASSERT_TRUE(rule.ParseSerializedRule(
+ "{"
+ "\"fmt\":\"%S%Z\","
+ "\"lfmt\":\"%Z%S\","
+ "\"id\":\"data/XA\","
+ "\"name\":\"Le Test\","
+ "\"lname\":\"Testistan\","
+ "\"require\":\"AC\","
+ "\"sub_keys\":\"aa~bb~cc\","
+ "\"languages\":\"en~fr\","
+ "\"zip\":\"\\\\d{3}\","
+ "\"state_name_type\":\"area\","
+ "\"locality_name_type\":\"post_town\","
+ "\"sublocality_name_type\":\"neighborhood\","
+ "\"zip_name_type\":\"postal\","
+ "\"zipex\":\"1234\","
+ "\"posturl\":\"http://www.testpost.com\""
+ "}"));
Rule copy;
EXPECT_NE(rule.GetFormat(), copy.GetFormat());
@@ -73,6 +76,10 @@ TEST(RuleTest, CopyOverwritesRule) {
copy.GetAdminAreaNameMessageId());
EXPECT_NE(rule.GetPostalCodeNameMessageId(),
copy.GetPostalCodeNameMessageId());
+ EXPECT_NE(rule.GetLocalityNameMessageId(),
+ copy.GetLocalityNameMessageId());
+ EXPECT_NE(rule.GetSublocalityNameMessageId(),
+ copy.GetSublocalityNameMessageId());
EXPECT_NE(rule.GetName(), copy.GetName());
EXPECT_NE(rule.GetLatinName(), copy.GetLatinName());
EXPECT_NE(rule.GetPostalCodeExample(), copy.GetPostalCodeExample());
@@ -92,6 +99,10 @@ TEST(RuleTest, CopyOverwritesRule) {
copy.GetAdminAreaNameMessageId());
EXPECT_EQ(rule.GetPostalCodeNameMessageId(),
copy.GetPostalCodeNameMessageId());
+ EXPECT_EQ(rule.GetSublocalityNameMessageId(),
+ copy.GetSublocalityNameMessageId());
+ EXPECT_EQ(rule.GetLocalityNameMessageId(),
+ copy.GetLocalityNameMessageId());
EXPECT_EQ(rule.GetName(), copy.GetName());
EXPECT_EQ(rule.GetLatinName(), copy.GetLatinName());
EXPECT_EQ(rule.GetPostalCodeExample(), copy.GetPostalCodeExample());
@@ -264,6 +275,64 @@ INSTANTIATE_TEST_CASE_P(
std::make_pair("{\"zip_name_type\":\"zip\"}",
IDS_LIBADDRESSINPUT_ZIP_CODE_LABEL)));
+// Tests for parsing the locality name.
+class LocalityNameParseTest
+ : public testing::TestWithParam<std::pair<std::string, int> > {
+ protected:
+ LocalityNameParseTest() {}
+ Rule rule_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LocalityNameParseTest);
+};
+
+// Verifies that a locality name is parsed correctly.
+TEST_P(LocalityNameParseTest, ParsedCorrectly) {
+ ASSERT_TRUE(rule_.ParseSerializedRule(GetParam().first));
+ EXPECT_EQ(GetParam().second, rule_.GetLocalityNameMessageId());
+}
+
+// Test parsing all locality names.
+INSTANTIATE_TEST_CASE_P(
+ AllLocalityNames, LocalityNameParseTest,
+ testing::Values(
+ std::make_pair("{\"locality_name_type\":\"post_town\"}",
+ IDS_LIBADDRESSINPUT_POST_TOWN),
+ std::make_pair("{\"locality_name_type\":\"city\"}",
+ IDS_LIBADDRESSINPUT_LOCALITY_LABEL),
+ std::make_pair("{\"locality_name_type\":\"district\"}",
+ IDS_LIBADDRESSINPUT_DISTRICT)));
+
+// Tests for parsing the locality name.
+class SublocalityNameParseTest
+ : public testing::TestWithParam<std::pair<std::string, int> > {
+ protected:
+ SublocalityNameParseTest() {}
+ Rule rule_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SublocalityNameParseTest);
+};
+
+// Verifies that a sublocality name is parsed correctly.
+TEST_P(SublocalityNameParseTest, ParsedCorrectly) {
+ ASSERT_TRUE(rule_.ParseSerializedRule(GetParam().first));
+ EXPECT_EQ(GetParam().second, rule_.GetSublocalityNameMessageId());
+}
+
+// Test parsing all sublocality names.
+INSTANTIATE_TEST_CASE_P(
+ AllSublocalityNames, SublocalityNameParseTest,
+ testing::Values(
+ std::make_pair("{\"sublocality_name_type\":\"village_township\"}",
+ IDS_LIBADDRESSINPUT_VILLAGE_TOWNSHIP),
+ std::make_pair("{\"sublocality_name_type\":\"neighborhood\"}",
+ IDS_LIBADDRESSINPUT_NEIGHBORHOOD),
+ std::make_pair("{\"sublocality_name_type\":\"suburb\"}",
+ IDS_LIBADDRESSINPUT_SUBURB),
+ std::make_pair("{\"sublocality_name_type\":\"district\"}",
+ IDS_LIBADDRESSINPUT_DISTRICT)));
+
// Tests for parsing the administrative area name.
class AdminAreaNameParseTest
: public testing::TestWithParam<std::pair<std::string, int> > {
@@ -355,6 +424,30 @@ TEST_P(RuleParseTest, PostalCodeNameTypeHasUiString) {
}
}
+// Verifies that the locality name type corresponds to a UI string.
+TEST_P(RuleParseTest, LocalityNameTypeHasUiString) {
+ const std::string& region_data = GetRegionData();
+ rule_.ParseSerializedRule(region_data);
+ // The leading quote here ensures we don't match against sublocality_name_type
+ // in the data.
+ if (region_data.find("\"locality_name_type") != std::string::npos) {
+ EXPECT_NE(INVALID_MESSAGE_ID, rule_.GetLocalityNameMessageId());
+ EXPECT_FALSE(
+ localization_.GetString(rule_.GetLocalityNameMessageId()).empty());
+ }
+}
+
+// Verifies that the sublocality name type corresponds to a UI string.
+TEST_P(RuleParseTest, SublocalityNameTypeHasUiString) {
+ const std::string& region_data = GetRegionData();
+ rule_.ParseSerializedRule(region_data);
+ if (region_data.find("sublocality_name_type") != std::string::npos) {
+ EXPECT_NE(INVALID_MESSAGE_ID, rule_.GetSublocalityNameMessageId());
+ EXPECT_FALSE(
+ localization_.GetString(rule_.GetSublocalityNameMessageId()).empty());
+ }
+}
+
// Verifies that the sole postal code is correctly recognised and copied.
TEST_P(RuleParseTest, SolePostalCode) {
Rule rule;
diff --git a/externals/grit b/externals/grit
new file mode 160000
+Subproject 77abf65c1d72af6fb7f9ef6f50cdf29fcf42d0a
diff --git a/externals/rapidjson b/externals/rapidjson
new file mode 160000
+Subproject d0f98d2da1e2e6345831dc1ab2c30950417e649
diff --git a/java/README b/java/README
new file mode 100644
index 0000000..c7ef026
--- /dev/null
+++ b/java/README
@@ -0,0 +1,35 @@
+Building and running tests with Android
+=======================================
+
+The easiest way to build libaddressinput for Android and run all the tests is
+using the Gradle project automation tool:
+
+http://tools.android.com/tech-docs/new-build-system
+http://www.gradle.org/
+
+With an Android emulator running or an Android device connected, the following
+command line then builds the library and runs the tests:
+
+$ gradle connectedInstrumentTest
+
+The test runner logs to the system log, which can be viewed using logcat:
+
+$ adb logcat
+
+Building and running tests with Java SE
+=======================================
+
+Large parts of the library and tests are not Android specific and those can be
+built and run in a standard Java SE environment using the Ant build tool:
+
+http://ant.apache.org/
+
+The following command line then builds those parts of the library and runs the
+corresponding tests:
+
+$ ant junit
+
+The test runner logs to XML files in the build/junitreport directory, which can
+be formatted into human-friendly HTML (build/junitreport/index.html) like this:
+
+$ ant junitreport
diff --git a/java/res/values/address_strings.xml b/java/res/values/address_strings.xml
index f12247a..f6ae180 100644
--- a/java/res/values/address_strings.xml
+++ b/java/res/values/address_strings.xml
@@ -31,135 +31,117 @@
server. The u2026 is the unicode character for the ellipses (...) -->
<string name="address_data_loading">Loading\u2026</string>
+ <!-- Message shown for a dropdown menu in which nothing is yet selected. -->
+ <string name="please_select">Please select</string>
+
<!-- Strings below this point are address-specific and relate either to
labels for input fields or to error messages that the widget may report. -->
- <!-- A country or a political region (countries like the United States or
- regions like Hong Kong) [CHAR LIMIT=30] -->
- <string name="i18n_country_label">Country</string>
+ <!-- A country or a political region (Countries like the United States or
+ regions like Hong Kong or Macao, or places like Taiwan, where whether it is
+ a country or not is a politically sensitive question). [CHAR LIMIT=30] -->
+ <string name="i18n_country_or_region_label">Country / Region</string>
<!-- A city or town, such as New York City [CHAR LIMIT=30] -->
<string name="i18n_locality_label">City</string>
- <!-- Area of a town (a neighbourhood/suburb) used for addresses in Korea and
- China, or a district of a country such as Nauru [CHAR LIMIT=30] -->
- <string name="i18n_dependent_locality_label">District</string>
+ <!-- The name of a town through which postal deliveries are routed, present
+ in UK addresses.
+ See: http://en.wikipedia.org/wiki/Post_town [CHAR LIMIT=30] -->
+ <string name="i18n_post_town">Post Town</string>
- <!-- Company/Organization of the address [CHAR LIMIT=30] -->
- <string name="i18n_organization_label">Company</string>
+ <!-- Smaller part of a city used in some addresses in countries like New
+ Zealand to give a more specific location in a postal address. [CHAR LIMIT=30] -->
+ <string name="i18n_suburb">Suburb</string>
- <!-- Label indicating the person to be contacted as part of this address, to
- be used for example as "Contact Name: John Doe".[CHAR LIMIT=30] -->
- <string name="i18n_recipient_label">Contact Name</string>
+ <!-- A unit used in postal addresses in Malaysia, which is smaller than the
+ city/town, and represents a village, township, or precinct. [CHAR LIMIT=30] -->
+ <string name="i18n_village_township">Village / Township</string>
- <!-- Street-level part of an address, e.g., 18th Street, Unit 3 [CHAR LIMIT=30] -->
- <string name="i18n_address_line1_label">Street Address</string>
+ <!-- Street-level part of an address, e.g. "18th Street, Unit 3". [CHAR LIMIT=30] -->
+ <string name="i18n_address_line1_label">Street address</string>
- <!-- Postal Code. Values are frequently alphanumeric. [CHAR LIMIT=30] -->
- <string name="i18n_postal_code_label">Postal Code</string>
+ <!-- Postal Code. Values are frequently alphanumeric. Used in countries such as Switzerland.
+ [CHAR LIMIT=30] -->
+ <string name="i18n_postal_code_label">Postal code</string>
- <!-- Label to represent ZIP codes, used in countries like the US. [CHAR LIMIT=30] -->
- <string name="i18n_zip_code_label">ZIP Code</string>
+ <!-- ZIP code. Used in countries like the US. [CHAR LIMIT=30] -->
+ <string name="i18n_zip_code_label">ZIP code</string>
- <!-- Administrative Area for Hong Kong (e.g., Kowloon) [CHAR LIMIT=30] -->
+ <!-- Administrative Area for Hong Kong (e.g. Kowloon). [CHAR LIMIT=30] -->
<string name="i18n_area">Area</string>
- <!-- Administrative Area for the United Kingdom (e.g., Yorkshire) [CHAR LIMIT=30] -->
- <string name="i18n_county_label">County</string>
+ <!-- Administrative Area for the United Kingdom (e.g. Yorkshire). [CHAR LIMIT=30] -->
+ <string name="i18n_county">County</string>
- <!-- Administrative Area, as used for countries like Nicaragua (e.g., Boaco)
+ <!-- Administrative Area, as used for countries like Nicaragua (e.g. Boaco).
[CHAR LIMIT=30] -->
<string name="i18n_department">Department</string>
- <!-- Administrative Area for Korea (e.g., Gyeonggi-do or Busan-si) [CHAR LIMIT=30] -->
- <string name="i18n_do_si">Do</string>
+ <!-- Administrative Area for Nauru Central Pacific (e.g. Aiwo district), or
+ area of a town (a neighborhood/suburb) used for addresses in Korea and
+ China. [CHAR LIMIT=30] -->
+ <string name="i18n_district">District</string>
+
+ <!-- Administrative Area for Korea (e.g. Gyeonggi-do or Busan-si). [CHAR LIMIT=30] -->
+ <string name="i18n_do_si">Do/Si</string>
- <!-- Administrative Area for United Arab Emirates (e.g., Abu Dhabi) [CHAR LIMIT=30] -->
+ <!-- Administrative Area for United Arab Emirates (e.g. Abu Dhabi). [CHAR LIMIT=30] -->
<string name="i18n_emirate">Emirate</string>
- <!-- Administrative Area for certain countries (e.g., Bahama's Cat Island) [CHAR LIMIT=30] -->
+ <!-- Administrative Area for certain countries (e.g. Bahama's Cat Island). [CHAR LIMIT=30] -->
<string name="i18n_island">Island</string>
- <!-- Administrative Area for certain countries (e.g., Russia's Leningrad) [CHAR LIMIT=30] -->
+ <!-- Administrative Area for certain countries (e.g. Russia's Leningrad). [CHAR LIMIT=30] -->
<string name="i18n_oblast">Oblast</string>
- <!-- Administrative Area for certain countries (e.g., Andorra's Canillo) [CHAR LIMIT=30] -->
+ <!-- Administrative Area for certain countries (e.g. Andorra's Canillo). [CHAR LIMIT=30] -->
<string name="i18n_parish">Parish</string>
- <!-- Administrative Area for Japan (e.g., Hokkaido) [CHAR LIMIT=30] -->
+ <!-- Administrative Area for Japan (e.g. Hokkaido). [CHAR LIMIT=30] -->
<string name="i18n_prefecture">Prefecture</string>
- <!-- Administrative Area for certain countries (e.g., France's Champagne) [CHAR LIMIT=30] -->
+ <!-- Administrative Area for certain countries (e.g. Canada's Ontario). [CHAR LIMIT=30] -->
<string name="i18n_province">Province</string>
- <!-- Administrative Area for certain countries (e.g., US' California) [CHAR LIMIT=30] -->
- <string name="i18n_state_label">State</string>
-
- <!-- Message to be shown when a required field is empty [CHAR LIMIT=30] -->
- <string name="i18n_missing_required_field">Required</string>
-
- <!-- Message to be shown when the value entered by the user in a given field is invalid
- [CHAR LIMIT=30] -->
- <string name="invalid_entry">Invalid entry</string>
-
- <!-- Message to be shown when a city or town entered by the user, such as
- New York City, is invalid. [CHAR LIMIT=30] -->
- <string name="invalid_locality_label">Invalid city</string>
+ <!-- Administrative Area for certain countries (e.g. California in the USA). [CHAR LIMIT=30] -->
+ <string name="i18n_state">State</string>
- <!-- Message to be shown when an area of a city which is entered by the user (a
- neighbourhood/suburb), is invalid. Used for addresses in Korea and
- China, or for districts of a country such as Nauru [CHAR LIMIT=30] -->
- <string name="invalid_dependent_locality_label">Invalid district</string>
-
- <!-- Message to be shown when an incorrect postal code is entered by the user. Postal codes
- are used in countries like New Zealand. [CHAR LIMIT=30] -->
- <string name="invalid_postal_code_label">Invalid postal code</string>
-
- <!-- Message to be shown when an incorrect ZIP code is entered by the user.
- ZIP codes are used in countries like the US. [CHAR LIMIT=30] -->
- <string name="invalid_zip_code_label">Invalid ZIP code</string>
-
- <!-- Message to be shown when the administrative area for Hong Kong (e.g., Kowloon)
- is entered incorrectly by the user [CHAR LIMIT=30] -->
- <string name="invalid_area">Invalid area</string>
-
- <!-- Message to be shown when the administrative area (county) for the United Kingdom
- is entered incorrectly by the user [CHAR LIMIT=30] -->
- <string name="invalid_county_label">Invalid county</string>
-
- <!-- Message to be shown when the administrative area (department) used for countries like
- Nicaragua (e.g., Boaco) is entered incorrectly by the user [CHAR LIMIT=30] -->
- <string name="invalid_department">Invalid department</string>
+ <!-- Label indicating the person to be contacted as part of this address, to
+ be used for example as "Name: John Doe". [CHAR LIMIT=30] -->
+ <string name="i18n_recipient_label">Name</string>
- <!-- Message to be shown when the administrative area for Korea (e.g., Gyeonggi-do or Busan-si)
- is entered incorrectly by the user [CHAR LIMIT=30] -->
- <string name="invalid_do_si">Invalid do</string>
+ <!-- Label for a neighborhood, shown as part of an address input form. [CHAR LIMIT=30] -->
+ <string name="i18n_neighborhood">Neighborhood</string>
- <!-- Message to be shown when the administrative area (emirate) for United Arab Emirates
- (e.g., Abu Dhabi) is entered incorrectly by the user [CHAR LIMIT=30] -->
- <string name="invalid_emirate">Invalid emirate</string>
+ <!-- Label for the field of organization, firm, company, or institution in an address. Examples
+ of values in this field: Google, Department of Transportation, University of Cambridge.
+ [CHAR LIMIT=30] -->
+ <string name="i18n_organization_label">Organization</string>
- <!-- Message to be shown when the administrative area (island) for certain countries
- (e.g., Bahama) is entered incorrectly by the user [CHAR LIMIT=30] -->
- <string name="invalid_island">Invalid island</string>
+ <!-- Error message shown with a UI field when it is a required field and the user has not filled
+ it out. [CHAR LIMIT=30] -->
+ <string name="i18n_missing_required_field">You can\u0027t leave this empty.</string>
- <!-- Message to be shown when the administrative area (oblast) for certain countries
- (e.g., Russia) is entered incorrectly by the user [CHAR LIMIT=30] -->
- <string name="invalid_oblast">Invalid oblast</string>
+ <!-- Occurs when the user fills out the wrong value for an address field. For example, this
+ would be shown when putting 'Cupertino' in United States' State field. [CHAR LIMIT=60] -->
+ <string name="unknown_entry">%1$s is not recognized as a known value for this field.</string>
- <!-- Message to be shown when the administrative area (parish) for certain countries
- (e.g., Andorra) is entered incorrectly by the user [CHAR LIMIT=30] -->
- <string name="invalid_parish">Invalid parish</string>
+ <!-- Occurs when the user fills out a postal code that does not conform to the country's postal
+ code format. For example, this would be shown when using '80' as a Swiss postal code, which
+ is normally 4 digits long. [CHAR LIMIT=60] -->
+ <string name="unrecognized_format_postal_code">This postal code format is not recognized.</string>
- <!-- Message to be shown when the administrative area (prefecture) for Japan (e.g., Hokkaido)
- is entered incorrectly by the user [CHAR LIMIT=30] -->
- <string name="invalid_prefecture">Invalid prefecture</string>
+ <!-- Occurs when the user fills out a ZIP code that does not conform to the country's ZIP
+ code format. For example, this would be shown when using '901' as a ZIP code for the United
+ States. [CHAR LIMIT=60] -->
+ <string name="unrecognized_format_zip_code">This ZIP code format is not recognized.</string>
- <!-- Message to be shown when the administrative area (province) for certain countries
- (e.g., France's Champagne) is entered incorrectly by the user [CHAR LIMIT=30] -->
- <string name="invalid_province">Invalid province</string>
+ <!-- Occurs when the user fills out the wrong postal code for a certain location. For example,
+ this would be shown when using Z3Z 2Y7 for Alberta, Canada. [CHAR LIMIT=70] -->
+ <string name="mismatching_value_postal_code">This postal code does not appear to match the rest of this address.</string>
- <!-- Message to be shown when the administrative area (state) for certain countries
- (e.g., the USA) is entered incorrectly by the user [CHAR LIMIT=30] -->
- <string name="invalid_state_label">Invalid state</string>
+ <!-- Occurs when the user fills out the wrong ZIP code for a certain location. For example,
+ this would be shown when using 10001 for Arizona state. [CHAR LIMIT=70] -->
+ <string name="mismatching_value_zip_code">This ZIP code does not appear to match the rest of this address.</string>
</resources>
diff --git a/java/src/AndroidManifest.xml b/java/src/AndroidManifest.xml
index c3d022e..cf738f3 100644
--- a/java/src/AndroidManifest.xml
+++ b/java/src/AndroidManifest.xml
@@ -6,5 +6,6 @@
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
+ <application/>
</manifest>
diff --git a/java/src/com/android/i18n/addressinput/AddressData.java b/java/src/com/android/i18n/addressinput/AddressData.java
index fc039a2..7e53d10 100644
--- a/java/src/com/android/i18n/addressinput/AddressData.java
+++ b/java/src/com/android/i18n/addressinput/AddressData.java
@@ -54,341 +54,341 @@ import java.util.Map;
* or a string consists of only spaces, it will not be set.
*/
public class AddressData {
- // CLDR (Common Locale Data Repository) country code.
- // For example, "US" for United States.
- // (Note: Use "GB", not "UK", for Great Britain)
- private final String mPostalCountry;
-
- // street street, line 1
- private final String mAddressLine1;
-
- // street street, line 2
- private final String mAddressLine2;
-
- // Top-level administrative subdivision of this country.
- // Examples: US state, IT region, UK constituent nation, JP prefecture.
- private final String mAdministrativeArea;
-
- // Locality. A fuzzy term, but it generally refers to
- // the city/town portion of an address. In regions of the world where
- // localities are not well defined or do not fit into this structure well
- // (for example, Japan and China), leave locality empty and use
- // addressLine1.
- // Examples: US city, IT comune, UK post town.
- private final String mLocality;
-
- // Dependent locality or sublocality. Used for UK dependent localities,
- // or neighborhoods or boroughs in other locations. If trying to
- // represent a UK double-dependent locality, include both the
- // double-dependent locality and the dependent locality in this field,
- // e.g. "Whaley, Langwith".
- private final String mDependentLocality;
-
- // Postal Code. values are frequently alphanumeric.
- // Examples: "94043", "94043-1351", "SW1W", "SW1W 9TQ".
- private final String mPostalCode;
-
- // Sorting code - use is very country-specific.
- // This corresponds to the SortingCode sub-element of the xAL
- // PostalServiceElements element.
- // Examples: FR CEDEX.
- private final String mSortingCode;
-
- // The firm or organization. This goes at a finer granularity than
- // address lines in the address. Omit if not needed.
- private final String mOrganization;
-
- // The recipient. This goes at a finer granularity than address lines
- // in the address. Not present in xAL. Omit if not needed.
- private final String mRecipient;
-
- // Language code of the address. Can be set to null. See its getter and setter
- // for more information.
- private final String mLanguageCode;
+ // CLDR (Common Locale Data Repository) country code.
+ // For example, "US" for United States.
+ // (Note: Use "GB", not "UK", for Great Britain)
+ private final String postalCountry;
+
+ // street street, line 1
+ private final String addressLine1;
+
+ // street street, line 2
+ private final String addressLine2;
+
+ // Top-level administrative subdivision of this country.
+ // Examples: US state, IT region, UK constituent nation, JP prefecture.
+ private final String administrativeArea;
+
+ // Locality. A fuzzy term, but it generally refers to
+ // the city/town portion of an address. In regions of the world where
+ // localities are not well defined or do not fit into this structure well
+ // (for example, Japan and China), leave locality empty and use
+ // addressLine1.
+ // Examples: US city, IT comune, UK post town.
+ private final String locality;
+
+ // Dependent locality or sublocality. Used for UK dependent localities,
+ // or neighborhoods or boroughs in other locations. If trying to
+ // represent a UK double-dependent locality, include both the
+ // double-dependent locality and the dependent locality in this field,
+ // e.g. "Whaley, Langwith".
+ private final String dependentLocality;
+
+ // Postal Code. values are frequently alphanumeric.
+ // Examples: "94043", "94043-1351", "SW1W", "SW1W 9TQ".
+ private final String postalCode;
+
+ // Sorting code - use is very country-specific.
+ // This corresponds to the SortingCode sub-element of the xAL
+ // PostalServiceElements element.
+ // Examples: FR CEDEX.
+ private final String sortingCode;
+
+ // The firm or organization. This goes at a finer granularity than
+ // address lines in the address. Omit if not needed.
+ private final String organization;
+
+ // The recipient. This goes at a finer granularity than address lines
+ // in the address. Not present in xAL. Omit if not needed.
+ private final String recipient;
+
+ // Language code of the address. Can be set to null. See its getter and setter
+ // for more information.
+ private final String languageCode;
+
+ /**
+ * Use {@link Builder} to create instances.
+ */
+ private AddressData(Builder builder) {
+ postalCountry = builder.values.get(AddressField.COUNTRY);
+ administrativeArea = builder.values.get(AddressField.ADMIN_AREA);
+ locality = builder.values.get(AddressField.LOCALITY);
+ dependentLocality = builder.values.get(AddressField.DEPENDENT_LOCALITY);
+ postalCode = builder.values.get(AddressField.POSTAL_CODE);
+ sortingCode = builder.values.get(AddressField.SORTING_CODE);
+ organization = builder.values.get(AddressField.ORGANIZATION);
+ recipient = builder.values.get(AddressField.RECIPIENT);
+ addressLine1 = builder.values.get(AddressField.ADDRESS_LINE_1);
+ addressLine2 = builder.values.get(AddressField.ADDRESS_LINE_2);
+ languageCode = builder.language;
+ }
+
+ /**
+ * Returns the postal country.
+ *
+ * <p>The returned value is not user-presentable. For example, {@code getPostalCountry()} may
+ * return {@code "GB"}, while addresses in Great Britain should be displayed using "UK".
+ */
+ public String getPostalCountry() {
+ return postalCountry;
+ }
+
+ public String getAddressLine1() {
+ return addressLine1;
+ }
+
+ public String getAddressLine2() {
+ return addressLine2;
+ }
+
+ /**
+ * Returns the top-level administrative subdivision of this country. Different postal countries
+ * use different names to refer to their administrative areas. For example, this is called
+ * "state" in the United States, "region" in Italy, "constituent nation" in Great Britain, or
+ * "prefecture" in Japan.
+ */
+ public String getAdministrativeArea() {
+ return administrativeArea;
+ }
+
+ /**
+ * Returns the locality. The usage of this field varies by region, but it generally refers to
+ * the "city" or "town" of the address. Some regions do not use this field; their address lines
+ * are sufficient to locate an address within a sub-administrative area. For example, this is
+ * called "city" in the United States, "comune" in Italy, or "post town" in Great Britain.
+ */
+ public String getLocality() {
+ return locality;
+ }
+
+ /**
+ * Returns the dependent locality.
+ *
+ * <p>This is used for Great Britain dependent localities, or neighborhoods or boroughs in other
+ * locations.
+ *
+ * <p>In cases such as Great Britain, this field may contain a double-dependent locality, such
+ * as "Whaley, Langwith".
+ */
+ public String getDependentLocality() {
+ return dependentLocality;
+ }
+
+ /**
+ * Returns the firm or organization.
+ */
+ public String getOrganization() {
+ return organization;
+ }
+
+ /**
+ * Returns the recipient. Examples: "Jesse Wilson" or "Jesse Wilson c/o Apurva Mathad".
+ */
+ public String getRecipient() {
+ return recipient;
+ }
+
+ /**
+ * Returns the country-specific postal code. Examples: "94043", "94043-1351", "SW1W",
+ * "SW1W 9TQ".
+ */
+ public String getPostalCode() {
+ return postalCode;
+ }
+
+ /**
+ * Returns the country-specific sorting code. For example, the
+ * <a href="http://en.wikipedia.org/wiki/List_of_postal_codes_in_France"> French CEDEX</a>
+ */
+ public String getSortingCode() {
+ return sortingCode;
+ }
+
+ public String getFieldValue(AddressField field) {
+ switch (field) {
+ case COUNTRY:
+ return postalCountry;
+ case ADMIN_AREA:
+ return administrativeArea;
+ case LOCALITY:
+ return locality;
+ case DEPENDENT_LOCALITY:
+ return dependentLocality;
+ case POSTAL_CODE:
+ return postalCode;
+ case SORTING_CODE:
+ return sortingCode;
+ case ADDRESS_LINE_1:
+ return addressLine1;
+ case ADDRESS_LINE_2:
+ return addressLine2;
+ case ORGANIZATION:
+ return organization;
+ case RECIPIENT:
+ return recipient;
+ default:
+ throw new IllegalArgumentException("unrecognized key: " + field);
+ }
+ }
- /**
- * Use {@link Builder} to create instances.
- */
- private AddressData(Builder builder) {
- mPostalCountry = builder.mValues.get(AddressField.COUNTRY);
- mAdministrativeArea = builder.mValues.get(AddressField.ADMIN_AREA);
- mLocality = builder.mValues.get(AddressField.LOCALITY);
- mDependentLocality = builder.mValues.get(AddressField.DEPENDENT_LOCALITY);
- mPostalCode = builder.mValues.get(AddressField.POSTAL_CODE);
- mSortingCode = builder.mValues.get(AddressField.SORTING_CODE);
- mOrganization = builder.mValues.get(AddressField.ORGANIZATION);
- mRecipient = builder.mValues.get(AddressField.RECIPIENT);
- mAddressLine1 = builder.mValues.get(AddressField.ADDRESS_LINE_1);
- mAddressLine2 = builder.mValues.get(AddressField.ADDRESS_LINE_2);
- mLanguageCode = builder.mLanguage;
+ /**
+ * Returns the language of the text of this address. Languages are used to guide how the address
+ * is <a href="http://en.wikipedia.org/wiki/Mailing_address_format_by_country"> formatted for
+ * display</a>. The same address may have different {@link AddressData} representations in
+ * different languages. For example, the French name of "New Mexico" is "Nouveau-Mexique".
+ */
+ public String getLanguageCode() {
+ return languageCode;
+ }
+
+ /**
+ * Builder for AddressData
+ */
+ public static class Builder {
+
+ private final Map<AddressField, String> values;
+
+ private String language = null;
+
+ public Builder() {
+ values = new HashMap<AddressField, String>();
}
/**
- * Returns the postal country.
- *
- * <p>The returned value is not user-presentable. For example, {@code getPostalCountry()} may
- * return {@code "GB"}, while addresses in Great Britain should be displayed using "UK".
+ * A constructor that sets address field with input data. Street fields will be normalized
+ * in the process. I.e., after copy, there will not be any empty street line in front of
+ * non-empty ones. For example, if input data's street line 1 is null but street line 2
+ * has a value, this method will copy street line 2's value and set it to street line 1.
*/
- public String getPostalCountry() {
- return mPostalCountry;
+ public Builder(AddressData addr) {
+ values = new HashMap<AddressField, String>();
+ set(addr);
}
- public String getAddressLine1() {
- return mAddressLine1;
+ public Builder setCountry(String value) {
+ return set(AddressField.COUNTRY, value);
}
- public String getAddressLine2() {
- return mAddressLine2;
+ public Builder setAdminArea(String value) {
+ return set(AddressField.ADMIN_AREA, value);
}
- /**
- * Returns the top-level administrative subdivision of this country. Different postal countries
- * use different names to refer to their administrative areas. For example, this is called
- * "state" in the United States, "region" in Italy, "constituent nation" in Great Britain, or
- * "prefecture" in Japan.
- */
- public String getAdministrativeArea() {
- return mAdministrativeArea;
+ public Builder setLocality(String value) {
+ return set(AddressField.LOCALITY, value);
+ }
+
+ public Builder setDependentLocality(String value) {
+ return set(AddressField.DEPENDENT_LOCALITY, value);
+ }
+
+ public Builder setPostalCode(String value) {
+ return set(AddressField.POSTAL_CODE, value);
+ }
+
+ public Builder setSortingCode(String value) {
+ return set(AddressField.SORTING_CODE, value);
}
/**
- * Returns the locality. The usage of this field varies by region, but it generally refers to
- * the "city" or "town" of the address. Some regions do not use this field; their address lines
- * are sufficient to locate an address within a sub-administrative area. For example, this is
- * called "city" in the United States, "comune" in Italy, or "post town" in Great Britain.
+ * Sets the language code.
+ *
+ * @param languageCode the language to use, or {@code null} for no specified language.
*/
- public String getLocality() {
- return mLocality;
+ public Builder setLanguageCode(String languageCode) {
+ this.language = languageCode;
+ return this;
}
/**
- * Returns the dependent locality.
+ * Sets address lines 1 and 2 (if necessary) from a string that may contain multiple lines.
*
- * <p>This is used for Great Britain dependent localities, or neighborhoods or boroughs in other
- * locations.
+ * <p> Example: Input " \n \n1600 Amphitheatre Ave\n\nRoom 122" will set the following
+ * values:<br/> line 1: 1600 Amphitheatre Ave<br/> line 2: Room 122<br/> </p>
*
- * <p>In cases such as Great Britain, this field may contain a double-dependent locality, such
- * as "Whaley, Langwith".
+ * @param value a street string
*/
- public String getDependentLocality() {
- return mDependentLocality;
+ public Builder setAddress(String value) {
+ setAddressLine1(value);
+ return this;
}
/**
- * Returns the firm or organization.
+ * Sets address by copying from input address data. Street fields will be normalized in the
+ * process. I.e., after copy, there will not be any empty street lines in front of non-empty
+ * ones. For example, if input data's street line 1 is null but street line 2 has a value,
+ * this method will copy street line 2's value and set it to street line 1.
*/
- public String getOrganization() {
- return mOrganization;
+ public Builder set(AddressData data) {
+ values.clear();
+ for (AddressField addressField : AddressField.values()) {
+ if (addressField == AddressField.STREET_ADDRESS) {
+ continue; // Do nothing.
+ } else {
+ set(addressField, data.getFieldValue(addressField));
+ }
+ }
+ normalizeAddresses();
+ setLanguageCode(data.getLanguageCode());
+ return this;
}
- /**
- * Returns the recipient. Examples: "Jesse Wilson" or "Jesse Wilson c/o Apurva Mathad".
- */
- public String getRecipient() {
- return mRecipient;
+ public Builder setAddressLine1(String value) {
+ return set(AddressField.ADDRESS_LINE_1, value);
}
- /**
- * Returns the country-specific postal code. Examples: "94043", "94043-1351", "SW1W",
- * "SW1W 9TQ".
- */
- public String getPostalCode() {
- return mPostalCode;
+ public Builder setAddressLine2(String value) {
+ return set(AddressField.ADDRESS_LINE_2, value);
}
- /**
- * Returns the country-specific sorting code. For example, the
- * <a href="http://en.wikipedia.org/wiki/List_of_postal_codes_in_France"> French CEDEX</a>
- */
- public String getSortingCode() {
- return mSortingCode;
+ public Builder setOrganization(String value) {
+ return set(AddressField.ORGANIZATION, value);
}
- public String getFieldValue(AddressField field) {
- switch (field) {
- case COUNTRY:
- return mPostalCountry;
- case ADMIN_AREA:
- return mAdministrativeArea;
- case LOCALITY:
- return mLocality;
- case DEPENDENT_LOCALITY:
- return mDependentLocality;
- case POSTAL_CODE:
- return mPostalCode;
- case SORTING_CODE:
- return mSortingCode;
- case ADDRESS_LINE_1:
- return mAddressLine1;
- case ADDRESS_LINE_2:
- return mAddressLine2;
- case ORGANIZATION:
- return mOrganization;
- case RECIPIENT:
- return mRecipient;
- default:
- throw new IllegalArgumentException("unrecognized key: " + field);
- }
+ public Builder setRecipient(String value) {
+ return set(AddressField.RECIPIENT, value);
}
/**
- * Returns the language of the text of this address. Languages are used to guide how the address
- * is <a href="http://en.wikipedia.org/wiki/Mailing_address_format_by_country"> formatted for
- * display</a>. The same address may have different {@link AddressData} representations in
- * different languages. For example, the French name of "New Mexico" is "Nouveau-Mexique".
+ * Sets an address field with the specified value. If the value is empty (a null string,
+ * empty string, or a string that contains only spaces), the original value associated with
+ * the field will be removed.
*/
- public String getLanguageCode() {
- return mLanguageCode;
+ public Builder set(AddressField field, String value) {
+ if (value == null || value.length() == 0) {
+ values.remove(field);
+ } else {
+ values.put(field, value.trim());
+ }
+ normalizeAddresses();
+ return this;
+ }
+
+ public AddressData build() {
+ return new AddressData(this);
}
/**
- * Builder for AddressData
+ * Parses content of address line fields.
+ * If address_line_1 is empty, address_line_2 will be used to populate address_line_1 if
+ * possible. If address_line_1 contains a new line, content after the new line will be
+ * saved in address_line_2.
*/
- public static class Builder {
-
- private final Map<AddressField, String> mValues;
-
- private String mLanguage = null;
-
- public Builder() {
- mValues = new HashMap<AddressField, String>();
- }
-
- /**
- * A constructor that sets address field with input data. Street fields will be normalized
- * in the process. I.e., after copy, there will not be any empty street line in front of
- * non-empty ones. For example, if input data's street line 1 is null but street line 2
- * has a value, this method will copy street line 2's value and set it to street line 1.
- */
- public Builder(AddressData addr) {
- mValues = new HashMap<AddressField, String>();
- set(addr);
- }
-
- public Builder setCountry(String value) {
- return set(AddressField.COUNTRY, value);
- }
-
- public Builder setAdminArea(String value) {
- return set(AddressField.ADMIN_AREA, value);
- }
-
- public Builder setLocality(String value) {
- return set(AddressField.LOCALITY, value);
- }
-
- public Builder setDependentLocality(String value) {
- return set(AddressField.DEPENDENT_LOCALITY, value);
- }
-
- public Builder setPostalCode(String value) {
- return set(AddressField.POSTAL_CODE, value);
- }
-
- public Builder setSortingCode(String value) {
- return set(AddressField.SORTING_CODE, value);
- }
-
- /**
- * Sets the language code.
- *
- * @param languageCode the language to use, or {@code null} for no specified language.
- */
- public Builder setLanguageCode(String languageCode) {
- this.mLanguage = languageCode;
- return this;
- }
-
- /**
- * Sets address lines 1 and 2 (if necessary) from a string that may contain multiple lines.
- *
- * <p> Example: Input " \n \n1600 Amphitheatre Ave\n\nRoom 122" will set the following
- * values:<br/> line 1: 1600 Amphitheatre Ave<br/> line 2: Room 122<br/> </p>
- *
- * @param value a street string
- */
- public Builder setAddress(String value) {
- setAddressLine1(value);
- return this;
- }
-
- /**
- * Sets address by copying from input address data. Street fields will be normalized in the
- * process. I.e., after copy, there will not be any empty street lines in front of non-empty
- * ones. For example, if input data's street line 1 is null but street line 2 has a value,
- * this method will copy street line 2's value and set it to street line 1.
- */
- public Builder set(AddressData data) {
- mValues.clear();
- for (AddressField addressField : AddressField.values()) {
- if (addressField == AddressField.STREET_ADDRESS) {
- continue; // Do nothing.
- } else {
- set(addressField, data.getFieldValue(addressField));
- }
- }
- normalizeAddresses();
- setLanguageCode(data.getLanguageCode());
- return this;
- }
-
- public Builder setAddressLine1(String value) {
- return set(AddressField.ADDRESS_LINE_1, value);
- }
-
- public Builder setAddressLine2(String value) {
- return set(AddressField.ADDRESS_LINE_2, value);
- }
-
- public Builder setOrganization(String value) {
- return set(AddressField.ORGANIZATION, value);
- }
-
- public Builder setRecipient(String value) {
- return set(AddressField.RECIPIENT, value);
- }
-
- /**
- * Sets an address field with the specified value. If the value is empty (a null string,
- * empty string, or a string that contains only spaces), the original value associated with
- * the field will be removed.
- */
- public Builder set(AddressField field, String value) {
- if (value == null || value.length() == 0) {
- mValues.remove(field);
- } else {
- mValues.put(field, value.trim());
- }
- normalizeAddresses();
- return this;
- }
-
- public AddressData build() {
- return new AddressData(this);
- }
-
- /**
- * Parses content of address line fields.
- * If address_line_1 is empty, address_line_2 will be used to populate address_line_1 if
- * possible. If address_line_1 contains a new line, content after the new line will be
- * saved in address_line_2.
- */
- private void normalizeAddresses() {
- String address1 = mValues.get(AddressField.ADDRESS_LINE_1);
- String address2 = mValues.get(AddressField.ADDRESS_LINE_2);
- if (address1 == null || address1.trim().length() == 0) {
- address1 = address2;
- address2 = null;
- }
- if (address1 != null) {
- String[] addressLines = address1.split("\n");
- if (addressLines.length > 1) {
- address1 = addressLines[0];
- address2 = addressLines[1];
- }
- }
- mValues.put(AddressField.ADDRESS_LINE_1, address1);
- mValues.put(AddressField.ADDRESS_LINE_2, address2);
+ private void normalizeAddresses() {
+ String address1 = values.get(AddressField.ADDRESS_LINE_1);
+ String address2 = values.get(AddressField.ADDRESS_LINE_2);
+ if (address1 == null || address1.trim().length() == 0) {
+ address1 = address2;
+ address2 = null;
+ }
+ if (address1 != null) {
+ String[] addressLines = address1.split("\n");
+ if (addressLines.length > 1) {
+ address1 = addressLines[0];
+ address2 = addressLines[1];
}
+ }
+ values.put(AddressField.ADDRESS_LINE_1, address1);
+ values.put(AddressField.ADDRESS_LINE_2, address2);
}
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/AddressDataKey.java b/java/src/com/android/i18n/addressinput/AddressDataKey.java
index a4766af..2fe58a4 100644
--- a/java/src/com/android/i18n/addressinput/AddressDataKey.java
+++ b/java/src/com/android/i18n/addressinput/AddressDataKey.java
@@ -77,6 +77,10 @@ enum AddressDataKey {
*/
SUB_LNAMES,
/**
+ * Indicates the type of the name used for the sublocality field.
+ */
+ SUBLOCALITY_NAME_TYPE,
+ /**
* Indicates, for each child of this region, whether that child has additional children.
*/
SUB_MORES,
diff --git a/java/src/com/android/i18n/addressinput/AddressField.java b/java/src/com/android/i18n/addressinput/AddressField.java
index 17b1817..7d3dbf2 100644
--- a/java/src/com/android/i18n/addressinput/AddressField.java
+++ b/java/src/com/android/i18n/addressinput/AddressField.java
@@ -24,64 +24,64 @@ import java.util.Map;
* formatting. Note that the metadata also has a character for newlines, which is not defined here.
*/
public enum AddressField {
- ADMIN_AREA('S'),
- LOCALITY('C'),
- RECIPIENT('N'),
- ORGANIZATION('O'),
- // Deprecated - use A instead.
- ADDRESS_LINE_1('1'),
- // Deprecated - use A instead.
- ADDRESS_LINE_2('2'),
- DEPENDENT_LOCALITY('D'),
- POSTAL_CODE('Z'),
- SORTING_CODE('X'),
- STREET_ADDRESS('A'),
+ ADMIN_AREA('S'),
+ LOCALITY('C'),
+ RECIPIENT('N'),
+ ORGANIZATION('O'),
+ // Deprecated - use A instead.
+ ADDRESS_LINE_1('1'),
+ // Deprecated - use A instead.
+ ADDRESS_LINE_2('2'),
+ DEPENDENT_LOCALITY('D'),
+ POSTAL_CODE('Z'),
+ SORTING_CODE('X'),
+ STREET_ADDRESS('A'),
- COUNTRY('R');
+ COUNTRY('R');
- /**
- * Enum for width types of address input fields.
- */
- public enum WidthType {
- LONG,
- SHORT;
- }
+ /**
+ * Enum for width types of address input fields.
+ */
+ public enum WidthType {
+ LONG,
+ SHORT;
+ }
- private static final Map<Character, AddressField> FIELD_MAPPING
- = new HashMap<Character, AddressField>();
+ private static final Map<Character, AddressField> FIELD_MAPPING
+ = new HashMap<Character, AddressField>();
- static {
- for (AddressField value : values()) {
- FIELD_MAPPING.put(value.getChar(), value);
- }
+ static {
+ for (AddressField value : values()) {
+ FIELD_MAPPING.put(value.getChar(), value);
}
+ }
- private final char mField;
+ private final char field;
- private AddressField(char field) {
- mField = field;
- }
+ private AddressField(char field) {
+ this.field = field;
+ }
- /**
- * Gets the corresponding AddressField for the character code. Returns null if the character is
- * not recognized.
- */
- static AddressField of(char field) {
- return FIELD_MAPPING.get(field);
- }
+ /**
+ * Gets the corresponding AddressField for the character code. Returns null if the character is
+ * not recognized.
+ */
+ static AddressField of(char field) {
+ return FIELD_MAPPING.get(field);
+ }
- /**
- * Gets the field's identification character, as used in the metadata.
- *
- * @return identification char.
- */
- char getChar() {
- return mField;
- }
+ /**
+ * Gets the field's identification character, as used in the metadata.
+ *
+ * @return identification char.
+ */
+ char getChar() {
+ return field;
+ }
- /** Returns default width type of the address field. */
- WidthType getDefaulWidthType() {
- return this.equals(POSTAL_CODE) || this.equals(SORTING_CODE)
- ? WidthType.SHORT : WidthType.LONG;
- }
+ /** Returns default width type of the address field. */
+ WidthType getDefaulWidthType() {
+ return this.equals(POSTAL_CODE) || this.equals(SORTING_CODE)
+ ? WidthType.SHORT : WidthType.LONG;
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/AddressProblemType.java b/java/src/com/android/i18n/addressinput/AddressProblemType.java
index 4cab705..27d19f6 100644
--- a/java/src/com/android/i18n/addressinput/AddressProblemType.java
+++ b/java/src/com/android/i18n/addressinput/AddressProblemType.java
@@ -21,50 +21,50 @@ package com.android.i18n.addressinput;
*/
public enum AddressProblemType {
- /**
- * The field is not null and not whitespace, and the field should not be used for this country.
- *
- * <p>For example, in the U.S. the SORTING_CODE field is unused, so its presence is an error.
- */
- USING_UNUSED_FIELD,
+ /**
+ * The field is not null and not whitespace, and the field should not be used for this country.
+ *
+ * <p>For example, in the U.S. the SORTING_CODE field is unused, so its presence is an error.
+ */
+ USING_UNUSED_FIELD,
- /**
- * The field is null or whitespace, and the field is required.
- *
- * <p>For example, in the U.S. ADMIN_AREA is a required field.
- */
- MISSING_REQUIRED_FIELD,
+ /**
+ * The field is null or whitespace, and the field is required.
+ *
+ * <p>For example, in the U.S. ADMIN_AREA is a required field.
+ */
+ MISSING_REQUIRED_FIELD,
- /**
- * A list of values for the field is defined and the value does not occur in the list. Applies
- * to hierarchical elements like REGION, ADMIN_AREA, LOCALITY, and DEPENDENT_LOCALITY.
- *
- * <p>For example, in the U.S. the only valid values for ADMIN_AREA are the two-letter state
- * codes.
- */
- UNKNOWN_VALUE,
+ /**
+ * A list of values for the field is defined and the value does not occur in the list. Applies
+ * to hierarchical elements like REGION, ADMIN_AREA, LOCALITY, and DEPENDENT_LOCALITY.
+ *
+ * <p>For example, in the U.S. the only valid values for ADMIN_AREA are the two-letter state
+ * codes.
+ */
+ UNKNOWN_VALUE,
- /**
- * A format for the field is defined and the value does not match. This is used to match
- * POSTAL_CODE against the the format pattern generally.
- *
- * <p>For example, in the U.S. postal codes are five digits with an optional hyphen followed by
- * four digits.
- */
- UNRECOGNIZED_FORMAT,
+ /**
+ * A format for the field is defined and the value does not match. This is used to match
+ * POSTAL_CODE against the the format pattern generally.
+ *
+ * <p>For example, in the U.S. postal codes are five digits with an optional hyphen followed by
+ * four digits.
+ */
+ UNRECOGNIZED_FORMAT,
- /**
- * A pattern for the field is defined and the value does not match. This is used to match
- * POSTAL_CODE against a regular expression.
- *
- * <p>For example, in the U.S. postal codes in the state of California start with '9'.
- */
- MISMATCHING_VALUE;
+ /**
+ * A pattern for the field is defined and the value does not match. This is used to match
+ * POSTAL_CODE against a regular expression.
+ *
+ * <p>For example, in the U.S. postal codes in the state of California start with '9'.
+ */
+ MISMATCHING_VALUE;
- /**
- * Returns a unique string identifying this problem (for use in a message catalog).
- */
- public String keyname() {
- return name().toLowerCase();
- }
+ /**
+ * Returns a unique string identifying this problem (for use in a message catalog).
+ */
+ public String keyname() {
+ return name().toLowerCase();
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/AddressProblems.java b/java/src/com/android/i18n/addressinput/AddressProblems.java
index 9371140..39a0457 100644
--- a/java/src/com/android/i18n/addressinput/AddressProblems.java
+++ b/java/src/com/android/i18n/addressinput/AddressProblems.java
@@ -24,44 +24,44 @@ import java.util.Map;
*/
public class AddressProblems {
- private Map<AddressField, AddressProblemType> mProblems =
- new HashMap<AddressField, AddressProblemType>();
+ private Map<AddressField, AddressProblemType> problems =
+ new HashMap<AddressField, AddressProblemType>();
- /**
- * Only one address problem type is saved per addressField. Address field as used here refers to
- * the different data parts in the AddressData class.
- */
- void add(AddressField addressField, AddressProblemType problem) {
- mProblems.put(addressField, problem);
- }
+ /**
+ * Only one address problem type is saved per addressField. Address field as used here refers to
+ * the different data parts in the AddressData class.
+ */
+ void add(AddressField addressField, AddressProblemType problem) {
+ problems.put(addressField, problem);
+ }
- /**
- * Returns true if no problems have been added.
- */
- public boolean isEmpty() {
- return mProblems.isEmpty();
- }
+ /**
+ * Returns true if no problems have been added.
+ */
+ public boolean isEmpty() {
+ return problems.isEmpty();
+ }
- @Override
- public String toString() {
- return mProblems.toString();
- }
+ @Override
+ public String toString() {
+ return problems.toString();
+ }
- public void clear() {
- mProblems.clear();
- }
+ public void clear() {
+ problems.clear();
+ }
- /**
- * Returns null if no problems exists.
- */
- public AddressProblemType getProblem(AddressField addressField) {
- return mProblems.get(addressField);
- }
+ /**
+ * Returns null if no problems exists.
+ */
+ public AddressProblemType getProblem(AddressField addressField) {
+ return problems.get(addressField);
+ }
- /**
- * This will return an empty map if there are no problems.
- */
- public Map<AddressField, AddressProblemType> getProblems() {
- return mProblems;
- }
+ /**
+ * This will return an empty map if there are no problems.
+ */
+ public Map<AddressField, AddressProblemType> getProblems() {
+ return problems;
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/AddressUiComponent.java b/java/src/com/android/i18n/addressinput/AddressUiComponent.java
index 3c2e937..5e07799 100644
--- a/java/src/com/android/i18n/addressinput/AddressUiComponent.java
+++ b/java/src/com/android/i18n/addressinput/AddressUiComponent.java
@@ -28,129 +28,129 @@ import java.util.List;
* candidate) or a spinner.
*/
class AddressUiComponent {
- // The label for the UI component
- private String mFieldName;
-
- // The type of the UI component
- private UiComponent mUiType;
-
- // The list of elements in the UI component
- private List<RegionData> mCandidatesList = new ArrayList<RegionData>();
-
- // The id of this UI component
- private AddressField mId;
-
- // The id of the parent UI component. When the parent UI component is updated, this UI
- // component should be updated.
- private AddressField mParentId;
-
- // The View representing the UI component
- private View mView;
-
- /**
- * Type of UI component. There are only EDIT (text-box) and SPINNER (drop-down) components.
- */
- enum UiComponent {
- EDIT, SPINNER,
- }
-
- AddressUiComponent(AddressField id) {
- mId = id;
- // By default, an AddressUiComponent doesn't depend on anything else.
- mParentId = null;
- mUiType = UiComponent.EDIT;
- }
-
- /**
- * Initializes the candidatesList, and set the uiType and parentId.
- * @param candidatesList
- */
- void initializeCandidatesList(List<RegionData> candidatesList) {
- mCandidatesList = candidatesList;
- if (candidatesList.size() > 1) {
- mUiType = UiComponent.SPINNER;
- switch (mId) {
- case DEPENDENT_LOCALITY:
- mParentId = AddressField.LOCALITY;
- break;
- case LOCALITY:
- mParentId = AddressField.ADMIN_AREA;
- break;
- case ADMIN_AREA:
- mParentId = AddressField.COUNTRY;
- break;
- default:
- // Ignore.
- }
- }
- }
-
- /**
- * Gets the value entered in the UI component.
- */
- String getValue() {
- if (mView == null) {
- return (mCandidatesList.size() == 0) ? "" : mCandidatesList.get(0).getDisplayName();
- }
- switch (mUiType) {
- case SPINNER:
- Object selectedItem = ((Spinner) mView).getSelectedItem();
- if (selectedItem == null) {
- return "";
- }
- return selectedItem.toString();
- case EDIT:
- return ((EditText) mView).getText().toString();
- default:
- return "";
+ // The label for the UI component
+ private String fieldName;
+
+ // The type of the UI component
+ private UiComponent uiType;
+
+ // The list of elements in the UI component
+ private List<RegionData> candidatesList = new ArrayList<RegionData>();
+
+ // The id of this UI component
+ private AddressField id;
+
+ // The id of the parent UI component. When the parent UI component is updated, this UI
+ // component should be updated.
+ private AddressField parentId;
+
+ // The View representing the UI component
+ private View view;
+
+ /**
+ * Type of UI component. There are only EDIT (text-box) and SPINNER (drop-down) components.
+ */
+ enum UiComponent {
+ EDIT, SPINNER,
+ }
+
+ AddressUiComponent(AddressField id) {
+ this.id = id;
+ // By default, an AddressUiComponent doesn't depend on anything else.
+ this.parentId = null;
+ this.uiType = UiComponent.EDIT;
+ }
+
+ /**
+ * Initializes the candidatesList, and set the uiType and parentId.
+ * @param candidatesList
+ */
+ void initializeCandidatesList(List<RegionData> candidatesList) {
+ this.candidatesList = candidatesList;
+ if (candidatesList.size() > 1) {
+ uiType = UiComponent.SPINNER;
+ switch (id) {
+ case DEPENDENT_LOCALITY:
+ parentId = AddressField.LOCALITY;
+ break;
+ case LOCALITY:
+ parentId = AddressField.ADMIN_AREA;
+ break;
+ case ADMIN_AREA:
+ parentId = AddressField.COUNTRY;
+ break;
+ default:
+ // Ignore.
+ }
+ }
+ }
+
+ /**
+ * Gets the value entered in the UI component.
+ */
+ String getValue() {
+ if (view == null) {
+ return (candidatesList.size() == 0) ? "" : candidatesList.get(0).getDisplayName();
+ }
+ switch (uiType) {
+ case SPINNER:
+ Object selectedItem = ((Spinner) view).getSelectedItem();
+ if (selectedItem == null) {
+ return "";
}
+ return selectedItem.toString();
+ case EDIT:
+ return ((EditText) view).getText().toString();
+ default:
+ return "";
}
+ }
- String getFieldName() {
- return mFieldName;
- }
+ String getFieldName() {
+ return fieldName;
+ }
- void setFieldName(String fieldName) {
- mFieldName = fieldName;
- }
+ void setFieldName(String fieldName) {
+ this.fieldName = fieldName;
+ }
- UiComponent getUiType() {
- return mUiType;
- }
+ UiComponent getUiType() {
+ return uiType;
+ }
- void setUiType(UiComponent uiType) {
- mUiType = uiType;
- }
+ void setUiType(UiComponent uiType) {
+ this.uiType = uiType;
+ }
- List<RegionData> getCandidatesList() {
- return mCandidatesList;
- }
+ List<RegionData> getCandidatesList() {
+ return candidatesList;
+ }
- void setCandidatesList(List<RegionData> candidatesList) {
- mCandidatesList = candidatesList;
- }
+ void setCandidatesList(List<RegionData> candidatesList) {
+ this.candidatesList = candidatesList;
+ }
- AddressField getId() {
- return mId;
- }
+ AddressField getId() {
+ return id;
+ }
- void setId(AddressField id) {
- mId = id;
- }
+ void setId(AddressField id) {
+ this.id = id;
+ }
- AddressField getParentId() {
- return mParentId;
- }
+ AddressField getParentId() {
+ return parentId;
+ }
- void setParentId(AddressField parentId) {
- mParentId = parentId;
- }
+ void setParentId(AddressField parentId) {
+ this.parentId = parentId;
+ }
- void setView(View view) {
- mView = view;
- }
+ void setView(View view) {
+ this.view = view;
+ }
- View getView() {
- return mView;
- }
+ View getView() {
+ return view;
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/AddressVerificationData.java b/java/src/com/android/i18n/addressinput/AddressVerificationData.java
index 58f4366..f5b9c05 100644
--- a/java/src/com/android/i18n/addressinput/AddressVerificationData.java
+++ b/java/src/com/android/i18n/addressinput/AddressVerificationData.java
@@ -29,129 +29,129 @@ import java.util.regex.Pattern;
*/
class AddressVerificationData implements DataSource {
- private final Map<String, String> mPropertiesMap;
+ private final Map<String, String> propertiesMap;
- private static final Pattern KEY_VALUES_PATTERN = Pattern.compile("\"([^\"]+)\":\"([^\"]*)\"");
+ private static final Pattern KEY_VALUES_PATTERN = Pattern.compile("\"([^\"]+)\":\"([^\"]*)\"");
- private static final Pattern SEPARATOR_PATTERN = Pattern.compile("\",\"");
+ private static final Pattern SEPARATOR_PATTERN = Pattern.compile("\",\"");
- /**
- * Constructs from a map of address property data. This keeps a reference to the map. This
- * does not mutate the map. The map should not be mutated subsequent to this call.
- */
- AddressVerificationData(Map<String, String> propertiesMap) {
- mPropertiesMap = propertiesMap;
- }
+ /**
+ * Constructs from a map of address property data. This keeps a reference to the map. This
+ * does not mutate the map. The map should not be mutated subsequent to this call.
+ */
+ AddressVerificationData(Map<String, String> propertiesMap) {
+ this.propertiesMap = propertiesMap;
+ }
- @Override
- public AddressVerificationNodeData get(String key) {
- String json = mPropertiesMap.get(key);
- if (json != null && isValidKey(key)) {
- return createNodeData(json);
- }
- return null;
+ @Override
+ public AddressVerificationNodeData get(String key) {
+ String json = propertiesMap.get(key);
+ if (json != null && isValidKey(key)) {
+ return createNodeData(json);
}
-
- /**
- * Returns a set of the keys for which verification data is provided. The returned set is
- * immutable.
- */
- Set<String> keys() {
- Set<String> result = new HashSet<String>();
- for (String key : mPropertiesMap.keySet()) {
- if (isValidKey(key)) {
- result.add(key);
+ return null;
+ }
+
+ /**
+ * Returns a set of the keys for which verification data is provided. The returned set is
+ * immutable.
+ */
+ Set<String> keys() {
+ Set<String> result = new HashSet<String>();
+ for (String key : propertiesMap.keySet()) {
+ if (isValidKey(key)) {
+ result.add(key);
+ }
+ }
+ return Collections.unmodifiableSet(result);
+ }
+
+ /**
+ * We can be initialized with the full set of address information, but validation only uses
+ * info prefixed with "data" (in particular, no info prefixed with "examples").
+ */
+ private boolean isValidKey(String key) {
+ return key.startsWith("data");
+ }
+
+ /**
+ * Returns the contents of the JSON-format string as a map.
+ */
+ AddressVerificationNodeData createNodeData(String json) {
+ // Remove leading and trailing { and }.
+ json = json.substring(1, json.length() - 1);
+ Map<AddressDataKey, String> map =
+ new EnumMap<AddressDataKey, String>(AddressDataKey.class);
+
+ // our objects are very simple so we parse manually
+ // - no double quotes within strings
+ // - no extra spaces
+ // can't use split "," since some data has commas in it.
+ Matcher sm = SEPARATOR_PATTERN.matcher(json);
+ int pos = 0;
+ while (pos < json.length()) {
+ String pair;
+ if (sm.find()) {
+ pair = json.substring(pos, sm.start() + 1);
+ pos = sm.start() + 2;
+ } else {
+ pair = json.substring(pos);
+ pos = json.length();
+ }
+
+ Matcher m = KEY_VALUES_PATTERN.matcher(pair);
+ if (m.matches()) {
+ String value = m.group(2);
+
+ // Remove escaped backslashes.
+ // Java regex doesn't handle a replacement String consisting of
+ // a single backslash, and treats a replacement String consisting of
+ // two backslashes as two backslashes instead of one. So there's
+ // no way to use regex to replace a match with a single backslash,
+ // apparently.
+ if (value.length() > 0) {
+ char[] linechars = m.group(2).toCharArray();
+ int w = 1;
+ for (int r = w; r < linechars.length; ++r) {
+ char c = linechars[r];
+ if (c == '\\' && linechars[w - 1] == '\\') {
+ // don't increment w;
+ continue;
}
+ linechars[w++] = c;
+ }
+ value = new String(linechars, 0, w);
}
- return Collections.unmodifiableSet(result);
- }
- /**
- * We can be initialized with the full set of address information, but validation only uses
- * info prefixed with "data" (in particular, no info prefixed with "examples").
- */
- private boolean isValidKey(String key) {
- return key.startsWith("data");
+ AddressDataKey df = AddressDataKey.get(m.group(1));
+ if (df == null) {
+ // Skip this data - it isn't used in the Android version.
+ } else {
+ map.put(df, value);
+ }
+ } else {
+ // This is a runtime data sanity check. The data should be
+ // checked when the data is built. The JSON data string should
+ // be parsable into string pairs using SEP_PAT.
+ throw new RuntimeException("could not match '" + pair + "' in '" + json + "'");
+ }
}
- /**
- * Returns the contents of the JSON-format string as a map.
- */
- AddressVerificationNodeData createNodeData(String json) {
- // Remove leading and trailing { and }.
- json = json.substring(1, json.length() - 1);
- Map<AddressDataKey, String> map =
- new EnumMap<AddressDataKey, String>(AddressDataKey.class);
-
- // our objects are very simple so we parse manually
- // - no double quotes within strings
- // - no extra spaces
- // can't use split "," since some data has commas in it.
- Matcher sm = SEPARATOR_PATTERN.matcher(json);
- int pos = 0;
- while (pos < json.length()) {
- String pair;
- if (sm.find()) {
- pair = json.substring(pos, sm.start() + 1);
- pos = sm.start() + 2;
- } else {
- pair = json.substring(pos);
- pos = json.length();
- }
+ return new AddressVerificationNodeData(map);
+ }
- Matcher m = KEY_VALUES_PATTERN.matcher(pair);
- if (m.matches()) {
- String value = m.group(2);
-
- // Remove escaped backslashes.
- // Java regex doesn't handle a replacement String consisting of
- // a single backslash, and treats a replacement String consisting of
- // two backslashes as two backslashes instead of one. So there's
- // no way to use regex to replace a match with a single backslash,
- // apparently.
- if (value.length() > 0) {
- char[] linechars = m.group(2).toCharArray();
- int w = 1;
- for (int r = w; r < linechars.length; ++r) {
- char c = linechars[r];
- if (c == '\\' && linechars[w - 1] == '\\') {
- // don't increment w;
- continue;
- }
- linechars[w++] = c;
- }
- value = new String(linechars, 0, w);
- }
-
- AddressDataKey df = AddressDataKey.get(m.group(1));
- if (df == null) {
- // Skip this data - it isn't used in the Android version.
- } else {
- map.put(df, value);
- }
- } else {
- // This is a runtime data sanity check. The data should be
- // checked when the data is built. The JSON data string should
- // be parsable into string pairs using SEP_PAT.
- throw new RuntimeException("could not match '" + pair + "' in '" + json + "'");
- }
- }
-
- return new AddressVerificationNodeData(map);
+ @Override
+ public AddressVerificationNodeData getDefaultData(String key) {
+ // gets country key
+ if (key.split("/").length > 1) {
+ String[] parts = key.split("/");
+ key = parts[0] + "/" + parts[1];
}
- @Override
- public AddressVerificationNodeData getDefaultData(String key) {
- // gets country key
- if (key.split("/").length > 1) {
- String[] parts = key.split("/");
- key = parts[0] + "/" + parts[1];
- }
-
- AddressVerificationNodeData data = get(key);
- if (data == null) {
- throw new RuntimeException("failed to get default data with key " + key);
- }
- return data;
+ AddressVerificationNodeData data = get(key);
+ if (data == null) {
+ throw new RuntimeException("failed to get default data with key " + key);
}
+ return data;
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/AddressVerificationNodeData.java b/java/src/com/android/i18n/addressinput/AddressVerificationNodeData.java
index bb291d9..8082c07 100644
--- a/java/src/com/android/i18n/addressinput/AddressVerificationNodeData.java
+++ b/java/src/com/android/i18n/addressinput/AddressVerificationNodeData.java
@@ -28,28 +28,28 @@ import java.util.Map;
*/
public class AddressVerificationNodeData {
- private final Map<AddressDataKey, String> mMap;
-
- public AddressVerificationNodeData(Map<AddressDataKey, String> map) {
- Util.checkNotNull("Cannot construct StandardNodeData with null map");
- mMap = map;
- }
-
- /**
- * Iterates through the map.
- */
- public Iterator<AddressDataKey> iterator() {
- return mMap.keySet().iterator();
- }
-
- public boolean containsKey(AddressDataKey key) {
- return mMap.containsKey(key);
- }
-
- /**
- * Gets the value for a particular key in the map.
- */
- public String get(AddressDataKey key) {
- return mMap.get(key);
- }
+ private final Map<AddressDataKey, String> map;
+
+ public AddressVerificationNodeData(Map<AddressDataKey, String> map) {
+ Util.checkNotNull("Cannot construct StandardNodeData with null map");
+ this.map = map;
+ }
+
+ /**
+ * Iterates through the map.
+ */
+ public Iterator<AddressDataKey> iterator() {
+ return map.keySet().iterator();
+ }
+
+ public boolean containsKey(AddressDataKey key) {
+ return map.containsKey(key);
+ }
+
+ /**
+ * Gets the value for a particular key in the map.
+ */
+ public String get(AddressDataKey key) {
+ return map.get(key);
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/AddressWidget.java b/java/src/com/android/i18n/addressinput/AddressWidget.java
index c377e2c..3a7267b 100644
--- a/java/src/com/android/i18n/addressinput/AddressWidget.java
+++ b/java/src/com/android/i18n/addressinput/AddressWidget.java
@@ -51,727 +51,728 @@ import java.util.Map;
* customs.
*/
public class AddressWidget implements AdapterView.OnItemSelectedListener {
- private Context mContext;
+ private Context context;
- private ViewGroup mRootView;
+ private ViewGroup rootView;
- private LayoutInflater mInflater;
+ private LayoutInflater inflater;
- private CacheData mCacheData;
+ private CacheData cacheData;
- // A map for all address fields except for country.
- private final EnumMap<AddressField, AddressUiComponent> mInputWidgets =
- new EnumMap<AddressField, AddressUiComponent>(AddressField.class);
+ // A map for all address fields.
+ private final EnumMap<AddressField, AddressUiComponent> inputWidgets =
+ new EnumMap<AddressField, AddressUiComponent>(AddressField.class);
- private FormController mFormController;
+ private FormController formController;
- private FormatInterpreter mFormatInterpreter;
+ private FormatInterpreter formatInterpreter;
- private FormOptions mFormOptions;
+ private FormOptions formOptions;
- private StandardAddressVerifier mVerifier;
+ private StandardAddressVerifier verifier;
- private ProgressDialog mProgressDialog;
+ private ProgressDialog progressDialog;
- private String mCurrentRegion;
+ private String currentRegion;
- // The current language the widget use in BCP47 format. It differs from the default locale of
- // the phone in that it contains information on the script to use.
- private String mWidgetLocale;
+ // The current language the widget uses in BCP47 format. It differs from the default locale of
+ // the phone in that it contains information on the script to use.
+ private String widgetLocale;
- private ScriptType mScript;
+ private ScriptType script;
- // The appropriate label that should be applied to the locality (city) field of the current
- // country. Examples include "city" or "district".
- private String mLocalityLabel;
+ // Possible labels that could be applied to the admin area field of the current country.
+ // Examples include "state", "province", "emirate", etc.
+ private static final Map<String, Integer> ADMIN_LABELS;
+ // Possible labels that could be applied to the locality (city) field of the current country.
+ // Examples include "city" or "district".
+ private static final Map<String, Integer> LOCALITY_LABELS;
+ // Possible labels that could be applied to the sublocality field of the current country.
+ // Examples include "suburb" or "neighborhood".
+ private static final Map<String, Integer> SUBLOCALITY_LABELS;
- // The appropriate label that should be applied to the admin area field of the current country.
- // Examples include "state", "province", "emirate", etc.
- private String mAdminLabel;
+ private static final FormOptions SHOW_ALL_FIELDS = new FormOptions.Builder().build();
- private static final Map<String, Integer> ADMIN_LABELS;
- private static final Map<String, Integer> LOCALITY_LABELS;
- private static final Map<String, Integer> ADMIN_ERROR_MESSAGES;
+ // The appropriate label that should be applied to the zip code field of the current country.
+ private enum ZipLabel {
+ ZIP,
+ POSTAL
+ }
- private static final FormOptions SHOW_ALL_FIELDS = new FormOptions.Builder().build();
+ private ZipLabel zipLabel;
- // The appropriate label that should be applied to the zip code field of the current country.
- private enum ZipLabel {
- ZIP,
- POSTAL
- }
+ static {
+ Map<String, Integer> adminLabelMap = new HashMap<String, Integer>(15);
+ adminLabelMap.put("area", R.string.i18n_area);
+ adminLabelMap.put("county", R.string.i18n_county);
+ adminLabelMap.put("department", R.string.i18n_department);
+ adminLabelMap.put("district", R.string.i18n_district);
+ adminLabelMap.put("do_si", R.string.i18n_do_si);
+ adminLabelMap.put("emirate", R.string.i18n_emirate);
+ adminLabelMap.put("island", R.string.i18n_island);
+ adminLabelMap.put("oblast", R.string.i18n_oblast);
+ adminLabelMap.put("parish", R.string.i18n_parish);
+ adminLabelMap.put("prefecture", R.string.i18n_prefecture);
+ adminLabelMap.put("province", R.string.i18n_province);
+ adminLabelMap.put("state", R.string.i18n_state);
+ ADMIN_LABELS = Collections.unmodifiableMap(adminLabelMap);
- private ZipLabel mZipLabel;
+ Map<String, Integer> localityLabelMap = new HashMap<String, Integer>(2);
+ localityLabelMap.put("city", R.string.i18n_locality_label);
+ localityLabelMap.put("district", R.string.i18n_district);
+ localityLabelMap.put("post_town", R.string.i18n_post_town);
+ LOCALITY_LABELS = Collections.unmodifiableMap(localityLabelMap);
- static {
- Map<String, Integer> adminLabelMap = new HashMap<String, Integer>(15);
- adminLabelMap.put("area", R.string.i18n_area);
- adminLabelMap.put("county", R.string.i18n_county_label);
- adminLabelMap.put("department", R.string.i18n_department);
- adminLabelMap.put("district", R.string.i18n_dependent_locality_label);
- adminLabelMap.put("do_si", R.string.i18n_do_si);
- adminLabelMap.put("emirate", R.string.i18n_emirate);
- adminLabelMap.put("island", R.string.i18n_island);
- adminLabelMap.put("oblast", R.string.i18n_oblast);
- adminLabelMap.put("parish", R.string.i18n_parish);
- adminLabelMap.put("prefecture", R.string.i18n_prefecture);
- adminLabelMap.put("province", R.string.i18n_province);
- adminLabelMap.put("state", R.string.i18n_state_label);
- ADMIN_LABELS = Collections.unmodifiableMap(adminLabelMap);
+ Map<String, Integer> sublocalityLabelMap = new HashMap<String, Integer>(2);
+ sublocalityLabelMap.put("suburb", R.string.i18n_suburb);
+ sublocalityLabelMap.put("district", R.string.i18n_district);
+ sublocalityLabelMap.put("neighborhood", R.string.i18n_neighborhood);
+ sublocalityLabelMap.put("village_township", R.string.i18n_village_township);
+ SUBLOCALITY_LABELS = Collections.unmodifiableMap(sublocalityLabelMap);
+ }
- Map<String, Integer> localityLabelMap = new HashMap<String, Integer>(2);
- localityLabelMap.put("city", R.string.i18n_locality_label);
- localityLabelMap.put("district", R.string.i18n_dependent_locality_label);
- LOCALITY_LABELS = Collections.unmodifiableMap(localityLabelMap);
+ // Need handler for callbacks to the UI thread
+ final Handler handler = new Handler();
- Map<String, Integer> adminErrorMap = new HashMap<String, Integer>(15);
- adminErrorMap.put("area", R.string.invalid_area);
- adminErrorMap.put("county", R.string.invalid_county_label);
- adminErrorMap.put("department", R.string.invalid_department);
- adminErrorMap.put("district", R.string.invalid_dependent_locality_label);
- adminErrorMap.put("do_si", R.string.invalid_do_si);
- adminErrorMap.put("emirate", R.string.invalid_emirate);
- adminErrorMap.put("island", R.string.invalid_island);
- adminErrorMap.put("oblast", R.string.invalid_oblast);
- adminErrorMap.put("parish", R.string.invalid_parish);
- adminErrorMap.put("prefecture", R.string.invalid_prefecture);
- adminErrorMap.put("province", R.string.invalid_province);
- adminErrorMap.put("state", R.string.invalid_state_label);
- ADMIN_ERROR_MESSAGES = Collections.unmodifiableMap(adminErrorMap);
+ final Runnable updateMultipleFields = new Runnable() {
+ @Override
+ public void run() {
+ updateFields();
}
+ };
- // Need handler for callbacks to the UI thread
- final Handler mHandler = new Handler();
-
- final Runnable mUpdateMultipleFields = new Runnable() {
- @Override
- public void run() {
- updateFields();
- }
- };
-
- private class UpdateRunnable implements Runnable {
- private AddressField myId;
+ private class UpdateRunnable implements Runnable {
+ private AddressField myId;
- public UpdateRunnable(AddressField id) {
- myId = id;
- }
+ public UpdateRunnable(AddressField id) {
+ myId = id;
+ }
- @Override
- public void run() {
- updateInputWidget(myId);
- }
+ @Override
+ public void run() {
+ updateInputWidget(myId);
}
+ }
- private static class AddressSpinnerInfo {
- private Spinner mView;
+ private static class AddressSpinnerInfo {
+ private Spinner view;
- private AddressField mId;
+ private AddressField id;
- private AddressField mParentId;
+ private AddressField parentId;
- private ArrayAdapter<String> mAdapter;
+ private ArrayAdapter<String> adapter;
- private List<RegionData> mCurrentRegions;
+ private List<RegionData> currentRegions;
- @SuppressWarnings("unchecked")
- public AddressSpinnerInfo(Spinner view, AddressField id, AddressField parentId) {
- mView = view;
- mId = id;
- mParentId = parentId;
- mAdapter = (ArrayAdapter<String>) view.getAdapter();
- }
+ @SuppressWarnings("unchecked")
+ public AddressSpinnerInfo(Spinner view, AddressField id, AddressField parentId) {
+ this.view = view;
+ this.id = id;
+ this.parentId = parentId;
+ this.adapter = (ArrayAdapter<String>) view.getAdapter();
+ }
- public void setSpinnerList(List<RegionData> list, String defaultKey) {
- mCurrentRegions = list;
- mAdapter.clear();
- for (RegionData item : list) {
- mAdapter.add(item.getDisplayName());
- }
- mAdapter.sort(Collator.getInstance(Locale.getDefault()));
- if (defaultKey.length() == 0) {
- mView.setSelection(0);
- } else {
- int position = mAdapter.getPosition(defaultKey);
- mView.setSelection(position);
- }
- }
+ public void setSpinnerList(List<RegionData> list, String defaultKey) {
+ currentRegions = list;
+ adapter.clear();
+ for (RegionData item : list) {
+ adapter.add(item.getDisplayName());
+ }
+ adapter.sort(Collator.getInstance(Locale.getDefault()));
+ if (defaultKey.length() == 0) {
+ view.setSelection(0);
+ } else {
+ int position = adapter.getPosition(defaultKey);
+ view.setSelection(position);
+ }
+ }
- // Returns the region key of the currently selected region in the Spinner.
- public String getRegionCode(int position) {
- if (mAdapter.getCount() <= position) {
- return "";
- }
- String value = mAdapter.getItem(position);
- return getRegionDataKeyForValue(value);
- }
+ // Returns the region key of the currently selected region in the Spinner.
+ public String getRegionCode(int position) {
+ if (adapter.getCount() <= position) {
+ return "";
+ }
+ String value = adapter.getItem(position);
+ return getRegionDataKeyForValue(value);
+ }
- // Returns the region key for the region value.
- public String getRegionDataKeyForValue(String value) {
- for (RegionData data : mCurrentRegions) {
- if (data.getDisplayName().endsWith(value)) {
- return data.getKey();
- }
- }
- return "";
+ // Returns the region key for the region value.
+ public String getRegionDataKeyForValue(String value) {
+ for (RegionData data : currentRegions) {
+ if (data.getDisplayName().endsWith(value)) {
+ return data.getKey();
}
+ }
+ return "";
}
+ }
- private final ArrayList<AddressSpinnerInfo> mSpinners = new ArrayList<AddressSpinnerInfo>();
+ private final ArrayList<AddressSpinnerInfo> spinners = new ArrayList<AddressSpinnerInfo>();
- private AddressWidgetUiComponentProvider mComponentProvider;
+ private AddressWidgetUiComponentProvider componentProvider;
- /** TODO: Add region-dependent width types for address fields. */
- private WidthType getFieldWidthType(AddressUiComponent field) {
- return field.getId().getDefaulWidthType();
- }
+ /** TODO: Add region-dependent width types for address fields. */
+ private WidthType getFieldWidthType(AddressUiComponent field) {
+ return field.getId().getDefaulWidthType();
+ }
- private void createView(ViewGroup rootView, AddressUiComponent field, String defaultKey,
- boolean readOnly) {
- @SuppressWarnings("deprecation") // FILL_PARENT renamed MATCH_PARENT in API Level 8.
+ private void createView(ViewGroup rootView, AddressUiComponent field, String defaultKey,
+ boolean readOnly) {
+ @SuppressWarnings("deprecation") // FILL_PARENT renamed MATCH_PARENT in API Level 8.
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
- LayoutParams.WRAP_CONTENT);
- String fieldText = field.getFieldName();
- WidthType widthType = getFieldWidthType(field);
-
- if (fieldText.length() > 0) {
- TextView textView = mComponentProvider.createUiLabel(fieldText, widthType);
- rootView.addView(textView, lp);
- }
- if (field.getUiType().equals(UiComponent.EDIT)) {
- EditText editText = mComponentProvider.createUiTextField(widthType);
- field.setView(editText);
- editText.setEnabled(!readOnly);
- rootView.addView(editText, lp);
- } else if (field.getUiType().equals(UiComponent.SPINNER)) {
- ArrayAdapter<String> adapter = mComponentProvider.createUiPickerAdapter(widthType);
- Spinner spinner = mComponentProvider.createUiPickerSpinner(widthType);
-
- field.setView(spinner);
- rootView.addView(spinner, lp);
- spinner.setAdapter(adapter);
- AddressSpinnerInfo spinnerInfo =
- new AddressSpinnerInfo(spinner, field.getId(), field.getParentId());
- spinnerInfo.setSpinnerList(field.getCandidatesList(), defaultKey);
-
- if (fieldText.length() > 0) {
- spinner.setPrompt(fieldText);
- }
- spinner.setOnItemSelectedListener(this);
- mSpinners.add(spinnerInfo);
- }
- }
-
- /**
- * Associates each field with its corresponding AddressUiComponent.
- */
- private void buildFieldWidgets() {
- AddressData data = new AddressData.Builder().setCountry(mCurrentRegion).build();
- LookupKey key = new LookupKey.Builder(LookupKey.KeyType.DATA).setAddressData(data).build();
- AddressVerificationNodeData countryNode =
- (new ClientData(mCacheData)).getDefaultData(key.toString());
-
- // Set up AddressField.ADMIN_AREA
- AddressUiComponent adminAreaUi = new AddressUiComponent(AddressField.ADMIN_AREA);
- adminAreaUi.setFieldName(getAdminAreaFieldName(countryNode));
- mInputWidgets.put(AddressField.ADMIN_AREA, adminAreaUi);
-
- // Set up AddressField.LOCALITY
- AddressUiComponent localityUi = new AddressUiComponent(AddressField.LOCALITY);
- localityUi.setFieldName(getLocalityFieldName(countryNode));
- mInputWidgets.put(AddressField.LOCALITY, localityUi);
-
- // Set up AddressField.DEPENDENT_LOCALITY
- AddressUiComponent subLocalityUi = new AddressUiComponent(AddressField.DEPENDENT_LOCALITY);
- subLocalityUi.setFieldName(mContext.getString(R.string.i18n_dependent_locality_label));
- mInputWidgets.put(AddressField.DEPENDENT_LOCALITY, subLocalityUi);
-
- // Set up AddressField.ADDRESS_LINE_1
- AddressUiComponent addressLine1Ui = new AddressUiComponent(AddressField.ADDRESS_LINE_1);
- addressLine1Ui.setFieldName(mContext.getString(R.string.i18n_address_line1_label));
- mInputWidgets.put(AddressField.ADDRESS_LINE_1, addressLine1Ui);
-
- // Set up AddressField.ADDRESS_LINE_2
- AddressUiComponent addressLine2Ui = new AddressUiComponent(AddressField.ADDRESS_LINE_2);
- addressLine2Ui.setFieldName("");
- mInputWidgets.put(AddressField.ADDRESS_LINE_2, addressLine2Ui);
-
- // Set up AddressField.ORGANIZATION
- AddressUiComponent organizationUi = new AddressUiComponent(AddressField.ORGANIZATION);
- organizationUi.setFieldName(mContext.getString(R.string.i18n_organization_label));
- mInputWidgets.put(AddressField.ORGANIZATION, organizationUi);
-
- // Set up AddressField.RECIPIENT
- AddressUiComponent recipientUi = new AddressUiComponent(AddressField.RECIPIENT);
- recipientUi.setFieldName(mContext.getString(R.string.i18n_recipient_label));
- mInputWidgets.put(AddressField.RECIPIENT, recipientUi);
-
- // Set up AddressField.POSTAL_CODE
- AddressUiComponent postalCodeUi = new AddressUiComponent(AddressField.POSTAL_CODE);
- postalCodeUi.setFieldName(getZipFieldName(countryNode));
- mInputWidgets.put(AddressField.POSTAL_CODE, postalCodeUi);
-
- // Set up AddressField.SORTING_CODE
- AddressUiComponent sortingCodeUi = new AddressUiComponent(AddressField.SORTING_CODE);
- sortingCodeUi.setFieldName("CEDEX");
- mInputWidgets.put(AddressField.SORTING_CODE, sortingCodeUi);
- }
-
- private void initializeDropDowns() {
- AddressUiComponent adminAreaUi = mInputWidgets.get(AddressField.ADMIN_AREA);
- List<RegionData> adminAreaList = getRegionData(AddressField.COUNTRY);
- adminAreaUi.initializeCandidatesList(adminAreaList);
-
- AddressUiComponent localityUi = mInputWidgets.get(AddressField.LOCALITY);
- List<RegionData> localityList = getRegionData(AddressField.ADMIN_AREA);
- localityUi.initializeCandidatesList(localityList);
- }
-
- // Zip code is called postal code in some countries. This method returns the appropriate name
- // for the given countryNode.
- private String getZipFieldName(AddressVerificationNodeData countryNode) {
- String zipName;
- String zipType = countryNode.get(AddressDataKey.ZIP_NAME_TYPE);
- if (zipType == null) {
- mZipLabel = ZipLabel.POSTAL;
- zipName = mContext.getString(R.string.i18n_postal_code_label);
- } else {
- mZipLabel = ZipLabel.ZIP;
- zipName = mContext.getString(R.string.i18n_zip_code_label);
- }
- return zipName;
- }
-
- private String getLocalityFieldName(AddressVerificationNodeData countryNode) {
- String localityLabelType = countryNode.get(AddressDataKey.LOCALITY_NAME_TYPE);
- mLocalityLabel = localityLabelType;
- Integer result = LOCALITY_LABELS.get(localityLabelType);
- if (result == null) {
- // Fallback to city.
- result = R.string.i18n_locality_label;
- }
- return mContext.getString(result);
+ LayoutParams.WRAP_CONTENT);
+ String fieldText = field.getFieldName();
+ WidthType widthType = getFieldWidthType(field);
+
+ if (fieldText.length() > 0) {
+ TextView textView = componentProvider.createUiLabel(fieldText, widthType);
+ rootView.addView(textView, lp);
+ }
+ if (field.getUiType().equals(UiComponent.EDIT)) {
+ EditText editText = componentProvider.createUiTextField(widthType);
+ field.setView(editText);
+ editText.setEnabled(!readOnly);
+ rootView.addView(editText, lp);
+ } else if (field.getUiType().equals(UiComponent.SPINNER)) {
+ ArrayAdapter<String> adapter = componentProvider.createUiPickerAdapter(widthType);
+ Spinner spinner = componentProvider.createUiPickerSpinner(widthType);
+
+ field.setView(spinner);
+ rootView.addView(spinner, lp);
+ spinner.setAdapter(adapter);
+ AddressSpinnerInfo spinnerInfo =
+ new AddressSpinnerInfo(spinner, field.getId(), field.getParentId());
+ spinnerInfo.setSpinnerList(field.getCandidatesList(), defaultKey);
+
+ if (fieldText.length() > 0) {
+ spinner.setPrompt(fieldText);
+ }
+ spinner.setOnItemSelectedListener(this);
+ spinners.add(spinnerInfo);
+ }
+ }
+
+ /**
+ * Associates each field with its corresponding AddressUiComponent.
+ */
+ private void buildFieldWidgets() {
+ AddressData data = new AddressData.Builder().setCountry(currentRegion).build();
+ LookupKey key = new LookupKey.Builder(LookupKey.KeyType.DATA).setAddressData(data).build();
+ AddressVerificationNodeData countryNode =
+ (new ClientData(cacheData)).getDefaultData(key.toString());
+
+ // Set up AddressField.ADMIN_AREA
+ AddressUiComponent adminAreaUi = new AddressUiComponent(AddressField.ADMIN_AREA);
+ adminAreaUi.setFieldName(getAdminAreaFieldName(countryNode));
+ inputWidgets.put(AddressField.ADMIN_AREA, adminAreaUi);
+
+ // Set up AddressField.LOCALITY
+ AddressUiComponent localityUi = new AddressUiComponent(AddressField.LOCALITY);
+ localityUi.setFieldName(getLocalityFieldName(countryNode));
+ inputWidgets.put(AddressField.LOCALITY, localityUi);
+
+ // Set up AddressField.DEPENDENT_LOCALITY
+ AddressUiComponent subLocalityUi = new AddressUiComponent(AddressField.DEPENDENT_LOCALITY);
+ subLocalityUi.setFieldName(getSublocalityFieldName(countryNode));
+ inputWidgets.put(AddressField.DEPENDENT_LOCALITY, subLocalityUi);
+
+ // Set up AddressField.ADDRESS_LINE_1
+ AddressUiComponent addressLine1Ui = new AddressUiComponent(AddressField.ADDRESS_LINE_1);
+ addressLine1Ui.setFieldName(context.getString(R.string.i18n_address_line1_label));
+ inputWidgets.put(AddressField.ADDRESS_LINE_1, addressLine1Ui);
+
+ // Set up AddressField.ADDRESS_LINE_2
+ AddressUiComponent addressLine2Ui = new AddressUiComponent(AddressField.ADDRESS_LINE_2);
+ addressLine2Ui.setFieldName("");
+ inputWidgets.put(AddressField.ADDRESS_LINE_2, addressLine2Ui);
+
+ // Set up AddressField.ORGANIZATION
+ AddressUiComponent organizationUi = new AddressUiComponent(AddressField.ORGANIZATION);
+ organizationUi.setFieldName(context.getString(R.string.i18n_organization_label));
+ inputWidgets.put(AddressField.ORGANIZATION, organizationUi);
+
+ // Set up AddressField.RECIPIENT
+ AddressUiComponent recipientUi = new AddressUiComponent(AddressField.RECIPIENT);
+ recipientUi.setFieldName(context.getString(R.string.i18n_recipient_label));
+ inputWidgets.put(AddressField.RECIPIENT, recipientUi);
+
+ // Set up AddressField.POSTAL_CODE
+ AddressUiComponent postalCodeUi = new AddressUiComponent(AddressField.POSTAL_CODE);
+ postalCodeUi.setFieldName(getZipFieldName(countryNode));
+ inputWidgets.put(AddressField.POSTAL_CODE, postalCodeUi);
+
+ // Set up AddressField.SORTING_CODE
+ AddressUiComponent sortingCodeUi = new AddressUiComponent(AddressField.SORTING_CODE);
+ sortingCodeUi.setFieldName("CEDEX");
+ inputWidgets.put(AddressField.SORTING_CODE, sortingCodeUi);
+ }
+
+ private void initializeDropDowns() {
+ AddressUiComponent adminAreaUi = inputWidgets.get(AddressField.ADMIN_AREA);
+ List<RegionData> adminAreaList = getRegionData(AddressField.COUNTRY);
+ adminAreaUi.initializeCandidatesList(adminAreaList);
+
+ AddressUiComponent localityUi = inputWidgets.get(AddressField.LOCALITY);
+ List<RegionData> localityList = getRegionData(AddressField.ADMIN_AREA);
+ localityUi.initializeCandidatesList(localityList);
+ }
+
+ // ZIP code is called postal code in some countries. This method returns the appropriate name
+ // for the given countryNode.
+ private String getZipFieldName(AddressVerificationNodeData countryNode) {
+ String zipName;
+ String zipType = countryNode.get(AddressDataKey.ZIP_NAME_TYPE);
+ if (zipType == null) {
+ zipLabel = ZipLabel.POSTAL;
+ zipName = context.getString(R.string.i18n_postal_code_label);
+ } else {
+ zipLabel = ZipLabel.ZIP;
+ zipName = context.getString(R.string.i18n_zip_code_label);
+ }
+ return zipName;
+ }
+
+ private String getLocalityFieldName(AddressVerificationNodeData countryNode) {
+ String localityLabelType = countryNode.get(AddressDataKey.LOCALITY_NAME_TYPE);
+ Integer result = LOCALITY_LABELS.get(localityLabelType);
+ if (result == null) {
+ // Fallback to city.
+ result = R.string.i18n_locality_label;
+ }
+ return context.getString(result);
+ }
+
+ private String getSublocalityFieldName(AddressVerificationNodeData countryNode) {
+ String sublocalityLabelType = countryNode.get(AddressDataKey.SUBLOCALITY_NAME_TYPE);
+ Integer result = SUBLOCALITY_LABELS.get(sublocalityLabelType);
+ if (result == null) {
+ // Fallback to suburb.
+ result = R.string.i18n_suburb;
+ }
+ return context.getString(result);
+ }
+
+ private String getAdminAreaFieldName(AddressVerificationNodeData countryNode) {
+ String adminLabelType = countryNode.get(AddressDataKey.STATE_NAME_TYPE);
+ Integer result = ADMIN_LABELS.get(adminLabelType);
+ if (result == null) {
+ // Fallback to province.
+ result = R.string.i18n_province;
+ }
+ return context.getString(result);
+ }
+
+ private void buildCountryListBox() {
+ // Set up AddressField.COUNTRY
+ AddressUiComponent countryUi = new AddressUiComponent(AddressField.COUNTRY);
+ countryUi.setFieldName(context.getString(R.string.i18n_country_or_region_label));
+ ArrayList<RegionData> countries = new ArrayList<RegionData>();
+ for (RegionData regionData : formController.getRegionData(new LookupKey.Builder(
+ KeyType.DATA).build())) {
+ String regionKey = regionData.getKey();
+ // ZZ represents an unknown region code.
+ if (!regionKey.equals("ZZ")) {
+ String localCountryName = getLocalCountryName(regionKey);
+ RegionData country = new RegionData.Builder().setKey(regionKey).setName(
+ localCountryName).build();
+ countries.add(country);
+ }
}
+ countryUi.initializeCandidatesList(countries);
+ inputWidgets.put(AddressField.COUNTRY, countryUi);
+ }
- private String getAdminAreaFieldName(AddressVerificationNodeData countryNode) {
- String adminLabelType = countryNode.get(AddressDataKey.STATE_NAME_TYPE);
- mAdminLabel = adminLabelType;
- Integer result = ADMIN_LABELS.get(adminLabelType);
- if (result == null) {
- // Fallback to province.
- result = R.string.i18n_province;
- }
- return mContext.getString(result);
- }
-
- private void buildCountryListBox() {
- // Set up AddressField.COUNTRY
- AddressUiComponent countryUi = new AddressUiComponent(AddressField.COUNTRY);
- countryUi.setFieldName(mContext.getString(R.string.i18n_country_label));
- ArrayList<RegionData> countries = new ArrayList<RegionData>();
- for (RegionData regionData : mFormController.getRegionData(new LookupKey.Builder(
- KeyType.DATA).build())) {
- String regionKey = regionData.getKey();
- // ZZ represents an unknown region code.
- if (!regionKey.equals("ZZ")) {
- String localCountryName = getLocalCountryName(regionKey);
- RegionData country = new RegionData.Builder().setKey(regionKey).setName(
- localCountryName).build();
- countries.add(country);
- }
- }
- countryUi.initializeCandidatesList(countries);
- mInputWidgets.put(AddressField.COUNTRY, countryUi);
- }
+ private String getLocalCountryName(String regionCode) {
+ return (new Locale("", regionCode)).getDisplayCountry(Locale.getDefault());
+ }
- private String getLocalCountryName(String regionCode) {
- return (new Locale("", regionCode)).getDisplayCountry(Locale.getDefault());
+ private AddressSpinnerInfo findSpinnerByView(View view) {
+ for (AddressSpinnerInfo spinnerInfo : spinners) {
+ if (spinnerInfo.view == view) {
+ return spinnerInfo;
+ }
}
+ return null;
+ }
- private AddressSpinnerInfo findSpinnerByView(View view) {
- for (AddressSpinnerInfo spinnerInfo : mSpinners) {
- if (spinnerInfo.mView == view) {
- return spinnerInfo;
- }
- }
- return null;
- }
+ private void updateFields() {
+ removePreviousViews();
+ buildFieldWidgets();
+ initializeDropDowns();
+ layoutAddressFields();
+ }
- private void updateFields() {
- removePreviousViews();
- buildFieldWidgets();
- initializeDropDowns();
- layoutAddressFields();
+ private void removePreviousViews() {
+ if (rootView == null) {
+ return;
}
-
- private void removePreviousViews() {
- if (mRootView == null) {
- return;
- }
- int childCount = mRootView.getChildCount();
- if (mFormOptions.isHidden(AddressField.COUNTRY)) {
- if (childCount > 0) {
- mRootView.removeAllViews();
- }
- } else if (childCount > 2) {
- // Keep the TextView and Spinner for Country and remove everything else.
- mRootView.removeViews(2, mRootView.getChildCount() - 2);
- }
+ int childCount = rootView.getChildCount();
+ if (formOptions.isHidden(AddressField.COUNTRY)) {
+ if (childCount > 0) {
+ rootView.removeAllViews();
+ }
+ } else if (childCount > 2) {
+ // Keep the TextView and Spinner for Country and remove everything else.
+ rootView.removeViews(2, rootView.getChildCount() - 2);
}
+ }
- private void layoutAddressFields() {
- for (AddressField field : mFormatInterpreter.getAddressFieldOrder(mScript,
- mCurrentRegion)) {
- if (!mFormOptions.isHidden(field)) {
- createView(mRootView, mInputWidgets.get(field), "", mFormOptions.isReadonly(field));
- }
- }
+ private void layoutAddressFields() {
+ for (AddressField field : formatInterpreter.getAddressFieldOrder(script,
+ currentRegion)) {
+ if (!formOptions.isHidden(field)) {
+ createView(rootView, inputWidgets.get(field), "", formOptions.isReadonly(field));
+ }
}
+ }
- private void updateChildNodes(AdapterView<?> parent, int position) {
- AddressSpinnerInfo spinnerInfo = findSpinnerByView(parent);
- if (spinnerInfo == null) {
- return;
- }
-
- // Find all the child spinners, if any, that depend on this one.
- final AddressField myId = spinnerInfo.mId;
- if (myId != AddressField.COUNTRY && myId != AddressField.ADMIN_AREA
- && myId != AddressField.LOCALITY) {
- // Only a change in the three AddressFields above will trigger a change in other
- // AddressFields. Therefore, for all other AddressFields, we return immediately.
- return;
- }
-
- String regionCode = spinnerInfo.getRegionCode(position);
- if (myId == AddressField.COUNTRY) {
- updateWidgetOnCountryChange(regionCode);
- return;
- }
-
- mFormController.requestDataForAddress(getAddressData(), new DataLoadListener() {
- @Override
- public void dataLoadingBegin(){
- }
-
- @Override
- public void dataLoadingEnd() {
- Runnable updateChild = new UpdateRunnable(myId);
- mHandler.post(updateChild);
- }
- });
+ private void updateChildNodes(AdapterView<?> parent, int position) {
+ AddressSpinnerInfo spinnerInfo = findSpinnerByView(parent);
+ if (spinnerInfo == null) {
+ return;
}
- public void updateWidgetOnCountryChange(String regionCode) {
- if (mCurrentRegion.equalsIgnoreCase(regionCode)) {
- return;
- }
- mCurrentRegion = regionCode;
- mFormController.setCurrentCountry(mCurrentRegion);
- renderForm();
+ // Find all the child spinners, if any, that depend on this one.
+ final AddressField myId = spinnerInfo.id;
+ if (myId != AddressField.COUNTRY && myId != AddressField.ADMIN_AREA
+ && myId != AddressField.LOCALITY) {
+ // Only a change in the three AddressFields above will trigger a change in other
+ // AddressFields. Therefore, for all other AddressFields, we return immediately.
+ return;
}
- private void updateInputWidget(AddressField myId) {
- for (AddressSpinnerInfo child : mSpinners) {
- if (child.mParentId == myId) {
- List<RegionData> candidates = getRegionData(child.mParentId);
- child.setSpinnerList(candidates, "");
- }
- }
+ String regionCode = spinnerInfo.getRegionCode(position);
+ if (myId == AddressField.COUNTRY) {
+ updateWidgetOnCountryChange(regionCode);
+ return;
}
- public void renderForm() {
- setWidgetLocaleAndScript();
- AddressData data = new AddressData.Builder().setCountry(mCurrentRegion)
- .setLanguageCode(mWidgetLocale).build();
- mFormController.requestDataForAddress(data, new DataLoadListener() {
- @Override
- public void dataLoadingBegin() {
- mProgressDialog = mComponentProvider.getUiActivityIndicatorView();
- mProgressDialog.setMessage(mContext.getString(R.string.address_data_loading));
- Log.d(this.toString(), "Progress dialog started.");
- }
- @Override
- public void dataLoadingEnd() {
- Log.d(this.toString(), "Data loading completed.");
- mProgressDialog.dismiss();
- Log.d(this.toString(), "Progress dialog stopped.");
- mHandler.post(mUpdateMultipleFields);
- }
- });
- }
-
- private void setWidgetLocaleAndScript() {
- mWidgetLocale = Util.getWidgetCompatibleLanguageCode(Locale.getDefault(), mCurrentRegion);
- mFormController.setLanguageCode(mWidgetLocale);
- mScript = Util.isExplicitLatinScript(mWidgetLocale)
- ? ScriptType.LATIN
- : ScriptType.LOCAL;
- }
-
- private List<RegionData> getRegionData(AddressField parentField) {
- AddressData address = getAddressData();
-
- // Removes language code from address if it is default. This address is used to build
- // lookup key, which neglects default language. For example, instead of "data/US--en/CA",
- // the right lookup key is "data/US/CA".
- if (mFormController.isDefaultLanguage(address.getLanguageCode())) {
- address = new AddressData.Builder(address).setLanguageCode(null).build();
- }
+ formController.requestDataForAddress(getAddressData(), new DataLoadListener() {
+ @Override
+ public void dataLoadingBegin(){
+ }
- LookupKey parentKey = mFormController.getDataKeyFor(address).getKeyForUpperLevelField(
- parentField);
- List<RegionData> candidates;
- // Can't build a key with parent field, quit.
- if (parentKey == null) {
- Log.w(this.toString(), "Can't build key with parent field " + parentField + ". One of"
- + " the ancestor fields might be empty");
-
- // Removes candidates that exist from previous settings. For example, data/US has a
- // list of candidates AB, BC, CA, etc, that list should be cleaned up when user updates
- // the address by changing country to Channel Islands.
- candidates = new ArrayList<RegionData>(1);
- } else {
- candidates = mFormController.getRegionData(parentKey);
- }
- return candidates;
- }
-
- /**
- * Creates an AddressWidget to be attached to rootView for the specific context using the
- * default UI component provider.
- */
- public AddressWidget(Context context, ViewGroup rootView, FormOptions formOptions,
- ClientCacheManager cacheManager) {
- this(context, rootView, formOptions, cacheManager,
- new AddressWidgetUiComponentProvider(context));
- }
-
- /**
- * Creates an AddressWidget to be attached to rootView for the specific context using UI
- * component provided by the provider.
- */
- public AddressWidget(Context context, ViewGroup rootView, FormOptions formOptions,
- ClientCacheManager cacheManager, AddressWidgetUiComponentProvider provider) {
- mComponentProvider = provider;
- mCurrentRegion =
- ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE))
- .getSimCountryIso().toUpperCase(Locale.US);
- if (mCurrentRegion.length() == 0) {
- mCurrentRegion = "US";
- }
- init(context, rootView, formOptions, cacheManager);
- renderForm();
- }
-
- /**
- * Creates an AddressWidget to be attached to rootView for the specific context using the
- * default UI component provider, and fill out the address form with savedAddress.
- */
- public AddressWidget(Context context, ViewGroup rootView, FormOptions formOptions,
- ClientCacheManager cacheManager, AddressData savedAddress) {
- this(context, rootView, formOptions, cacheManager, savedAddress,
- new AddressWidgetUiComponentProvider(context));
- }
-
- /**
- * Creates an AddressWidget to be attached to rootView for the specific context using UI
- * component provided by the provider, and fill out the address form with savedAddress.
- */
- public AddressWidget(Context context, ViewGroup rootView, FormOptions formOptions,
- ClientCacheManager cacheManager, AddressData savedAddress,
- AddressWidgetUiComponentProvider provider) {
- mComponentProvider = provider;
- mCurrentRegion = savedAddress.getPostalCountry();
- // Postal country must be 2 letter country code. Otherwise default to US.
- if (mCurrentRegion == null || mCurrentRegion.length() != 2) {
- mCurrentRegion = "US";
- }
- init(context, rootView, formOptions, cacheManager);
- renderFormWithSavedAddress(savedAddress);
- }
-
- public void renderFormWithSavedAddress(AddressData savedAddress) {
- setWidgetLocaleAndScript();
- removePreviousViews();
- buildFieldWidgets();
- layoutAddressFields();
- initializeFieldsWithAddress(savedAddress);
- }
-
- private void initializeFieldsWithAddress(AddressData savedAddress) {
- for (AddressField field : mFormatInterpreter.getAddressFieldOrder(mScript,
- mCurrentRegion)) {
- String value = savedAddress.getFieldValue(field);
- if (value == null) {
- value = "";
- }
- AddressUiComponent uiComponent = mInputWidgets.get(field);
- EditText view = (EditText) uiComponent.getView();
- if (view != null) {
- view.setText(value);
- }
- }
+ @Override
+ public void dataLoadingEnd() {
+ Runnable updateChild = new UpdateRunnable(myId);
+ handler.post(updateChild);
+ }
+ });
+ }
+
+ public void updateWidgetOnCountryChange(String regionCode) {
+ if (currentRegion.equalsIgnoreCase(regionCode)) {
+ return;
+ }
+ currentRegion = regionCode;
+ formController.setCurrentCountry(currentRegion);
+ renderForm();
+ }
+
+ private void updateInputWidget(AddressField myId) {
+ for (AddressSpinnerInfo child : spinners) {
+ if (child.parentId == myId) {
+ List<RegionData> candidates = getRegionData(child.parentId);
+ child.setSpinnerList(candidates, "");
+ }
}
-
- private void init(Context context, ViewGroup rootView, FormOptions formOptions,
- ClientCacheManager cacheManager) {
- mContext = context;
- mRootView = rootView;
- mFormOptions = formOptions;
- mCacheData = new CacheData(cacheManager);
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mFormController =
- new FormController(new ClientData(mCacheData),
- mWidgetLocale, mCurrentRegion);
- mFormatInterpreter = new FormatInterpreter(mFormOptions);
- mVerifier = new StandardAddressVerifier(
- new FieldVerifier(new ClientData(mCacheData)));
- if (!formOptions.isHidden(AddressField.COUNTRY)) {
- buildCountryListBox();
- createView(mRootView, mInputWidgets.get(AddressField.COUNTRY),
- getLocalCountryName(mCurrentRegion),
- formOptions.isReadonly(AddressField.COUNTRY));
- }
+ }
+
+ public void renderForm() {
+ setWidgetLocaleAndScript();
+ AddressData data = new AddressData.Builder().setCountry(currentRegion)
+ .setLanguageCode(widgetLocale).build();
+ formController.requestDataForAddress(data, new DataLoadListener() {
+ @Override
+ public void dataLoadingBegin() {
+ progressDialog = componentProvider.getUiActivityIndicatorView();
+ progressDialog.setMessage(context.getString(R.string.address_data_loading));
+ Log.d(this.toString(), "Progress dialog started.");
+ }
+ @Override
+ public void dataLoadingEnd() {
+ Log.d(this.toString(), "Data loading completed.");
+ progressDialog.dismiss();
+ Log.d(this.toString(), "Progress dialog stopped.");
+ handler.post(updateMultipleFields);
+ }
+ });
+ }
+
+ private void setWidgetLocaleAndScript() {
+ widgetLocale = Util.getWidgetCompatibleLanguageCode(Locale.getDefault(), currentRegion);
+ formController.setLanguageCode(widgetLocale);
+ script = Util.isExplicitLatinScript(widgetLocale)
+ ? ScriptType.LATIN
+ : ScriptType.LOCAL;
+ }
+
+ private List<RegionData> getRegionData(AddressField parentField) {
+ AddressData address = getAddressData();
+
+ // Removes language code from address if it is default. This address is used to build
+ // lookup key, which neglects default language. For example, instead of "data/US--en/CA",
+ // the right lookup key is "data/US/CA".
+ if (formController.isDefaultLanguage(address.getLanguageCode())) {
+ address = new AddressData.Builder(address).setLanguageCode(null).build();
+ }
+
+ LookupKey parentKey = formController.getDataKeyFor(address).getKeyForUpperLevelField(
+ parentField);
+ List<RegionData> candidates;
+ // Can't build a key with parent field, quit.
+ if (parentKey == null) {
+ Log.w(this.toString(), "Can't build key with parent field " + parentField + ". One of"
+ + " the ancestor fields might be empty");
+
+ // Removes candidates that exist from previous settings. For example, data/US has a
+ // list of candidates AB, BC, CA, etc, that list should be cleaned up when user updates
+ // the address by changing country to Channel Islands.
+ candidates = new ArrayList<RegionData>(1);
+ } else {
+ candidates = formController.getRegionData(parentKey);
+ }
+ return candidates;
+ }
+
+ /**
+ * Creates an AddressWidget to be attached to rootView for the specific context using the
+ * default UI component provider.
+ */
+ public AddressWidget(Context context, ViewGroup rootView, FormOptions formOptions,
+ ClientCacheManager cacheManager) {
+ this(context, rootView, formOptions, cacheManager,
+ new AddressWidgetUiComponentProvider(context));
+ }
+
+ /**
+ * Creates an AddressWidget to be attached to rootView for the specific context using UI
+ * component provided by the provider.
+ */
+ public AddressWidget(Context context, ViewGroup rootView, FormOptions formOptions,
+ ClientCacheManager cacheManager, AddressWidgetUiComponentProvider provider) {
+ componentProvider = provider;
+ currentRegion =
+ ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE))
+ .getSimCountryIso().toUpperCase(Locale.US);
+ if (currentRegion.length() == 0) {
+ currentRegion = "US";
+ }
+ init(context, rootView, formOptions, cacheManager);
+ renderForm();
+ }
+
+ /**
+ * Creates an AddressWidget to be attached to rootView for the specific context using the
+ * default UI component provider, and fill out the address form with savedAddress.
+ */
+ public AddressWidget(Context context, ViewGroup rootView, FormOptions formOptions,
+ ClientCacheManager cacheManager, AddressData savedAddress) {
+ this(context, rootView, formOptions, cacheManager, savedAddress,
+ new AddressWidgetUiComponentProvider(context));
+ }
+
+ /**
+ * Creates an AddressWidget to be attached to rootView for the specific context using UI
+ * component provided by the provider, and fill out the address form with savedAddress.
+ */
+ public AddressWidget(Context context, ViewGroup rootView, FormOptions formOptions,
+ ClientCacheManager cacheManager, AddressData savedAddress,
+ AddressWidgetUiComponentProvider provider) {
+ componentProvider = provider;
+ currentRegion = savedAddress.getPostalCountry();
+ // Postal country must be 2 letter country code. Otherwise default to US.
+ if (currentRegion == null || currentRegion.length() != 2) {
+ currentRegion = "US";
+ }
+ init(context, rootView, formOptions, cacheManager);
+ renderFormWithSavedAddress(savedAddress);
+ }
+
+ public void renderFormWithSavedAddress(AddressData savedAddress) {
+ setWidgetLocaleAndScript();
+ removePreviousViews();
+ buildFieldWidgets();
+ layoutAddressFields();
+ initializeFieldsWithAddress(savedAddress);
+ }
+
+ private void initializeFieldsWithAddress(AddressData savedAddress) {
+ for (AddressField field : formatInterpreter.getAddressFieldOrder(script, currentRegion)) {
+ String value = savedAddress.getFieldValue(field);
+ if (value == null) {
+ value = "";
+ }
+ AddressUiComponent uiComponent = inputWidgets.get(field);
+ EditText view = (EditText) uiComponent.getView();
+ if (view != null) {
+ view.setText(value);
+ }
}
-
- /**
- * Sets address data server URL. Input URL cannot be null.
- *
- * @param url The service URL.
- */
- public void setUrl(String url) {
- mCacheData.setUrl(url);
- }
-
- /**
- * Gets user input address in AddressData format.
- */
- public AddressData getAddressData() {
- AddressData.Builder builder = new AddressData.Builder();
- builder.setCountry(mCurrentRegion);
- for (AddressField field : mFormatInterpreter.getAddressFieldOrder(mScript,
- mCurrentRegion)) {
- AddressUiComponent addressUiComponent = mInputWidgets.get(field);
- if (addressUiComponent != null) {
- String value = addressUiComponent.getValue();
- if (addressUiComponent.getUiType() == UiComponent.SPINNER) {
- // For drop-downs, return the key of the region selected instead of the value.
- View view = getViewForField(field);
- AddressSpinnerInfo spinnerInfo = findSpinnerByView(view);
- if (spinnerInfo != null) {
- value = spinnerInfo.getRegionDataKeyForValue(value);
- }
- }
- builder.set(field, value);
- }
- }
- builder.setLanguageCode(mWidgetLocale);
- return builder.build();
- }
-
- /**
- * Gets the formatted address.
- *
- * This method does not validate addresses. Also, it will "normalize" the result strings by
- * removing redundant spaces and empty lines.
- *
- * @return the formatted address
- */
- public List<String> getEnvelopeAddress() {
- return mFormatInterpreter.getEnvelopeAddress(getAddressData());
- }
-
- /**
- * Gets the formatted address based on the AddressData passed in.
- */
- public List<String> getEnvelopeAddress(AddressData address) {
- return mFormatInterpreter.getEnvelopeAddress(address);
- }
-
- /**
- * Gets the formatted address based on the AddressData passed in with none of the relevant
- * fields hidden.
- */
- public static List<String> getFullEnvelopeAddress(AddressData address) {
- return new FormatInterpreter(SHOW_ALL_FIELDS).getEnvelopeAddress(address);
- }
-
- /**
- * Get problems found in the address data entered by the user.
- */
- public AddressProblems getAddressProblems() {
- AddressProblems problems = new AddressProblems();
- AddressData addressData = getAddressData();
- mVerifier.verify(addressData, problems);
- return problems;
- }
-
- /**
- * Displays an appropriate error message when the AddressField contains an invalid entry.
- *
- * @return the View object representing the AddressField.
- */
- public View displayErrorMessageForInvalidEntryIn(AddressField field) {
- Log.d(this.toString(), "Display error message for the field: " + field.toString());
- AddressUiComponent addressUiComponent = mInputWidgets.get(field);
- if (addressUiComponent != null && addressUiComponent.getUiType() == UiComponent.EDIT) {
- int errorMessageId = getErrorMessageIdForInvalidEntryIn(field);
- EditText view = (EditText) addressUiComponent.getView();
- view.setError(mContext.getString(errorMessageId));
- return view;
- }
- return null;
- }
-
- private int getErrorMessageIdForInvalidEntryIn(AddressField field) {
- switch (field) {
- case ADMIN_AREA:
- return ADMIN_ERROR_MESSAGES.get(mAdminLabel);
- case LOCALITY:
- return R.string.invalid_locality_label;
- case DEPENDENT_LOCALITY:
- return R.string.invalid_dependent_locality_label;
- case POSTAL_CODE:
- return (mZipLabel == ZipLabel.POSTAL
- ? R.string.invalid_postal_code_label
- : R.string.invalid_zip_code_label);
- default:
- return R.string.invalid_entry;
- }
+ }
+
+ private void init(Context context, ViewGroup rootView, FormOptions formOptions,
+ ClientCacheManager cacheManager) {
+ this.context = context;
+ this.rootView = rootView;
+ this.formOptions = formOptions;
+ this.cacheData = new CacheData(cacheManager);
+ this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ this.formController =
+ new FormController(new ClientData(cacheData), widgetLocale, currentRegion);
+ this.formatInterpreter = new FormatInterpreter(formOptions);
+ this.verifier = new StandardAddressVerifier(new FieldVerifier(new ClientData(cacheData)));
+ if (!formOptions.isHidden(AddressField.COUNTRY)) {
+ buildCountryListBox();
+ createView(rootView, inputWidgets.get(AddressField.COUNTRY),
+ getLocalCountryName(currentRegion),
+ formOptions.isReadonly(AddressField.COUNTRY));
+ }
+ }
+
+ /**
+ * Sets address data server URL. Input URL cannot be null.
+ *
+ * @param url The service URL.
+ */
+ public void setUrl(String url) {
+ cacheData.setUrl(url);
+ }
+
+ /**
+ * Gets user input address in AddressData format.
+ */
+ public AddressData getAddressData() {
+ AddressData.Builder builder = new AddressData.Builder();
+ builder.setCountry(currentRegion);
+ for (AddressField field : formatInterpreter.getAddressFieldOrder(script,
+ currentRegion)) {
+ AddressUiComponent addressUiComponent = inputWidgets.get(field);
+ if (addressUiComponent != null) {
+ String value = addressUiComponent.getValue();
+ if (addressUiComponent.getUiType() == UiComponent.SPINNER) {
+ // For drop-downs, return the key of the region selected instead of the value.
+ View view = getViewForField(field);
+ AddressSpinnerInfo spinnerInfo = findSpinnerByView(view);
+ if (spinnerInfo != null) {
+ value = spinnerInfo.getRegionDataKeyForValue(value);
+ }
+ }
+ builder.set(field, value);
+ }
}
-
- /**
- * Clears all error messages in the UI.
- */
- public void clearErrorMessage() {
- for (AddressField field : mFormatInterpreter.getAddressFieldOrder(mScript,
- mCurrentRegion)) {
- AddressUiComponent addressUiComponent = mInputWidgets.get(field);
-
- if (addressUiComponent != null && addressUiComponent.getUiType() == UiComponent.EDIT) {
- EditText view = (EditText) addressUiComponent.getView();
- if (view != null) {
- view.setError(null);
- }
- }
+ builder.setLanguageCode(widgetLocale);
+ return builder.build();
+ }
+
+ /**
+ * Gets the formatted address.
+ *
+ * This method does not validate addresses. Also, it will "normalize" the result strings by
+ * removing redundant spaces and empty lines.
+ *
+ * @return the formatted address
+ */
+ public List<String> getEnvelopeAddress() {
+ return formatInterpreter.getEnvelopeAddress(getAddressData());
+ }
+
+ /**
+ * Gets the formatted address based on the AddressData passed in.
+ */
+ public List<String> getEnvelopeAddress(AddressData address) {
+ return formatInterpreter.getEnvelopeAddress(address);
+ }
+
+ /**
+ * Gets the formatted address based on the AddressData passed in with none of the relevant
+ * fields hidden.
+ */
+ public static List<String> getFullEnvelopeAddress(AddressData address) {
+ return new FormatInterpreter(SHOW_ALL_FIELDS).getEnvelopeAddress(address);
+ }
+
+ /**
+ * Get problems found in the address data entered by the user.
+ */
+ public AddressProblems getAddressProblems() {
+ AddressProblems problems = new AddressProblems();
+ AddressData addressData = getAddressData();
+ verifier.verify(addressData, problems);
+ return problems;
+ }
+
+ /**
+ * Displays an appropriate error message for an AddressField with a problem.
+ *
+ * @return the View object representing the AddressField.
+ */
+ public View displayErrorMessageForField(AddressData address,
+ AddressField field, AddressProblemType problem) {
+ Log.d(this.toString(), "Display error message for the field: " + field.toString());
+ AddressUiComponent addressUiComponent = inputWidgets.get(field);
+ if (addressUiComponent != null && addressUiComponent.getUiType() == UiComponent.EDIT) {
+ EditText view = (EditText) addressUiComponent.getView();
+ view.setError(getErrorMessageForInvalidEntry(address, field, problem));
+ return view;
+ }
+ return null;
+ }
+
+ private String getErrorMessageForInvalidEntry(AddressData address, AddressField field,
+ AddressProblemType problem) {
+ switch (problem) {
+ case MISSING_REQUIRED_FIELD:
+ return context.getString(R.string.i18n_missing_required_field);
+ case UNKNOWN_VALUE:
+ String currentValue = address.getFieldValue(field);
+ return String.format(context.getString(R.string.unknown_entry), currentValue);
+ case UNRECOGNIZED_FORMAT:
+ // We only support this error type for the Postal Code field.
+ return (zipLabel == ZipLabel.POSTAL
+ ? context.getString(R.string.unrecognized_format_postal_code)
+ : context.getString(R.string.unrecognized_format_zip_code));
+ case MISMATCHING_VALUE:
+ // We only support this error type for the Postal Code field.
+ return (zipLabel == ZipLabel.POSTAL
+ ? context.getString(R.string.mismatching_value_postal_code)
+ : context.getString(R.string.mismatching_value_zip_code));
+ }
+ return "";
+ }
+
+ /**
+ * Clears all error messages in the UI.
+ */
+ public void clearErrorMessage() {
+ for (AddressField field : formatInterpreter.getAddressFieldOrder(script,
+ currentRegion)) {
+ AddressUiComponent addressUiComponent = inputWidgets.get(field);
+
+ if (addressUiComponent != null && addressUiComponent.getUiType() == UiComponent.EDIT) {
+ EditText view = (EditText) addressUiComponent.getView();
+ if (view != null) {
+ view.setError(null);
}
- }
-
- public View getViewForField(AddressField field) {
- AddressUiComponent component = mInputWidgets.get(field);
- if (component == null) {
- return null;
}
- return component.getView();
}
+ }
- @Override
- public void onNothingSelected(AdapterView<?> arg0) {
+ public View getViewForField(AddressField field) {
+ AddressUiComponent component = inputWidgets.get(field);
+ if (component == null) {
+ return null;
}
+ return component.getView();
+ }
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- updateChildNodes(parent, position);
- }
+ @Override
+ public void onNothingSelected(AdapterView<?> arg0) {
+ }
+
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ updateChildNodes(parent, position);
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/AddressWidgetUiComponentProvider.java b/java/src/com/android/i18n/addressinput/AddressWidgetUiComponentProvider.java
index 9f5a350..31160b9 100644
--- a/java/src/com/android/i18n/addressinput/AddressWidgetUiComponentProvider.java
+++ b/java/src/com/android/i18n/addressinput/AddressWidgetUiComponentProvider.java
@@ -37,63 +37,63 @@ import com.android.i18n.addressinput.AddressField.WidthType;
* alongside the address widget.
*/
public class AddressWidgetUiComponentProvider {
- protected Context mContext;
- protected LayoutInflater mInflater;
+ protected Context context;
+ protected LayoutInflater inflater;
- public AddressWidgetUiComponentProvider(Context context) {
- mContext = context;
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
+ public AddressWidgetUiComponentProvider(Context context) {
+ this.context = context;
+ this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
- /**
- * Creates a label, e.g. "State", for an address input field.
- *
- * @param label the label of the address input field
- * @param widthType {@link WidthType} of the field
- * @return a custom {@link TextView} created for the field
- */
- protected TextView createUiLabel(CharSequence label, WidthType widthType) {
- TextView textView = (TextView) mInflater.inflate(R.layout.address_textview, null, false);
- textView.setText(label);
- return textView;
- }
+ /**
+ * Creates a label, e.g. "State", for an address input field.
+ *
+ * @param label the label of the address input field
+ * @param widthType {@link WidthType} of the field
+ * @return a custom {@link TextView} created for the field
+ */
+ protected TextView createUiLabel(CharSequence label, WidthType widthType) {
+ TextView textView = (TextView) inflater.inflate(R.layout.address_textview, null, false);
+ textView.setText(label);
+ return textView;
+ }
- /**
- * Creates a text input view for an address input field.
- *
- * @param widthType {@link WidthType} of the field
- * @return a custom {@link EditText} created for the field
- */
- protected EditText createUiTextField(WidthType widthType) {
- return (EditText) mInflater.inflate(R.layout.address_edittext, null, false);
- }
+ /**
+ * Creates a text input view for an address input field.
+ *
+ * @param widthType {@link WidthType} of the field
+ * @return a custom {@link EditText} created for the field
+ */
+ protected EditText createUiTextField(WidthType widthType) {
+ return (EditText) inflater.inflate(R.layout.address_edittext, null, false);
+ }
- /**
- * Creates a {@link Spinner} for a input field that uses UI picker.
- *
- * @param widthType {@link WidthType} of the field
- * @return a custom {@link Spinner} created for the field
- */
- protected Spinner createUiPickerSpinner(WidthType widthType) {
- return (Spinner) mInflater.inflate(R.layout.address_spinner, null, false);
- }
+ /**
+ * Creates a {@link Spinner} for a input field that uses UI picker.
+ *
+ * @param widthType {@link WidthType} of the field
+ * @return a custom {@link Spinner} created for the field
+ */
+ protected Spinner createUiPickerSpinner(WidthType widthType) {
+ return (Spinner) inflater.inflate(R.layout.address_spinner, null, false);
+ }
- /**
- * Creates an {@link ArrayAdapter} to work with the custom {@link Spinner} of a input field that
- * uses UI picker.
- *
- * @param widthType {@link WidthType} of the field
- * @return a custom {@link ArrayAdapter} for the field
- */
- protected ArrayAdapter<String> createUiPickerAdapter(WidthType widthType) {
- ArrayAdapter<String> adapter =
- new ArrayAdapter<String>(mContext, android.R.layout.simple_spinner_item);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- return adapter;
- }
+ /**
+ * Creates an {@link ArrayAdapter} to work with the custom {@link Spinner} of a input field that
+ * uses UI picker.
+ *
+ * @param widthType {@link WidthType} of the field
+ * @return a custom {@link ArrayAdapter} for the field
+ */
+ protected ArrayAdapter<String> createUiPickerAdapter(WidthType widthType) {
+ ArrayAdapter<String> adapter =
+ new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ return adapter;
+ }
- /** Gets an activity indicator to show that a task is in progress. */
- protected ProgressDialog getUiActivityIndicatorView() {
- return new ProgressDialog(mContext);
- }
+ /** Gets an activity indicator to show that a task is in progress. */
+ protected ProgressDialog getUiActivityIndicatorView() {
+ return new ProgressDialog(context);
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/CacheData.java b/java/src/com/android/i18n/addressinput/CacheData.java
index 4f98e6f..39942c9 100644
--- a/java/src/com/android/i18n/addressinput/CacheData.java
+++ b/java/src/com/android/i18n/addressinput/CacheData.java
@@ -34,385 +34,385 @@ import java.util.HashSet;
*/
public final class CacheData {
- /**
- * Used to identify the source of a log message.
- */
- private static final String TAG = "CacheData";
-
- /**
- * Time out value for the server to respond in millisecond.
- */
- private static final int TIMEOUT = 5000;
-
- /**
- * URL to get address data. You can also reset it by calling {@link #setUrl(String)}.
- */
- private String mServiceUrl;
-
- /**
- * Storage for all dynamically retrieved data.
- */
- private final JsoMap mCache;
-
- /**
- * CacheManager that handles caching that is needed by the client of the Address Widget.
- */
- private final ClientCacheManager mClientCacheManager;
-
- /**
- * All requests that have been sent.
- */
- private final HashSet<String> mRequestedKeys = new HashSet<String>();
-
- /**
- * All invalid requested keys. For example, if we request a random string "asdfsdf9o", and the
- * server responds by saying this key is invalid, it will be stored here.
- */
- private final HashSet<String> mBadKeys = new HashSet<String>();
-
- /**
- * Temporary store for {@code CacheListener}s. When a key is requested and still waiting for
- * server's response, the listeners for the same key will be temporary stored here. When the
- * server responded, these listeners will be triggered and then removed.
- */
- private final HashMap<LookupKey, HashSet<CacheListener>> mTemporaryListenerStore =
- new HashMap<LookupKey, HashSet<CacheListener>>();
-
- /**
- * Creates an instance of CacheData with an empty cache, and uses no caching that is external
- * to the AddressWidget.
- */
- public CacheData() {
- this(new SimpleClientCacheManager());
+ /**
+ * Used to identify the source of a log message.
+ */
+ private static final String TAG = "CacheData";
+
+ /**
+ * Time out value for the server to respond in millisecond.
+ */
+ private static final int TIMEOUT = 5000;
+
+ /**
+ * URL to get address data. You can also reset it by calling {@link #setUrl(String)}.
+ */
+ private String serviceUrl;
+
+ /**
+ * Storage for all dynamically retrieved data.
+ */
+ private final JsoMap cache;
+
+ /**
+ * CacheManager that handles caching that is needed by the client of the Address Widget.
+ */
+ private final ClientCacheManager clientCacheManager;
+
+ /**
+ * All requests that have been sent.
+ */
+ private final HashSet<String> requestedKeys = new HashSet<String>();
+
+ /**
+ * All invalid requested keys. For example, if we request a random string "asdfsdf9o", and the
+ * server responds by saying this key is invalid, it will be stored here.
+ */
+ private final HashSet<String> badKeys = new HashSet<String>();
+
+ /**
+ * Temporary store for {@code CacheListener}s. When a key is requested and still waiting for
+ * server's response, the listeners for the same key will be temporary stored here. When the
+ * server responded, these listeners will be triggered and then removed.
+ */
+ private final HashMap<LookupKey, HashSet<CacheListener>> temporaryListenerStore =
+ new HashMap<LookupKey, HashSet<CacheListener>>();
+
+ /**
+ * Creates an instance of CacheData with an empty cache, and uses no caching that is external
+ * to the AddressWidget.
+ */
+ public CacheData() {
+ this(new SimpleClientCacheManager());
+ }
+
+ /**
+ * Creates an instance of CacheData with an empty cache, and uses additional caching (external
+ * to the AddressWidget) specified by clientCacheManager.
+ */
+ public CacheData(ClientCacheManager clientCacheManager) {
+ this.clientCacheManager = clientCacheManager;
+ setUrl(clientCacheManager.getAddressServerUrl());
+ cache = JsoMap.createEmptyJsoMap();
+ }
+
+ /**
+ * This constructor is meant to be used together with external caching.
+ *
+ * Use case:
+ *
+ * After having finished using the address widget:
+ * String allCachedData = getJsonString();
+ * Cache (save) allCachedData wherever makes sense for your service / activity
+ *
+ * Before using it next time:
+ * Get the saved allCachedData string
+ * new ClientData(new CacheData(allCachedData))
+ *
+ * If you don't have any saved data you can either just pass an empty string to
+ * this constructor or use the other constructor.
+ *
+ * @param jsonString cached data from last time the class was used
+ */
+ public CacheData(String jsonString) {
+ clientCacheManager = new SimpleClientCacheManager();
+ setUrl(clientCacheManager.getAddressServerUrl());
+ JsoMap tempMap = null;
+ try {
+ tempMap = JsoMap.buildJsoMap(jsonString);
+ } catch (JSONException jsonE) {
+ // If parsing the JSON string throws an exception, default to
+ // starting with an empty cache.
+ Log.w(TAG, "Could not parse json string, creating empty cache instead.");
+ tempMap = JsoMap.createEmptyJsoMap();
+ } finally {
+ cache = tempMap;
}
+ }
- /**
- * Creates an instance of CacheData with an empty cache, and uses additional caching (external
- * to the AddressWidget) specified by clientCacheManager.
- */
- public CacheData(ClientCacheManager clientCacheManager) {
- mClientCacheManager = clientCacheManager;
- setUrl(mClientCacheManager.getAddressServerUrl());
- mCache = JsoMap.createEmptyJsoMap();
- }
+ /**
+ * Interface for all listeners to {@link CacheData} change. This is only used when multiple
+ * requests of the same key is dispatched and server has not responded yet.
+ */
+ private static interface CacheListener extends EventListener {
/**
- * This constructor is meant to be used together with external caching.
- *
- * Use case:
- *
- * After having finished using the address widget:
- * String allCachedData = getJsonString();
- * Cache (save) allCachedData wherever makes sense for your service / activity
- *
- * Before using it next time:
- * Get the saved allCachedData string
- * new ClientData(new CacheData(allCachedData))
- *
- * If you don't have any saved data you can either just pass an empty string to
- * this constructor or use the other constructor.
+ * The function that will be called when valid data is about to be put in the cache.
*
- * @param jsonString cached data from last time the class was used
+ * @param key the key for newly arrived data.
*/
- public CacheData(String jsonString) {
- mClientCacheManager = new SimpleClientCacheManager();
- setUrl(mClientCacheManager.getAddressServerUrl());
- JsoMap tempMap = null;
- try {
- tempMap = JsoMap.buildJsoMap(jsonString);
- } catch (JSONException jsonE) {
- // If parsing the JSON string throws an exception, default to
- // starting with an empty cache.
- Log.w(TAG, "Could not parse json string, creating empty cache instead.");
- tempMap = JsoMap.createEmptyJsoMap();
- } finally {
- mCache = tempMap;
- }
- }
+ void onAdd(String key);
+ }
- /**
- * Interface for all listeners to {@link CacheData} change. This is only used when multiple
- * requests of the same key is dispatched and server has not responded yet.
- */
- private static interface CacheListener extends EventListener {
-
- /**
- * The function that will be called when valid data is about to be put in the cache.
- *
- * @param key the key for newly arrived data.
- */
- void onAdd(String key);
- }
+ /**
+ * Class to handle JSON response.
+ */
+ private class JsonHandler {
/**
- * Class to handle JSON response.
+ * Key for the requested data.
*/
- private class JsonHandler {
-
- /**
- * Key for the requested data.
- */
- private final String mKey;
-
- /**
- * Pre-existing data for the requested key. Null is allowed.
- */
- private final JSONObject mExistingJso;
-
- private final DataLoadListener mListener;
-
- /**
- * Constructs a JsonHandler instance.
- *
- * @param key The key for requested data.
- * @param oldJso Pre-existing data for this key or null.
- */
- private JsonHandler(String key, JSONObject oldJso, DataLoadListener listener) {
- checkNotNull(key);
- mKey = key;
- mExistingJso = oldJso;
- mListener = listener;
- }
-
- /**
- * Saves valid responded data to the cache once data arrives, or if the key is invalid,
- * saves it in the invalid cache. If there is pre-existing data for the key, it will merge
- * the new data will the old one. It also triggers {@link DataLoadListener#dataLoadingEnd()}
- * method before it returns (even when the key is invalid, or input jso is null). This is
- * called from a background thread.
- *
- * @param map The received JSON data as a map.
- */
- private void handleJson(JsoMap map) {
- // Can this ever happen?
- if (map == null) {
- Log.w(TAG, "server returns null for key:" + mKey);
- mBadKeys.add(mKey);
- notifyListenersAfterJobDone(mKey);
- triggerDataLoadingEndIfNotNull(mListener);
- return;
- }
-
- JSONObject json = map;
- String idKey = AddressDataKey.ID.name().toLowerCase();
- if (!json.has(idKey)) {
- Log.w(TAG, "invalid or empty data returned for key: " + mKey);
- mBadKeys.add(mKey);
- notifyListenersAfterJobDone(mKey);
- triggerDataLoadingEndIfNotNull(mListener);
- return;
- }
-
- if (mExistingJso != null) {
- map.mergeData((JsoMap) mExistingJso);
- }
-
- mCache.putObj(mKey, map);
- notifyListenersAfterJobDone(mKey);
- triggerDataLoadingEndIfNotNull(mListener);
- }
- }
+ private final String key;
/**
- * Sets address data server URL. Input URL cannot be null.
- *
- * @param url The service URL.
+ * Pre-existing data for the requested key. Null is allowed.
*/
- public void setUrl(String url) {
- checkNotNull(url, "Cannot set URL of address data server to null.");
- mServiceUrl = url;
- }
+ private final JSONObject existingJso;
- /**
- * Gets address data server URL.
- */
- public String getUrl() {
- return mServiceUrl;
- }
+ private final DataLoadListener listener;
/**
- * Returns a JSON string representing the data currently stored in this cache. It can be used
- * to later create a new CacheData object containing the same cached data.
+ * Constructs a JsonHandler instance.
*
- * @return a JSON string representing the data stored in this cache
+ * @param key The key for requested data.
+ * @param oldJso Pre-existing data for this key or null.
*/
- public String getJsonString() {
- return mCache.toString();
- }
-
- /**
- * Checks if key and its value is cached (Note that only valid ones are cached).
- */
- public boolean containsKey(String key) {
- return mCache.containsKey(key);
- }
-
- // This method is called from a background thread.
- private void triggerDataLoadingEndIfNotNull(DataLoadListener listener) {
- if (listener != null) {
- listener.dataLoadingEnd();
- }
+ private JsonHandler(String key, JSONObject oldJso, DataLoadListener listener) {
+ checkNotNull(key);
+ this.key = key;
+ this.existingJso = oldJso;
+ this.listener = listener;
}
/**
- * Fetches data from server, or returns if the data is already cached. If the fetched data is
- * valid, it will be added to the cache. This method also triggers {@link
- * DataLoadListener#dataLoadingEnd()} method before it returns.
+ * Saves valid responded data to the cache once data arrives, or if the key is invalid,
+ * saves it in the invalid cache. If there is pre-existing data for the key, it will merge
+ * the new data will the old one. It also triggers {@link DataLoadListener#dataLoadingEnd()}
+ * method before it returns (even when the key is invalid, or input jso is null). This is
+ * called from a background thread.
*
- * @param existingJso Pre-existing data for this key or null if none.
- * @param listener An optional listener to call when done.
+ * @param map The received JSON data as a map.
*/
- void fetchDynamicData(final LookupKey key, JSONObject existingJso,
- final DataLoadListener listener) {
- checkNotNull(key, "null key not allowed.");
-
- if (listener != null) {
- listener.dataLoadingBegin();
- }
-
- // Key is valid and cached.
- if (mCache.containsKey(key.toString())) {
- triggerDataLoadingEndIfNotNull(listener);
- return;
- }
-
- // Key is invalid and cached.
- if (mBadKeys.contains(key.toString())) {
- triggerDataLoadingEndIfNotNull(listener);
- return;
- }
-
- // Already requested the key, and is still waiting for server's response.
- if (!mRequestedKeys.add(key.toString())) {
- Log.d(TAG, "data for key " + key + " requested but not cached yet");
- addListenerToTempStore(key, new CacheListener() {
- @Override
- public void onAdd(String myKey) {
- triggerDataLoadingEndIfNotNull(listener);
- }
- });
- return;
- }
-
- // Key is in the cache maintained by the client of the AddressWidget.
- String dataFromClientCache = mClientCacheManager.get(key.toString());
- if (dataFromClientCache != null && dataFromClientCache.length() > 0) {
- final JsonHandler handler = new JsonHandler(key.toString(),
- existingJso, listener);
- try {
- handler.handleJson(JsoMap.buildJsoMap(dataFromClientCache));
- return;
- } catch (JSONException e) {
- Log.w(TAG, "Data from client's cache is in the wrong format: "
- + dataFromClientCache);
- }
- }
-
- // Key is not cached yet, now sending the request to the server.
- JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
- jsonp.setTimeout(TIMEOUT);
- final JsonHandler handler = new JsonHandler(key.toString(),
- existingJso, listener);
- jsonp.requestObject(mServiceUrl + "/" + key.toString(),
- new AsyncCallback<JsoMap>() {
- @Override
- public void onFailure(Throwable caught) {
- Log.w(TAG, "Request for key " + key + " failed");
- mRequestedKeys.remove(key.toString());
- notifyListenersAfterJobDone(key.toString());
- triggerDataLoadingEndIfNotNull(listener);
- }
-
- @Override
- public void onSuccess(JsoMap result) {
- handler.handleJson(result);
- // Put metadata into the cache maintained by the client of the
- // AddressWidget.
- String dataRetrieved = result.toString();
- mClientCacheManager.put(key.toString(), dataRetrieved);
- }
- });
+ private void handleJson(JsoMap map) {
+ // Can this ever happen?
+ if (map == null) {
+ Log.w(TAG, "server returns null for key:" + key);
+ badKeys.add(key);
+ notifyListenersAfterJobDone(key);
+ triggerDataLoadingEndIfNotNull(listener);
+ return;
+ }
+
+ JSONObject json = map;
+ String idKey = AddressDataKey.ID.name().toLowerCase();
+ if (!json.has(idKey)) {
+ Log.w(TAG, "invalid or empty data returned for key: " + key);
+ badKeys.add(key);
+ notifyListenersAfterJobDone(key);
+ triggerDataLoadingEndIfNotNull(listener);
+ return;
+ }
+
+ if (existingJso != null) {
+ map.mergeData((JsoMap) existingJso);
+ }
+
+ cache.putObj(key, map);
+ notifyListenersAfterJobDone(key);
+ triggerDataLoadingEndIfNotNull(listener);
}
-
- /**
- * Gets region data from our compiled-in java file and stores it in the
- * cache. This is only called when data cannot be obtained from the server,
- * so there will be no pre-existing data for this key.
- */
- void getFromRegionDataConstants(final LookupKey key) {
- checkNotNull(key, "null key not allowed.");
- String data = RegionDataConstants.getCountryFormatMap().get(
- key.getValueForUpperLevelField(AddressField.COUNTRY));
- if (data != null) {
- try {
- mCache.putObj(key.toString(), JsoMap.buildJsoMap(data));
- } catch (JSONException e) {
- Log.w(TAG, "Failed to parse data for key " + key +
- " from RegionDataConstants");
- }
- }
+ }
+
+ /**
+ * Sets address data server URL. Input URL cannot be null.
+ *
+ * @param url The service URL.
+ */
+ public void setUrl(String url) {
+ checkNotNull(url, "Cannot set URL of address data server to null.");
+ serviceUrl = url;
+ }
+
+ /**
+ * Gets address data server URL.
+ */
+ public String getUrl() {
+ return serviceUrl;
+ }
+
+ /**
+ * Returns a JSON string representing the data currently stored in this cache. It can be used
+ * to later create a new CacheData object containing the same cached data.
+ *
+ * @return a JSON string representing the data stored in this cache
+ */
+ public String getJsonString() {
+ return cache.toString();
+ }
+
+ /**
+ * Checks if key and its value is cached (Note that only valid ones are cached).
+ */
+ public boolean containsKey(String key) {
+ return cache.containsKey(key);
+ }
+
+ // This method is called from a background thread.
+ private void triggerDataLoadingEndIfNotNull(DataLoadListener listener) {
+ if (listener != null) {
+ listener.dataLoadingEnd();
}
-
- /**
- * Retrieves string data identified by key.
- *
- * @param key Non-null key. E.g., "data/US/CA".
- * @return String value for specified key.
- */
- public String get(String key) {
- checkNotNull(key, "null key not allowed");
- return mCache.get(key);
+ }
+
+ /**
+ * Fetches data from server, or returns if the data is already cached. If the fetched data is
+ * valid, it will be added to the cache. This method also triggers {@link
+ * DataLoadListener#dataLoadingEnd()} method before it returns.
+ *
+ * @param existingJso Pre-existing data for this key or null if none.
+ * @param listener An optional listener to call when done.
+ */
+ void fetchDynamicData(final LookupKey key, JSONObject existingJso,
+ final DataLoadListener listener) {
+ checkNotNull(key, "null key not allowed.");
+
+ if (listener != null) {
+ listener.dataLoadingBegin();
}
- /**
- * Retrieves JsoMap data identified by key.
- *
- * @param key Non-null key. E.g., "data/US/CA".
- * @return String value for specified key.
- */
- public JsoMap getObj(String key) {
- checkNotNull(key, "null key not allowed");
- return mCache.getObj(key);
+ // Key is valid and cached.
+ if (cache.containsKey(key.toString())) {
+ triggerDataLoadingEndIfNotNull(listener);
+ return;
}
- private void notifyListenersAfterJobDone(String key) {
- LookupKey lookupKey = new LookupKey.Builder(key).build();
- HashSet<CacheListener> listeners = mTemporaryListenerStore.get(lookupKey);
- if (listeners != null) {
- for (CacheListener listener : listeners) {
- listener.onAdd(key.toString());
- }
- listeners.clear();
- }
+ // Key is invalid and cached.
+ if (badKeys.contains(key.toString())) {
+ triggerDataLoadingEndIfNotNull(listener);
+ return;
}
- private void addListenerToTempStore(LookupKey key, CacheListener listener) {
- checkNotNull(key);
- checkNotNull(listener);
- HashSet<CacheListener> listeners = mTemporaryListenerStore.get(key);
- if (listeners == null) {
- listeners = new HashSet<CacheListener>();
- mTemporaryListenerStore.put(key, listeners);
+ // Already requested the key, and is still waiting for server's response.
+ if (!requestedKeys.add(key.toString())) {
+ Log.d(TAG, "data for key " + key + " requested but not cached yet");
+ addListenerToTempStore(key, new CacheListener() {
+ @Override
+ public void onAdd(String myKey) {
+ triggerDataLoadingEndIfNotNull(listener);
}
- listeners.add(listener);
+ });
+ return;
}
- /**
- * Added for testing purposes.
- * Adds a new object into the cache.
- * @param id string of the format "data/country/.." ie. "data/US/CA"
- * @param object The JSONObject to be put into cache.
- */
- void addToJsoMap(String id, JSONObject object) {
- mCache.putObj(id, object);
+ // Key is in the cache maintained by the client of the AddressWidget.
+ String dataFromClientCache = clientCacheManager.get(key.toString());
+ if (dataFromClientCache != null && dataFromClientCache.length() > 0) {
+ final JsonHandler handler = new JsonHandler(key.toString(),
+ existingJso, listener);
+ try {
+ handler.handleJson(JsoMap.buildJsoMap(dataFromClientCache));
+ return;
+ } catch (JSONException e) {
+ Log.w(TAG, "Data from client's cache is in the wrong format: "
+ + dataFromClientCache);
+ }
}
- /**
- * Added for testing purposes.
- * Checks to see if the cache is empty,
- * @return true if the internal cache is empty
- */
- boolean isEmpty() {
- return mCache.length() == 0;
+ // Key is not cached yet, now sending the request to the server.
+ JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
+ jsonp.setTimeout(TIMEOUT);
+ final JsonHandler handler = new JsonHandler(key.toString(),
+ existingJso, listener);
+ jsonp.requestObject(serviceUrl + "/" + key.toString(),
+ new AsyncCallback<JsoMap>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ Log.w(TAG, "Request for key " + key + " failed");
+ requestedKeys.remove(key.toString());
+ notifyListenersAfterJobDone(key.toString());
+ triggerDataLoadingEndIfNotNull(listener);
+ }
+
+ @Override
+ public void onSuccess(JsoMap result) {
+ handler.handleJson(result);
+ // Put metadata into the cache maintained by the client of the
+ // AddressWidget.
+ String dataRetrieved = result.toString();
+ clientCacheManager.put(key.toString(), dataRetrieved);
+ }
+ });
+ }
+
+ /**
+ * Gets region data from our compiled-in java file and stores it in the
+ * cache. This is only called when data cannot be obtained from the server,
+ * so there will be no pre-existing data for this key.
+ */
+ void getFromRegionDataConstants(final LookupKey key) {
+ checkNotNull(key, "null key not allowed.");
+ String data = RegionDataConstants.getCountryFormatMap().get(
+ key.getValueForUpperLevelField(AddressField.COUNTRY));
+ if (data != null) {
+ try {
+ cache.putObj(key.toString(), JsoMap.buildJsoMap(data));
+ } catch (JSONException e) {
+ Log.w(TAG, "Failed to parse data for key " + key +
+ " from RegionDataConstants");
+ }
+ }
+ }
+
+ /**
+ * Retrieves string data identified by key.
+ *
+ * @param key Non-null key. E.g., "data/US/CA".
+ * @return String value for specified key.
+ */
+ public String get(String key) {
+ checkNotNull(key, "null key not allowed");
+ return cache.get(key);
+ }
+
+ /**
+ * Retrieves JsoMap data identified by key.
+ *
+ * @param key Non-null key. E.g., "data/US/CA".
+ * @return String value for specified key.
+ */
+ public JsoMap getObj(String key) {
+ checkNotNull(key, "null key not allowed");
+ return cache.getObj(key);
+ }
+
+ private void notifyListenersAfterJobDone(String key) {
+ LookupKey lookupKey = new LookupKey.Builder(key).build();
+ HashSet<CacheListener> listeners = temporaryListenerStore.get(lookupKey);
+ if (listeners != null) {
+ for (CacheListener listener : listeners) {
+ listener.onAdd(key.toString());
+ }
+ listeners.clear();
+ }
+ }
+
+ private void addListenerToTempStore(LookupKey key, CacheListener listener) {
+ checkNotNull(key);
+ checkNotNull(listener);
+ HashSet<CacheListener> listeners = temporaryListenerStore.get(key);
+ if (listeners == null) {
+ listeners = new HashSet<CacheListener>();
+ temporaryListenerStore.put(key, listeners);
}
+ listeners.add(listener);
+ }
+
+ /**
+ * Added for testing purposes.
+ * Adds a new object into the cache.
+ * @param id string of the format "data/country/.." ie. "data/US/CA"
+ * @param object The JSONObject to be put into cache.
+ */
+ void addToJsoMap(String id, JSONObject object) {
+ cache.putObj(id, object);
+ }
+
+ /**
+ * Added for testing purposes.
+ * Checks to see if the cache is empty,
+ * @return true if the internal cache is empty
+ */
+ boolean isEmpty() {
+ return cache.length() == 0;
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/ClientCacheManager.java b/java/src/com/android/i18n/addressinput/ClientCacheManager.java
index 0ee1816..8c2c312 100644
--- a/java/src/com/android/i18n/addressinput/ClientCacheManager.java
+++ b/java/src/com/android/i18n/addressinput/ClientCacheManager.java
@@ -20,10 +20,10 @@ package com.android.i18n.addressinput;
* Used by AddressWidget to handle caching in client-specific ways.
*/
public interface ClientCacheManager {
- /** Get the data that is cached for the given key. */
- public String get(String key);
- /** Put the data for the given key into the cache. */
- public void put(String key, String data);
- /** Get the Url of the server that serves address metadata. */
- public String getAddressServerUrl();
+ /** Get the data that is cached for the given key. */
+ public String get(String key);
+ /** Put the data for the given key into the cache. */
+ public void put(String key, String data);
+ /** Get the Url of the server that serves address metadata. */
+ public String getAddressServerUrl();
}
diff --git a/java/src/com/android/i18n/addressinput/ClientData.java b/java/src/com/android/i18n/addressinput/ClientData.java
index 72be34f..8e23f3a 100644
--- a/java/src/com/android/i18n/addressinput/ClientData.java
+++ b/java/src/com/android/i18n/addressinput/ClientData.java
@@ -35,266 +35,264 @@ import java.util.Set;
*/
public class ClientData implements DataSource {
- private static final String TAG = "ClientData";
-
- /**
- * Data to bootstrap the process. The data are all regional (country level)
- * data. Keys are like "data/US/CA"
- */
- private final Map<String, JsoMap> mBootstrapMap = new HashMap<String, JsoMap>();
-
- private CacheData mCacheData;
-
- public ClientData(CacheData cacheData) {
- this.mCacheData = cacheData;
- buildRegionalData();
+ private static final String TAG = "ClientData";
+
+ /**
+ * Data to bootstrap the process. The data are all regional (country level)
+ * data. Keys are like "data/US/CA"
+ */
+ private final Map<String, JsoMap> bootstrapMap = new HashMap<String, JsoMap>();
+
+ private CacheData cacheData;
+
+ public ClientData(CacheData cacheData) {
+ this.cacheData = cacheData;
+ buildRegionalData();
+ }
+
+ @Override
+ public AddressVerificationNodeData get(String key) {
+ JsoMap jso = cacheData.getObj(key);
+ if (jso == null) { // Not cached.
+ fetchDataIfNotAvailable(key);
+ jso = cacheData.getObj(key);
}
-
- @Override
- public AddressVerificationNodeData get(String key) {
- JsoMap jso = mCacheData.getObj(key);
- if (jso == null) { // Not cached.
- fetchDataIfNotAvailable(key);
- jso = mCacheData.getObj(key);
- }
- if (jso != null && isValidDataKey(key)) {
- return createNodeData(jso);
- }
- return null;
+ if (jso != null && isValidDataKey(key)) {
+ return createNodeData(jso);
+ }
+ return null;
+ }
+
+ @Override
+ public AddressVerificationNodeData getDefaultData(String key) {
+ // root data
+ if (key.split("/").length == 1) {
+ JsoMap jso = bootstrapMap.get(key);
+ if (jso == null || !isValidDataKey(key)) {
+ throw new RuntimeException("key " + key + " does not have bootstrap data");
+ }
+ return createNodeData(jso);
}
- @Override
- public AddressVerificationNodeData getDefaultData(String key) {
- // root data
- if (key.split("/").length == 1) {
- JsoMap jso = mBootstrapMap.get(key);
- if (jso == null || !isValidDataKey(key)) {
- throw new RuntimeException("key " + key + " does not have bootstrap data");
- }
- return createNodeData(jso);
- }
+ key = getCountryKey(key);
+ JsoMap jso = bootstrapMap.get(key);
+ if (jso == null || !isValidDataKey(key)) {
+ throw new RuntimeException("key " + key + " does not have bootstrap data");
+ }
+ return createNodeData(jso);
+ }
- key = getCountryKey(key);
- JsoMap jso = mBootstrapMap.get(key);
- if (jso == null || !isValidDataKey(key)) {
- throw new RuntimeException("key " + key + " does not have bootstrap data");
- }
- return createNodeData(jso);
+ private String getCountryKey(String hierarchyKey) {
+ if (hierarchyKey.split("/").length <= 1) {
+ throw new RuntimeException("Cannot get country key with key '" + hierarchyKey + "'");
+ }
+ if (isCountryKey(hierarchyKey)) {
+ return hierarchyKey;
}
- private String getCountryKey(String hierarchyKey) {
- if (hierarchyKey.split("/").length <= 1) {
- throw new RuntimeException("Cannot get country key with key '" + hierarchyKey + "'");
- }
- if (isCountryKey(hierarchyKey)) {
- return hierarchyKey;
- }
+ String[] parts = hierarchyKey.split("/");
- String[] parts = hierarchyKey.split("/");
+ return new StringBuilder().append(parts[0])
+ .append("/")
+ .append(parts[1])
+ .toString();
+ }
- return new StringBuilder().append(parts[0])
- .append("/")
- .append(parts[1])
- .toString();
- }
+ private boolean isCountryKey(String hierarchyKey) {
+ Util.checkNotNull(hierarchyKey, "Cannot use null as a key");
+ return hierarchyKey.split("/").length == 2;
+ }
- private boolean isCountryKey(String hierarchyKey) {
- Util.checkNotNull(hierarchyKey, "Cannot use null as a key");
- return hierarchyKey.split("/").length == 2;
- }
+ /**
+ * Returns the contents of the JSON-format string as a map.
+ */
+ protected AddressVerificationNodeData createNodeData(JsoMap jso) {
+ Map<AddressDataKey, String> map =
+ new EnumMap<AddressDataKey, String>(AddressDataKey.class);
- /**
- * Returns the contents of the JSON-format string as a map.
- */
- protected AddressVerificationNodeData createNodeData(JsoMap jso) {
- Map<AddressDataKey, String> map =
- new EnumMap<AddressDataKey, String>(AddressDataKey.class);
-
- JSONArray arr = jso.getKeys();
- for (int i = 0; i < arr.length(); i++) {
- try {
- AddressDataKey key = AddressDataKey.get(arr.getString(i));
-
- if (key == null) {
- // Not all keys are supported by Android, so we continue if we encounter one
- // that is not used.
- continue;
- }
-
- String value = jso.get(key.toString().toLowerCase());
- map.put(key, value);
- } catch (JSONException e) {
- // This should not happen - we should not be fetching a key from outside the bounds
- // of the array.
- }
+ JSONArray arr = jso.getKeys();
+ for (int i = 0; i < arr.length(); i++) {
+ try {
+ AddressDataKey key = AddressDataKey.get(arr.getString(i));
+
+ if (key == null) {
+ // Not all keys are supported by Android, so we continue if we encounter one
+ // that is not used.
+ continue;
}
- return new AddressVerificationNodeData(map);
+ String value = jso.get(key.toString().toLowerCase());
+ map.put(key, value);
+ } catch (JSONException e) {
+ // This should not happen - we should not be fetching a key from outside the bounds
+ // of the array.
+ }
}
- /**
- * We can be initialized with the full set of address information, but validation only uses info
- * prefixed with "data" (in particular, no info prefixed with "examples").
- */
- private boolean isValidDataKey(String key) {
- return key.startsWith("data");
+ return new AddressVerificationNodeData(map);
+ }
+
+ /**
+ * We can be initialized with the full set of address information, but validation only uses info
+ * prefixed with "data" (in particular, no info prefixed with "examples").
+ */
+ private boolean isValidDataKey(String key) {
+ return key.startsWith("data");
+ }
+
+ /**
+ * Initializes regionalData structure based on property file.
+ */
+ private void buildRegionalData() {
+ StringBuilder countries = new StringBuilder();
+
+ for (String countryCode : RegionDataConstants.getCountryFormatMap().keySet()) {
+ countries.append(countryCode + "~");
+ String json = RegionDataConstants.getCountryFormatMap().get(countryCode);
+ JsoMap jso = null;
+ try {
+ jso = JsoMap.buildJsoMap(json);
+ } catch (JSONException e) {
+ // Ignore.
+ }
+
+ AddressData data = new AddressData.Builder().setCountry(countryCode).build();
+ LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(data).build();
+ bootstrapMap.put(key.toString(), jso);
}
+ countries.setLength(countries.length() - 1);
- /**
- * Initializes regionalData structure based on property file.
+ // TODO: this is messy. do we have better ways to do it?
+ /* Creates verification data for key="data". This will be used for the
+ * root FieldVerifier.
*/
- private void buildRegionalData() {
- StringBuilder countries = new StringBuilder();
-
- for (String countryCode : RegionDataConstants.getCountryFormatMap().keySet()) {
- countries.append(countryCode + "~");
- String json = RegionDataConstants.getCountryFormatMap().get(countryCode);
- JsoMap jso = null;
- try {
- jso = JsoMap.buildJsoMap(json);
- } catch (JSONException e) {
- // Ignore.
- }
-
- AddressData data = new AddressData.Builder().setCountry(countryCode).build();
- LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(data).build();
- mBootstrapMap.put(key.toString(), jso);
- }
- countries.setLength(countries.length() - 1);
-
- // TODO: this is messy. do we have better ways to do it?
- /* Creates verification data for key="data". This will be used for the
- * root FieldVerifier.
- */
- String str = "{\"id\":\"data\",\"" +
- AddressDataKey.COUNTRIES.toString().toLowerCase() +
- "\": \"" + countries.toString() + "\"}";
- JsoMap jsoData = null;
- try {
- jsoData = JsoMap.buildJsoMap(str);
- } catch (JSONException e) {
- // Ignore.
- }
- mBootstrapMap.put("data", jsoData);
+ String str = "{\"id\":\"data\",\"" +
+ AddressDataKey.COUNTRIES.toString().toLowerCase() +
+ "\": \"" + countries.toString() + "\"}";
+ JsoMap jsoData = null;
+ try {
+ jsoData = JsoMap.buildJsoMap(str);
+ } catch (JSONException e) {
+ // Ignore.
}
-
- /**
- * Fetches data from remote server if it is not cached yet.
- *
- * @param key The key for data that being requested. Key can be either a data key (starts with
- * "data") or example key (starts with "examples")
- */
- private void fetchDataIfNotAvailable(String key) {
- JsoMap jso = mCacheData.getObj(key);
- if (jso == null) {
- // If there is bootstrap data for the key, pass the data to fetchDynamicData
- JsoMap regionalData = mBootstrapMap.get(key);
- NotifyingListener listener = new NotifyingListener(this);
- // If the key was invalid, we don't want to attempt to fetch it.
- if (LookupKey.hasValidKeyPrefix(key)) {
- LookupKey lookupKey = new LookupKey.Builder(key).build();
- mCacheData.fetchDynamicData(lookupKey, regionalData, listener);
- try {
- listener.waitLoadingEnd();
- // Check to see if there is data for this key now.
- if (mCacheData.getObj(key) == null && isCountryKey(key)) {
- // If not, see if there is data in RegionDataConstants.
- Log.i(TAG, "Server failure: looking up key in region data constants.");
- mCacheData.getFromRegionDataConstants(lookupKey);
- }
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
+ bootstrapMap.put("data", jsoData);
+ }
+
+ /**
+ * Fetches data from remote server if it is not cached yet.
+ *
+ * @param key The key for data that being requested. Key can be either a data key (starts with
+ * "data") or example key (starts with "examples")
+ */
+ private void fetchDataIfNotAvailable(String key) {
+ JsoMap jso = cacheData.getObj(key);
+ if (jso == null) {
+ // If there is bootstrap data for the key, pass the data to fetchDynamicData
+ JsoMap regionalData = bootstrapMap.get(key);
+ NotifyingListener listener = new NotifyingListener(this);
+ // If the key was invalid, we don't want to attempt to fetch it.
+ if (LookupKey.hasValidKeyPrefix(key)) {
+ LookupKey lookupKey = new LookupKey.Builder(key).build();
+ cacheData.fetchDynamicData(lookupKey, regionalData, listener);
+ try {
+ listener.waitLoadingEnd();
+ // Check to see if there is data for this key now.
+ if (cacheData.getObj(key) == null && isCountryKey(key)) {
+ // If not, see if there is data in RegionDataConstants.
+ Log.i(TAG, "Server failure: looking up key in region data constants.");
+ cacheData.getFromRegionDataConstants(lookupKey);
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
}
+ }
}
-
- public void requestData(LookupKey key, DataLoadListener listener) {
- Util.checkNotNull(key, "Null lookup key not allowed");
- JsoMap regionalData = mBootstrapMap.get(key.toString());
- mCacheData.fetchDynamicData(key, regionalData, listener);
+ }
+
+ public void requestData(LookupKey key, DataLoadListener listener) {
+ Util.checkNotNull(key, "Null lookup key not allowed");
+ JsoMap regionalData = bootstrapMap.get(key.toString());
+ cacheData.fetchDynamicData(key, regionalData, listener);
+ }
+
+ /**
+ * Fetches all data for the specified country from the remote server.
+ */
+ public void prefetchCountry(String country, DataLoadListener listener) {
+ String key = "data/" + country;
+ Set<RecursiveLoader> loaders = new HashSet<RecursiveLoader>();
+ listener.dataLoadingBegin();
+ cacheData.fetchDynamicData(
+ new LookupKey.Builder(key).build(),
+ null,
+ new RecursiveLoader(key, loaders, listener));
+ }
+
+ /**
+ * A helper class to recursively load all sub keys using fetchDynamicData().
+ */
+ private class RecursiveLoader implements DataLoadListener {
+
+ private final String key;
+
+ private final Set<RecursiveLoader> loaders;
+
+ private final DataLoadListener listener;
+
+ public RecursiveLoader(String key, Set<RecursiveLoader> loaders,
+ DataLoadListener listener) {
+ this.key = key;
+ this.loaders = loaders;
+ this.listener = listener;
+
+ synchronized (loaders) {
+ loaders.add(this);
+ }
}
- /**
- * Fetches all data for the specified country from the remote server.
- */
- public void prefetchCountry(String country, DataLoadListener listener) {
- String key = "data/" + country;
- Set<RecursiveLoader> loaders = new HashSet<RecursiveLoader>();
- listener.dataLoadingBegin();
- mCacheData.fetchDynamicData(
- new LookupKey.Builder(key).build(),
- null,
- new RecursiveLoader(key, loaders, listener));
+ @Override
+ public void dataLoadingBegin() {
}
- /**
- * A helper class to recursively load all sub keys using fetchDynamicData().
- */
- private class RecursiveLoader implements DataLoadListener {
-
- private final String key;
+ @Override
+ public void dataLoadingEnd() {
+ final String subKeys = AddressDataKey.SUB_KEYS.name().toLowerCase();
+ final String subMores = AddressDataKey.SUB_MORES.name().toLowerCase();
- private final Set<RecursiveLoader> loaders;
+ JsoMap map = cacheData.getObj(key);
- private final DataLoadListener listener;
+ if (map.containsKey(subMores)) {
+ // This key could have sub keys.
+ String[] mores = map.get(subMores).split("~");
+ String[] keys = {};
- public RecursiveLoader(String key, Set<RecursiveLoader> loaders,
- DataLoadListener listener) {
- this.key = key;
- this.loaders = loaders;
- this.listener = listener;
+ if (map.containsKey(subKeys)) {
+ keys = map.get(subKeys).split("~");
+ }
- synchronized (loaders) {
- loaders.add(this);
- }
+ if (mores.length != keys.length) { // This should never happen.
+ throw new IndexOutOfBoundsException("mores.length != keys.length");
}
- @Override
- public void dataLoadingBegin() {
+ for (int i = 0; i < mores.length; i++) {
+ if (mores[i].equalsIgnoreCase("true")) {
+ // This key should have sub keys.
+ String subKey = key + "/" + keys[i];
+ cacheData.fetchDynamicData(
+ new LookupKey.Builder(subKey).build(),
+ null,
+ new RecursiveLoader(subKey, loaders, listener));
+ }
}
+ }
- @Override
- public void dataLoadingEnd() {
- final String subKeys = AddressDataKey.SUB_KEYS.name().toLowerCase();
- final String subMores = AddressDataKey.SUB_MORES.name().toLowerCase();
-
- JsoMap map = mCacheData.getObj(key);
-
- if (map.containsKey(subMores)) {
- // This key could have sub keys.
- String[] mores = {};
- String[] keys = {};
-
- mores = map.get(subMores).split("~");
-
- if (map.containsKey(subKeys)) {
- keys = map.get(subKeys).split("~");
- }
-
- if (mores.length != keys.length) { // This should never happen.
- throw new IndexOutOfBoundsException("mores.length != keys.length");
- }
-
- for (int i = 0; i < mores.length; i++) {
- if (mores[i].equalsIgnoreCase("true")) {
- // This key should have sub keys.
- String subKey = key + "/" + keys[i];
- mCacheData.fetchDynamicData(
- new LookupKey.Builder(subKey).build(),
- null,
- new RecursiveLoader(subKey, loaders, listener));
- }
- }
- }
-
- synchronized (loaders) {
- loaders.remove(this);
- if (loaders.isEmpty()) {
- listener.dataLoadingEnd();
- }
- }
+ synchronized (loaders) {
+ loaders.remove(this);
+ if (loaders.isEmpty()) {
+ listener.dataLoadingEnd();
}
+ }
}
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/DataLoadListener.java b/java/src/com/android/i18n/addressinput/DataLoadListener.java
index fc7782c..4e6fbee 100644
--- a/java/src/com/android/i18n/addressinput/DataLoadListener.java
+++ b/java/src/com/android/i18n/addressinput/DataLoadListener.java
@@ -20,7 +20,7 @@ package com.android.i18n.addressinput;
* Invoked when the data is fetched from the server or the cache.
*/
public interface DataLoadListener {
- // These callbacks are invoked from a background thread.
- void dataLoadingBegin();
- void dataLoadingEnd();
+ // These callbacks are invoked from a background thread.
+ void dataLoadingBegin();
+ void dataLoadingEnd();
}
diff --git a/java/src/com/android/i18n/addressinput/DataSource.java b/java/src/com/android/i18n/addressinput/DataSource.java
index d77f27f..605ae2a 100644
--- a/java/src/com/android/i18n/addressinput/DataSource.java
+++ b/java/src/com/android/i18n/addressinput/DataSource.java
@@ -20,6 +20,6 @@ package com.android.i18n.addressinput;
// removed when we have created code for static loading of data without using the
// AddressVerificationData class.
public interface DataSource {
- AddressVerificationNodeData getDefaultData(String key);
- AddressVerificationNodeData get(String key);
+ AddressVerificationNodeData getDefaultData(String key);
+ AddressVerificationNodeData get(String key);
}
diff --git a/java/src/com/android/i18n/addressinput/FieldVerifier.java b/java/src/com/android/i18n/addressinput/FieldVerifier.java
index bd9c5e5..9dee8de 100644
--- a/java/src/com/android/i18n/addressinput/FieldVerifier.java
+++ b/java/src/com/android/i18n/addressinput/FieldVerifier.java
@@ -20,6 +20,7 @@ import com.android.i18n.addressinput.LookupKey.ScriptType;
import java.util.EnumSet;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
@@ -31,328 +32,295 @@ import java.util.regex.Pattern;
* and only provides format and match verification for the postal code field.
*/
public class FieldVerifier {
- // Node data values are delimited by this symbol.
- private static final String DATA_DELIMITER = "~";
- // Keys are built up using this delimiter: eg data/US, data/US/CA.
- private static final String KEY_DELIMITER = "/";
+ // Node data values are delimited by this symbol.
+ private static final String DATA_DELIMITER = "~";
+ // Keys are built up using this delimiter: eg data/US, data/US/CA.
+ private static final String KEY_DELIMITER = "/";
- private String mId;
- private DataSource mDataSource;
+ private static final FormatInterpreter FORMAT_INTERPRETER =
+ new FormatInterpreter(new FormOptions.Builder().build());
- private Set<AddressField> mPossibleFields;
- private Set<AddressField> mRequired;
- // Known values. Can be either a key, a name in Latin, or a name in native script.
- private Map<String, String> mCandidateValues;
+ // Package-private so it can be accessed by tests.
+ String id;
+ private DataSource dataSource;
- // Keys for the subnodes of this verifier. For example, a key for the US would be CA, since
- // there is a sub-verifier with the ID "data/US/CA". Keys may be the local names of the
- // locations in the next level of the hierarchy, or the abbreviations if suitable abbreviations
- // exist.
- private String[] mKeys;
- // Names in Latin. These are only populated if the native/local names are in a script other than
- // latin.
- private String[] mLatinNames;
- // Names in native script.
- private String[] mLocalNames;
+ // Package-private so they can be accessed by tests.
+ Set<AddressField> possiblyUsedFields;
+ Set<AddressField> required;
+ // Known values. Can be either a key, a name in Latin, or a name in native script.
+ private Map<String, String> candidateValues;
- // Pattern representing the format of a postal code number.
- private Pattern mFormat;
- // Defines the valid range of a postal code number.
- private Pattern mMatch;
+ // Keys for the subnodes of this verifier. For example, a key for the US would be CA, since
+ // there is a sub-verifier with the ID "data/US/CA". Keys may be the local names of the
+ // locations in the next level of the hierarchy, or the abbreviations if suitable abbreviations
+ // exist. Package-private so it can be accessed by tests.
+ String[] keys;
+ // Names in Latin. These are only populated if the native/local names are in a script other than
+ // latin.
+ private String[] latinNames;
+ // Names in native script.
+ private String[] localNames;
- /**
- * Creates the root field verifier for a particular data source.
- */
- public FieldVerifier(DataSource dataSource) {
- mDataSource = dataSource;
- populateRootVerifier();
- }
+ // Pattern representing the format of a postal code number.
+ private Pattern format;
+ // Defines the valid range of a postal code number.
+ private Pattern match;
+
+ /**
+ * Creates the root field verifier for a particular data source.
+ */
+ public FieldVerifier(DataSource dataSource) {
+ this.dataSource = dataSource;
+ populateRootVerifier();
+ }
+
+ /**
+ * Creates a field verifier based on its parent and on the new data for this node supplied by
+ * nodeData (which may be null).
+ *
+ * Package-private so it can be accessed by tests.
+ */
+ FieldVerifier(FieldVerifier parent, AddressVerificationNodeData nodeData) {
+ // Most information is inherited from the parent.
+ possiblyUsedFields = parent.possiblyUsedFields;
+ required = parent.required;
+ dataSource = parent.dataSource;
+ format = parent.format;
+ match = parent.match;
+ // Here we add in any overrides from this particular node as well as information such as
+ // localNames, latinNames and keys.
+ populate(nodeData);
+ // candidateValues should never be inherited from the parent, but built up from the
+ // localNames in this node.
+ candidateValues = Util.buildNameToKeyMap(keys, localNames, latinNames);
+ }
- /**
- * Creates a field verifier based on its parent and on the new data for this node supplied by
- * nodeData (which may be null).
- */
- private FieldVerifier(FieldVerifier parent, AddressVerificationNodeData nodeData) {
- // Most information is inherited from the parent.
- mPossibleFields = parent.mPossibleFields;
- mRequired = parent.mRequired;
- mDataSource = parent.mDataSource;
- mFormat = parent.mFormat;
- mMatch = parent.mMatch;
- // Here we add in any overrides from this particular node as well as information such as
- // localNames, latinNames and keys.
- populate(nodeData);
- // candidateValues should never be inherited from the parent, but built up from the
- // localNames in this node.
- mCandidateValues = Util.buildNameToKeyMap(mKeys, mLocalNames, mLatinNames);
+ /**
+ * Sets possiblyUsedFields, required, keys and candidateValues for the root field verifier.
+ */
+ private void populateRootVerifier() {
+ id = "data";
+ // Keys come from the countries under "data".
+ AddressVerificationNodeData rootNode = dataSource.getDefaultData("data");
+ if (rootNode.containsKey(AddressDataKey.COUNTRIES)) {
+ keys = rootNode.get(AddressDataKey.COUNTRIES).split(DATA_DELIMITER);
}
+ // candidateValues is just the set of keys.
+ candidateValues = Util.buildNameToKeyMap(keys, null, null);
- /**
- * Sets possibleFieldsUsed, required, keys and candidateValues for the root field verifier. This
- * is a little messy at the moment since not all the appropriate information is actually under
- * the root "data" node in the metadata. For example, "possibleFields" and "required" are not
- * present there.
- */
- private void populateRootVerifier() {
- mId = "data";
- // Keys come from the countries under "data".
- AddressVerificationNodeData rootNode = mDataSource.getDefaultData("data");
- if (rootNode.containsKey(AddressDataKey.COUNTRIES)) {
- mKeys = rootNode.get(AddressDataKey.COUNTRIES).split(DATA_DELIMITER);
- }
- // candidateValues is just the set of keys.
- mCandidateValues = Util.buildNameToKeyMap(mKeys, null, null);
+ // TODO: Investigate if these need to be set here. The country level population already
+ // handles the fallback, the question is if validation can be done without a country level
+ // validator being created.
+ // Copy "possiblyUsedFields" and "required" from the defaults here for bootstrapping.
+ possiblyUsedFields = new HashSet<AddressField>();
+ required = new HashSet<AddressField>();
+ populatePossibleAndRequired("ZZ");
+ }
- // Copy "possibleFieldsUsed" and "required" from the defaults here for bootstrapping.
- // TODO: Investigate a cleaner way of doing this - maybe we should populate "data" with this
- // information instead.
- AddressVerificationNodeData defaultZZ = mDataSource.getDefaultData("data/ZZ");
- mPossibleFields = new HashSet<AddressField>();
- if (defaultZZ.containsKey(AddressDataKey.FMT)) {
- mPossibleFields = parseAddressFields(defaultZZ.get(AddressDataKey.FMT));
- }
- mRequired = new HashSet<AddressField>();
- if (defaultZZ.containsKey(AddressDataKey.REQUIRE)) {
- mRequired = parseRequireString(defaultZZ.get(AddressDataKey.REQUIRE));
- }
+ /**
+ * Populates this verifier with data from the node data passed in and from RegionDataConstants.
+ * The node data may be null.
+ */
+ private void populate(AddressVerificationNodeData nodeData) {
+ if (nodeData == null) {
+ return;
+ }
+ if (nodeData.containsKey(AddressDataKey.ID)) {
+ id = nodeData.get(AddressDataKey.ID);
+ }
+ if (nodeData.containsKey(AddressDataKey.SUB_KEYS)) {
+ keys = nodeData.get(AddressDataKey.SUB_KEYS).split(DATA_DELIMITER);
+ }
+ if (nodeData.containsKey(AddressDataKey.SUB_LNAMES)) {
+ latinNames = nodeData.get(AddressDataKey.SUB_LNAMES).split(DATA_DELIMITER);
+ }
+ if (nodeData.containsKey(AddressDataKey.SUB_NAMES)) {
+ localNames = nodeData.get(AddressDataKey.SUB_NAMES).split(DATA_DELIMITER);
+ }
+ if (nodeData.containsKey(AddressDataKey.XZIP)) {
+ format = Pattern.compile(nodeData.get(AddressDataKey.XZIP), Pattern.CASE_INSENSITIVE);
+ }
+ if (nodeData.containsKey(AddressDataKey.ZIP)) {
+ // This key has two different meanings, depending on whether this is a country-level key
+ // or not.
+ if (isCountryKey()) {
+ format = Pattern.compile(nodeData.get(AddressDataKey.ZIP),
+ Pattern.CASE_INSENSITIVE);
+ } else {
+ match = Pattern.compile(nodeData.get(AddressDataKey.ZIP),
+ Pattern.CASE_INSENSITIVE);
+ }
+ }
+ // If there are latin names but no local names, and there are the same number of latin names
+ // as there are keys, then we assume the local names are the same as the keys.
+ if (keys != null && localNames == null && latinNames != null &&
+ keys.length == latinNames.length) {
+ localNames = keys;
}
- /**
- * Populates this verifier with data from the node data passed in. This may be null.
- */
- private void populate(AddressVerificationNodeData nodeData) {
- if (nodeData == null) {
- return;
- }
- if (nodeData.containsKey(AddressDataKey.ID)) {
- mId = nodeData.get(AddressDataKey.ID);
- }
- if (nodeData.containsKey(AddressDataKey.SUB_KEYS)) {
- mKeys = nodeData.get(AddressDataKey.SUB_KEYS).split(DATA_DELIMITER);
- }
- if (nodeData.containsKey(AddressDataKey.SUB_LNAMES)) {
- mLatinNames = nodeData.get(AddressDataKey.SUB_LNAMES).split(DATA_DELIMITER);
- }
- if (nodeData.containsKey(AddressDataKey.SUB_NAMES)) {
- mLocalNames = nodeData.get(AddressDataKey.SUB_NAMES).split(DATA_DELIMITER);
- }
- if (nodeData.containsKey(AddressDataKey.FMT)) {
- mPossibleFields = parseAddressFields(nodeData.get(AddressDataKey.FMT));
- }
- if (nodeData.containsKey(AddressDataKey.REQUIRE)) {
- mRequired = parseRequireString(nodeData.get(AddressDataKey.REQUIRE));
- }
- if (nodeData.containsKey(AddressDataKey.XZIP)) {
- mFormat = Pattern.compile(nodeData.get(AddressDataKey.XZIP), Pattern.CASE_INSENSITIVE);
- }
- if (nodeData.containsKey(AddressDataKey.ZIP)) {
- // This key has two different meanings, depending on whether this is a country-level key
- // or not.
- if (isCountryKey()) {
- mFormat = Pattern.compile(nodeData.get(AddressDataKey.ZIP),
- Pattern.CASE_INSENSITIVE);
- } else {
- mMatch = Pattern.compile(nodeData.get(AddressDataKey.ZIP),
- Pattern.CASE_INSENSITIVE);
- }
- }
- // If there are latin names but no local names, and there are the same number of latin names
- // as there are keys, then we assume the local names are the same as the keys.
- if (mKeys != null && mLocalNames == null && mLatinNames != null &&
- mKeys.length == mLatinNames.length) {
- mLocalNames = mKeys;
- }
+ // These fields are populated from RegionDataConstants so that the metadata server can be
+ // updated without needing to be in sync with clients.
+ if (isCountryKey()) {
+ populatePossibleAndRequired(id.split(KEY_DELIMITER)[1]);
}
+ }
- FieldVerifier refineVerifier(String sublevel) {
- if (Util.trimToNull(sublevel) == null) {
- return new FieldVerifier(this, null);
- }
- // If the parent node didn't exist, then the subLevelName will start with "null".
- String subLevelName = mId + KEY_DELIMITER + sublevel;
- // For names with no Latin equivalent, we can look up the sublevel name directly.
- AddressVerificationNodeData nodeData = mDataSource.get(subLevelName);
+ private void populatePossibleAndRequired(String regionCode) {
+ List<AddressField> possible = FORMAT_INTERPRETER.getAddressFieldOrder(regionCode);
+ possiblyUsedFields = convertAddressFieldsToPossiblyUsedSet(possible);
+ required = FormatInterpreter.getRequiredFields(regionCode);
+ }
+
+ FieldVerifier refineVerifier(String sublevel) {
+ if (Util.trimToNull(sublevel) == null) {
+ return new FieldVerifier(this, null);
+ }
+ // If the parent node didn't exist, then the subLevelName will start with "null".
+ String subLevelName = id + KEY_DELIMITER + sublevel;
+ // For names with no Latin equivalent, we can look up the sublevel name directly.
+ AddressVerificationNodeData nodeData = dataSource.get(subLevelName);
+ if (nodeData != null) {
+ return new FieldVerifier(this, nodeData);
+ }
+ // If that failed, then we try to look up the local name equivalent of this latin name.
+ // First check these exist.
+ if (latinNames == null) {
+ return new FieldVerifier(this, null);
+ }
+ for (int n = 0; n < latinNames.length; n++) {
+ if (latinNames[n].equalsIgnoreCase(sublevel)) {
+ // We found a match - we should try looking up a key with the local name at the same
+ // index.
+ subLevelName = id + KEY_DELIMITER + localNames[n];
+ nodeData = dataSource.get(subLevelName);
if (nodeData != null) {
- return new FieldVerifier(this, nodeData);
+ return new FieldVerifier(this, nodeData);
}
- // If that failed, then we try to look up the local name equivalent of this latin name.
- // First check these exist.
- if (mLatinNames == null) {
- return new FieldVerifier(this, null);
- }
- for (int n = 0; n < mLatinNames.length; n++) {
- if (mLatinNames[n].equalsIgnoreCase(sublevel)) {
- // We found a match - we should try looking up a key with the local name at the same
- // index.
- subLevelName = mId + KEY_DELIMITER + mLocalNames[n];
- nodeData = mDataSource.get(subLevelName);
- if (nodeData != null) {
- return new FieldVerifier(this, nodeData);
- }
- }
- }
- // No sub-verifiers were found.
- return new FieldVerifier(this, null);
+ }
}
+ // No sub-verifiers were found.
+ return new FieldVerifier(this, null);
+ }
- /**
- * Returns the ID of this verifier.
- */
- @Override
- public String toString() {
- return mId;
- }
+ /**
+ * Returns the ID of this verifier.
+ */
+ @Override
+ public String toString() {
+ return id;
+ }
- /**
- * Checks a value in a particular script for a particular field to see if it causes the problem
- * specified. If so, this problem is added to the AddressProblems collection passed in. Returns
- * true if no problem was found.
- */
- protected boolean check(ScriptType script, AddressProblemType problem, AddressField field,
- String value, AddressProblems problems) {
- boolean problemFound = false;
+ /**
+ * Checks a value in a particular script for a particular field to see if it causes the problem
+ * specified. If so, this problem is added to the AddressProblems collection passed in. Returns
+ * true if no problem was found.
+ */
+ protected boolean check(ScriptType script, AddressProblemType problem, AddressField field,
+ String value, AddressProblems problems) {
+ boolean problemFound = false;
- String trimmedValue = Util.trimToNull(value);
- switch (problem) {
- case USING_UNUSED_FIELD:
- if (trimmedValue != null && !mPossibleFields.contains(field)) {
- problemFound = true;
- }
- break;
- case MISSING_REQUIRED_FIELD:
- if (mRequired.contains(field) && trimmedValue == null) {
- problemFound = true;
- }
- break;
- case UNKNOWN_VALUE:
- // An empty string will never be an UNKNOWN_VALUE. It is invalid
- // only when it appears in a required field (In that case it will
- // be reported as MISSING_REQUIRED_FIELD).
- if (trimmedValue == null) {
- break;
- }
- problemFound = !isKnownInScript(script, trimmedValue);
- break;
- case UNRECOGNIZED_FORMAT:
- if (trimmedValue != null && mFormat != null &&
- !mFormat.matcher(trimmedValue).matches()) {
- problemFound = true;
- }
- break;
- case MISMATCHING_VALUE:
- if (trimmedValue != null && mMatch != null &&
- !mMatch.matcher(trimmedValue).lookingAt()) {
- problemFound = true;
- }
- break;
- default:
- throw new RuntimeException("Unknown problem: " + problem);
+ String trimmedValue = Util.trimToNull(value);
+ switch (problem) {
+ case USING_UNUSED_FIELD:
+ if (trimmedValue != null && !possiblyUsedFields.contains(field)) {
+ problemFound = true;
}
- if (problemFound) {
- problems.add(field, problem);
- }
- return !problemFound;
- }
-
- /**
- * Checks the value of a particular field in a particular script against the known values for
- * this field. If script is null, it checks both the local and the latin values. Otherwise it
- * checks only the values in the script specified.
- */
- private boolean isKnownInScript(ScriptType script, String value) {
- String trimmedValue = Util.trimToNull(value);
- Util.checkNotNull(trimmedValue);
- if (script == null) {
- return (mCandidateValues == null ||
- mCandidateValues.containsKey(trimmedValue.toLowerCase()));
+ break;
+ case MISSING_REQUIRED_FIELD:
+ if (required.contains(field) && trimmedValue == null) {
+ problemFound = true;
}
- // Otherwise, if we know the script, we want to restrict the candidates to only names in
- // that script.
- String[] namesToConsider = (script == ScriptType.LATIN) ? mLatinNames : mLocalNames;
- Set<String> candidates = new HashSet<String>();
- if (namesToConsider != null) {
- for (String name : namesToConsider) {
- candidates.add(name.toLowerCase());
- }
+ break;
+ case UNKNOWN_VALUE:
+ // An empty string will never be an UNKNOWN_VALUE. It is invalid
+ // only when it appears in a required field (In that case it will
+ // be reported as MISSING_REQUIRED_FIELD).
+ if (trimmedValue == null) {
+ break;
}
- if (mKeys != null) {
- for (String name : mKeys) {
- candidates.add(name.toLowerCase());
- }
+ problemFound = !isKnownInScript(script, trimmedValue);
+ break;
+ case UNRECOGNIZED_FORMAT:
+ if (trimmedValue != null && format != null &&
+ !format.matcher(trimmedValue).matches()) {
+ problemFound = true;
}
-
- if (candidates.size() == 0 || trimmedValue == null) {
- return true;
+ break;
+ case MISMATCHING_VALUE:
+ if (trimmedValue != null && match != null &&
+ !match.matcher(trimmedValue).lookingAt()) {
+ problemFound = true;
}
-
- return candidates.contains(value.toLowerCase());
+ break;
+ default:
+ throw new RuntimeException("Unknown problem: " + problem);
}
+ if (problemFound) {
+ problems.add(field, problem);
+ }
+ return !problemFound;
+ }
- /**
- * Parses the value of the "fmt" key in the data to see which fields are used for a particular
- * country. Returns a list of all fields found. Country is always assumed to be present. Skips
- * characters that indicate new-lines in the format information, as well as any characters not
- * escaped with "%".
- */
- private static Set<AddressField> parseAddressFields(String value) {
- EnumSet<AddressField> result = EnumSet.of(AddressField.COUNTRY);
- boolean escaped = false;
- for (char c : value.toCharArray()) {
- if (escaped) {
- escaped = false;
- if (c == 'n') {
- continue;
- }
- AddressField f = AddressField.of(c);
- if (f == null) {
- throw new RuntimeException(
- "Unrecognized character '" + c + "' in format pattern: " + value);
- }
- result.add(f);
- } else if (c == '%') {
- escaped = true;
- }
- }
- // These fields are not mentioned in the metadata at the moment since there is an effort to
- // move away from STREET_ADDRESS and use these fields instead. This means they have to be
- // removed here.
- result.remove(AddressField.ADDRESS_LINE_1);
- result.remove(AddressField.ADDRESS_LINE_2);
-
- return result;
+ /**
+ * Checks the value of a particular field in a particular script against the known values for
+ * this field. If script is null, it checks both the local and the latin values. Otherwise it
+ * checks only the values in the script specified.
+ */
+ private boolean isKnownInScript(ScriptType script, String value) {
+ String trimmedValue = Util.trimToNull(value);
+ Util.checkNotNull(trimmedValue);
+ if (script == null) {
+ return (candidateValues == null ||
+ candidateValues.containsKey(trimmedValue.toLowerCase()));
+ }
+ // Otherwise, if we know the script, we want to restrict the candidates to only names in
+ // that script.
+ String[] namesToConsider = (script == ScriptType.LATIN) ? latinNames : localNames;
+ Set<String> candidates = new HashSet<String>();
+ if (namesToConsider != null) {
+ for (String name : namesToConsider) {
+ candidates.add(name.toLowerCase());
+ }
+ }
+ if (keys != null) {
+ for (String name : keys) {
+ candidates.add(name.toLowerCase());
+ }
}
- /**
- * Parses the value of the "required" key in the data. Adds country as well as any other field
- * mentioned in the string.
- */
- private static Set<AddressField> parseRequireString(String value) {
- // Country is always required
- EnumSet<AddressField> result = EnumSet.of(AddressField.COUNTRY);
+ if (candidates.size() == 0 || trimmedValue == null) {
+ return true;
+ }
- for (char c : value.toCharArray()) {
- AddressField f = AddressField.of(c);
- if (f == null) {
- throw new RuntimeException("Unrecognized character '" + c + "' in require pattern: "
- + value);
- }
- result.add(f);
- }
- // These fields are not mentioned in the metadata at the moment since there is an effort to
- // move away from STREET_ADDRESS and use these fields instead. This means they have to be
- // removed here.
- result.remove(AddressField.ADDRESS_LINE_1);
- result.remove(AddressField.ADDRESS_LINE_2);
+ return candidates.contains(value.toLowerCase());
+ }
- return result;
+ /**
+ * Converts a list of address fields to a set of possibly used fields. Adds country and handles
+ * street address.
+ */
+ private static Set<AddressField> convertAddressFieldsToPossiblyUsedSet(
+ List<AddressField> fields) {
+ // COUNTRY is never unexpected.
+ EnumSet<AddressField> result = EnumSet.of(AddressField.COUNTRY);
+ for (AddressField field : fields) {
+ // Replace ADDRESS_LINE with STREET_ADDRESS because that's what the validation expects.
+ if (field == AddressField.ADDRESS_LINE_1 ||
+ field == AddressField.ADDRESS_LINE_2) {
+ result.add(AddressField.STREET_ADDRESS);
+ } else {
+ result.add(field);
+ }
}
+ return result;
+ }
- /**
- * Returns true if this key represents a country. We assume all keys with only one delimiter are
- * at the country level (such as "data/US").
- */
- private boolean isCountryKey() {
- Util.checkNotNull(mId, "Cannot use null as key");
- return mId.split(KEY_DELIMITER).length == 2;
- }
+ /**
+ * Returns true if this key represents a country. We assume all keys with only one delimiter are
+ * at the country level (such as "data/US").
+ */
+ private boolean isCountryKey() {
+ Util.checkNotNull(id, "Cannot use null as key");
+ return id.split(KEY_DELIMITER).length == 2;
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/FormController.java b/java/src/com/android/i18n/addressinput/FormController.java
index c8c5953..63c69ab 100644
--- a/java/src/com/android/i18n/addressinput/FormController.java
+++ b/java/src/com/android/i18n/addressinput/FormController.java
@@ -29,306 +29,305 @@ import java.util.Queue;
* values for the next level down in the address hierarchy, if these are known.
*/
class FormController {
- // For address hierarchy in lookup key.
- private static final String SLASH_DELIM = "/";
- // For joined values.
- private static final String TILDE_DELIM = "~";
- // For language code info in lookup key (E.g., data/CA--fr).
- private static final String DASH_DELIM = "--";
- private static final LookupKey ROOT_KEY = FormController.getDataKeyForRoot();
- private static final String DEFAULT_REGION_CODE = "ZZ";
- private static final AddressField[] ADDRESS_HIERARCHY = {
- AddressField.COUNTRY,
- AddressField.ADMIN_AREA,
- AddressField.LOCALITY,
- AddressField.DEPENDENT_LOCALITY
- };
-
- // Current user language.
- private String mLanguageCode;
- private ClientData mIntegratedData;
- private String mCurrentCountry;
-
- /**
- * Constructor that populates this with data. languageCode should be a BCP language code (such
- * as "en" or "zh-Hant") and currentCountry should be an ISO 2-letter region code (such as "GB"
- * or "US").
- */
- FormController(ClientData integratedData, String languageCode, String currentCountry) {
- Util.checkNotNull(integratedData, "null data not allowed");
- mLanguageCode = languageCode;
- this.mCurrentCountry = currentCountry;
-
- AddressData address = new AddressData.Builder().setCountry(DEFAULT_REGION_CODE).build();
- LookupKey defaultCountryKey = getDataKeyFor(address);
-
- AddressVerificationNodeData defaultCountryData =
- integratedData.getDefaultData(defaultCountryKey.toString());
- Util.checkNotNull(defaultCountryData,
- "require data for default country key: " + defaultCountryKey);
- this.mIntegratedData = integratedData;
+ // For address hierarchy in lookup key.
+ private static final String SLASH_DELIM = "/";
+ // For joined values.
+ private static final String TILDE_DELIM = "~";
+ // For language code info in lookup key (E.g., data/CA--fr).
+ private static final String DASH_DELIM = "--";
+ private static final LookupKey ROOT_KEY = FormController.getDataKeyForRoot();
+ private static final String DEFAULT_REGION_CODE = "ZZ";
+ private static final AddressField[] ADDRESS_HIERARCHY = {
+ AddressField.COUNTRY,
+ AddressField.ADMIN_AREA,
+ AddressField.LOCALITY,
+ AddressField.DEPENDENT_LOCALITY
+ };
+
+ // Current user language.
+ private String languageCode;
+ private ClientData integratedData;
+ private String currentCountry;
+
+ /**
+ * Constructor that populates this with data. languageCode should be a BCP language code (such
+ * as "en" or "zh-Hant") and currentCountry should be an ISO 2-letter region code (such as "GB"
+ * or "US").
+ */
+ FormController(ClientData integratedData, String languageCode, String currentCountry) {
+ Util.checkNotNull(integratedData, "null data not allowed");
+ this.languageCode = languageCode;
+ this.currentCountry = currentCountry;
+
+ AddressData address = new AddressData.Builder().setCountry(DEFAULT_REGION_CODE).build();
+ LookupKey defaultCountryKey = getDataKeyFor(address);
+
+ AddressVerificationNodeData defaultCountryData =
+ integratedData.getDefaultData(defaultCountryKey.toString());
+ Util.checkNotNull(defaultCountryData,
+ "require data for default country key: " + defaultCountryKey);
+ this.integratedData = integratedData;
+ }
+
+ void setLanguageCode(String languageCode) {
+ this.languageCode = languageCode;
+ }
+
+ void setCurrentCountry(String currentCountry) {
+ this.currentCountry = currentCountry;
+ }
+
+ private ScriptType getScriptType() {
+ if (languageCode != null && Util.isExplicitLatinScript(languageCode)) {
+ return ScriptType.LATIN;
}
-
- void setLanguageCode(String languageCode) {
- mLanguageCode = languageCode;
- }
-
- void setCurrentCountry(String currentCountry) {
- mCurrentCountry = currentCountry;
+ return ScriptType.LOCAL;
+ }
+
+ private static LookupKey getDataKeyForRoot() {
+ AddressData address = new AddressData.Builder().build();
+ return new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
+ }
+
+ LookupKey getDataKeyFor(AddressData address) {
+ return new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
+ }
+
+ /**
+ * Requests data for the input address. This method chains multiple requests together. For
+ * example, an address for Mt View, California needs data from "data/US", "data/US/CA", and
+ * "data/US/CA/Mt View" to support it. This method will request them one by one (from top level
+ * key down to the most granular) and evokes {@link DataLoadListener#dataLoadingEnd} method when
+ * all data is collected. If the address is invalid, it will request the first valid child key
+ * instead. For example, a request for "data/US/Foo" will end up requesting data for "data/US",
+ * "data/US/AL".
+ *
+ * @param address the current address.
+ * @param listener triggered when requested data for the address is returned.
+ */
+ void requestDataForAddress(AddressData address, DataLoadListener listener) {
+ Util.checkNotNull(address.getPostalCountry(), "null country not allowed");
+
+ // Gets the key for deepest available node.
+ Queue<String> subkeys = new LinkedList<String>();
+
+ for (AddressField field : ADDRESS_HIERARCHY) {
+ String value = address.getFieldValue(field);
+ if (value == null) {
+ break;
+ }
+ subkeys.add(value);
}
-
- private ScriptType getScriptType() {
- if (mLanguageCode != null && Util.isExplicitLatinScript(mLanguageCode)) {
- return ScriptType.LATIN;
- }
- return ScriptType.LOCAL;
+ if (subkeys.size() == 0) {
+ throw new RuntimeException("Need at least country level info");
}
- private static LookupKey getDataKeyForRoot() {
- AddressData address = new AddressData.Builder().build();
- return new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
+ if (listener != null) {
+ listener.dataLoadingBegin();
}
-
- LookupKey getDataKeyFor(AddressData address) {
- return new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
- }
-
- /**
- * Requests data for the input address. This method chains multiple requests together. For
- * example, an address for Mt View, California needs data from "data/US", "data/US/CA", and
- * "data/US/CA/Mt View" to support it. This method will request them one by one (from top level
- * key down to the most granular) and evokes {@link DataLoadListener#dataLoadingEnd} method when
- * all data is collected. If the address is invalid, it will request the first valid child key
- * instead. For example, a request for "data/US/Foo" will end up requesting data for "data/US",
- * "data/US/AL".
- *
- * @param address the current address.
- * @param listener triggered when requested data for the address is returned.
- */
- void requestDataForAddress(AddressData address, DataLoadListener listener) {
- Util.checkNotNull(address.getPostalCountry(), "null country not allowed");
-
- // Gets the key for deepest available node.
- Queue<String> subkeys = new LinkedList<String>();
-
- for (AddressField field : ADDRESS_HIERARCHY) {
- String value = address.getFieldValue(field);
- if (value == null) {
- break;
+ requestDataRecursively(ROOT_KEY, subkeys, listener);
+ }
+
+ private void requestDataRecursively(final LookupKey key,
+ final Queue<String> subkeys, final DataLoadListener listener) {
+ Util.checkNotNull(key, "Null key not allowed");
+ Util.checkNotNull(subkeys, "Null subkeys not allowed");
+
+ integratedData.requestData(key, new DataLoadListener() {
+ @Override
+ public void dataLoadingBegin() {
+ }
+
+ @Override
+ public void dataLoadingEnd() {
+ List<RegionData> subregions = getRegionData(key);
+ if (subregions.isEmpty()) {
+ if (listener != null) {
+ listener.dataLoadingEnd();
+ }
+ // TODO: Should update the selectors here.
+ return;
+ } else if (subkeys.size() > 0) {
+ String subkey = subkeys.remove();
+ for (RegionData subregion : subregions) {
+ if (subregion.isValidName(subkey)) {
+ LookupKey nextKey = buildDataLookupKey(key, subregion.getKey());
+ requestDataRecursively(nextKey, subkeys, listener);
+ return;
}
- subkeys.add(value);
- }
- if (subkeys.size() == 0) {
- throw new RuntimeException("Need at least country level info");
+ }
}
- if (listener != null) {
- listener.dataLoadingBegin();
- }
- requestDataRecursively(ROOT_KEY, subkeys, listener);
+ // Current value in the field is not valid, use the first valid subkey
+ // to request more data instead.
+ String firstSubkey = subregions.get(0).getKey();
+ LookupKey nextKey = buildDataLookupKey(key, firstSubkey);
+ Queue<String> emptyList = new LinkedList<String>();
+ requestDataRecursively(nextKey, emptyList, listener);
+ }
+ });
+ }
+
+ private LookupKey buildDataLookupKey(LookupKey lookupKey, String subKey) {
+ String[] subKeys = lookupKey.toString().split(SLASH_DELIM);
+ String languageCodeSubTag =
+ (languageCode == null) ? null : Util.getLanguageSubtag(languageCode);
+ String key = lookupKey.toString() + SLASH_DELIM + subKey;
+
+ // Country level key
+ if (subKeys.length == 1 &&
+ languageCodeSubTag != null && !isDefaultLanguage(languageCodeSubTag)) {
+ key += DASH_DELIM + languageCodeSubTag.toString();
}
-
- private void requestDataRecursively(final LookupKey key,
- final Queue<String> subkeys, final DataLoadListener listener) {
- Util.checkNotNull(key, "Null key not allowed");
- Util.checkNotNull(subkeys, "Null subkeys not allowed");
-
- mIntegratedData.requestData(key, new DataLoadListener() {
- @Override
- public void dataLoadingBegin() {
- }
-
- @Override
- public void dataLoadingEnd() {
- List<RegionData> subregions = getRegionData(key);
- if (subregions.isEmpty()) {
- if (listener != null) {
- listener.dataLoadingEnd();
- }
- // TODO: Should update the selectors here.
- return;
- } else if (subkeys.size() > 0) {
- String subkey = subkeys.remove();
- for (RegionData subregion : subregions) {
- if (subregion.isValidName(subkey)) {
- LookupKey nextKey = buildDataLookupKey(key, subregion.getKey());
- requestDataRecursively(nextKey, subkeys, listener);
- return;
- }
- }
- }
-
- // Current value in the field is not valid, use the first valid subkey
- // to request more data instead.
- String firstSubkey = subregions.get(0).getKey();
- LookupKey nextKey = buildDataLookupKey(key, firstSubkey);
- Queue<String> emptyList = new LinkedList<String>();
- requestDataRecursively(nextKey, emptyList, listener);
- }
- });
+ return new LookupKey.Builder(key).build();
+ }
+
+ /**
+ * Compares the language subtags of input {@code languageCode} and default language code. For
+ * example, "zh-Hant" and "zh" are viewed as identical.
+ */
+ boolean isDefaultLanguage(String languageCode) {
+ if (languageCode == null) {
+ return true;
}
-
- private LookupKey buildDataLookupKey(LookupKey lookupKey, String subKey) {
- String[] subKeys = lookupKey.toString().split(SLASH_DELIM);
- String languageCodeSubTag =
- (mLanguageCode == null) ? null : Util.getLanguageSubtag(mLanguageCode);
- String key = lookupKey.toString() + SLASH_DELIM + subKey;
-
- // Country level key
- if (subKeys.length == 1 &&
- languageCodeSubTag != null && !isDefaultLanguage(languageCodeSubTag)) {
- key += DASH_DELIM + languageCodeSubTag.toString();
- }
- return new LookupKey.Builder(key).build();
+ AddressData addr = new AddressData.Builder().setCountry(currentCountry).build();
+ LookupKey lookupKey = getDataKeyFor(addr);
+ AddressVerificationNodeData data =
+ integratedData.getDefaultData(lookupKey.toString());
+ String defaultLanguage = data.get(AddressDataKey.LANG);
+
+ // Current language is not the default language for the country.
+ if (Util.trimToNull(defaultLanguage) != null &&
+ !Util.getLanguageSubtag(languageCode).equals(Util.getLanguageSubtag(languageCode))) {
+ return false;
}
-
- /**
- * Compares the language subtags of input {@code languageCode} and default language code. For
- * example, "zh-Hant" and "zh" are viewed as identical.
- */
- boolean isDefaultLanguage(String languageCode) {
- if (languageCode == null) {
- return true;
- }
- AddressData addr = new AddressData.Builder().setCountry(mCurrentCountry).build();
- LookupKey lookupKey = getDataKeyFor(addr);
- AddressVerificationNodeData data =
- mIntegratedData.getDefaultData(lookupKey.toString());
- String defaultLanguage = data.get(AddressDataKey.LANG);
-
- // Current language is not the default language for the country.
- if (Util.trimToNull(defaultLanguage) != null &&
- !Util.getLanguageSubtag(languageCode).equals(Util.getLanguageSubtag(languageCode))) {
- return false;
- }
- return true;
+ return true;
+ }
+
+ /**
+ * Gets a list of {@link RegionData} for sub-regions for a given key. For example, sub regions
+ * for "data/US" are AL/Alabama, AK/Alaska, etc.
+ *
+ * <p> TODO: It seems more straight forward to return a list of pairs instead of RegionData.
+ * Actually, we can remove RegionData since it does not contain anything more than key/value
+ * pairs now.
+ *
+ * @return A list of sub-regions, each sub-region represented by a {@link RegionData}.
+ */
+ List<RegionData> getRegionData(LookupKey key) {
+ if (key.getKeyType() == KeyType.EXAMPLES) {
+ throw new RuntimeException("example key not allowed for getting region data");
}
-
- /**
- * Gets a list of {@link RegionData} for sub-regions for a given key. For example, sub regions
- * for "data/US" are AL/Alabama, AK/Alaska, etc.
- *
- * <p> TODO: It seems more straight forward to return a list of pairs instead of RegionData.
- * Actually, we can remove RegionData since it does not contain anything more than key/value
- * pairs now.
- *
- * @return A list of sub-regions, each sub-region represented by a {@link RegionData}.
- */
- List<RegionData> getRegionData(LookupKey key) {
- if (key.getKeyType() == KeyType.EXAMPLES) {
- throw new RuntimeException("example key not allowed for getting region data");
- }
- Util.checkNotNull(key, "null regionKey not allowed");
- LookupKey normalizedKey = normalizeLookupKey(key);
- List<RegionData> results = new ArrayList<RegionData>();
-
- // Root key.
- if (normalizedKey.equals(ROOT_KEY)) {
- AddressVerificationNodeData data =
- mIntegratedData.getDefaultData(normalizedKey.toString());
- String[] countries = splitData(data.get(AddressDataKey.COUNTRIES));
- for (int i = 0; i < countries.length; i++) {
- RegionData rd = new RegionData.Builder()
- .setKey(countries[i])
- .setName(countries[i])
- .build();
- results.add(rd);
- }
- return results;
- }
-
- AddressVerificationNodeData data =
- mIntegratedData.get(normalizedKey.toString());
- if (data != null) {
- String[] keys = splitData(data.get(AddressDataKey.SUB_KEYS));
- String[] names = (getScriptType() == ScriptType.LOCAL)
- ? splitData(data.get(AddressDataKey.SUB_NAMES))
- : splitData(data.get(AddressDataKey.SUB_LNAMES));
-
- for (int i = 0; i < keys.length; i++) {
- RegionData rd =
- new RegionData.Builder()
- .setKey(keys[i])
- .setName((i < names.length) ? names[i] : keys[i])
- .build();
- results.add(rd);
- }
- }
- return results;
+ Util.checkNotNull(key, "null regionKey not allowed");
+ LookupKey normalizedKey = normalizeLookupKey(key);
+ List<RegionData> results = new ArrayList<RegionData>();
+
+ // Root key.
+ if (normalizedKey.equals(ROOT_KEY)) {
+ AddressVerificationNodeData data =
+ integratedData.getDefaultData(normalizedKey.toString());
+ String[] countries = splitData(data.get(AddressDataKey.COUNTRIES));
+ for (int i = 0; i < countries.length; i++) {
+ RegionData rd = new RegionData.Builder()
+ .setKey(countries[i])
+ .setName(countries[i])
+ .build();
+ results.add(rd);
+ }
+ return results;
}
- /**
- * Split a '~' delimited string into an array of strings. This method is null tolerant and
- * considers an empty string to contain no elements.
- *
- * @param raw The data to split
- * @return an array of strings
- */
- private String[] splitData(String raw) {
- if (raw == null || raw.length() == 0) {
- return new String[]{};
- }
- return raw.split(TILDE_DELIM);
+ AddressVerificationNodeData data =
+ integratedData.get(normalizedKey.toString());
+ if (data != null) {
+ String[] keys = splitData(data.get(AddressDataKey.SUB_KEYS));
+ String[] names = (getScriptType() == ScriptType.LOCAL)
+ ? splitData(data.get(AddressDataKey.SUB_NAMES))
+ : splitData(data.get(AddressDataKey.SUB_LNAMES));
+
+ for (int i = 0; i < keys.length; i++) {
+ RegionData rd = new RegionData.Builder()
+ .setKey(keys[i])
+ .setName((i < names.length) ? names[i] : keys[i])
+ .build();
+ results.add(rd);
+ }
}
-
- private String getSubKey(LookupKey parentKey, String name) {
- for (RegionData subRegion : getRegionData(parentKey)) {
- if (subRegion.isValidName(name)) {
- return subRegion.getKey();
- }
- }
- return null;
+ return results;
+ }
+
+ /**
+ * Split a '~' delimited string into an array of strings. This method is null tolerant and
+ * considers an empty string to contain no elements.
+ *
+ * @param raw The data to split
+ * @return an array of strings
+ */
+ private String[] splitData(String raw) {
+ if (raw == null || raw.length() == 0) {
+ return new String[]{};
+ }
+ return raw.split(TILDE_DELIM);
+ }
+
+ private String getSubKey(LookupKey parentKey, String name) {
+ for (RegionData subRegion : getRegionData(parentKey)) {
+ if (subRegion.isValidName(name)) {
+ return subRegion.getKey();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Normalizes {@code key} by replacing field values with sub-keys. For example, California is
+ * replaced with CA. The normalization goes from top (country) to bottom (dependent locality)
+ * and if any field value is empty, unknown, or invalid, it will stop and return whatever it
+ * gets. For example, a key "data/US/California/foobar/kar" will be normalized into
+ * "data/US/CA/foobar/kar" since "foobar" is unknown. This method supports only key of
+ * {@link KeyType#DATA} type.
+ *
+ * @return normalized {@link LookupKey}.
+ */
+ private LookupKey normalizeLookupKey(LookupKey key) {
+ Util.checkNotNull(key);
+ if (key.getKeyType() != KeyType.DATA) {
+ throw new RuntimeException("Only DATA keyType is supported");
}
- /**
- * Normalizes {@code key} by replacing field values with sub-keys. For example, California is
- * replaced with CA. The normalization goes from top (country) to bottom (dependent locality)
- * and if any field value is empty, unknown, or invalid, it will stop and return whatever it
- * gets. For example, a key "data/US/California/foobar/kar" will be normalized into
- * "data/US/CA/foobar/kar" since "foobar" is unknown. This method supports only key of
- * {@link KeyType#DATA} type.
- *
- * @return normalized {@link LookupKey}.
- */
- private LookupKey normalizeLookupKey(LookupKey key) {
- Util.checkNotNull(key);
- if (key.getKeyType() != KeyType.DATA) {
- throw new RuntimeException("Only DATA keyType is supported");
- }
-
- String subStr[] = key.toString().split(SLASH_DELIM);
-
- // Root key does not need to be normalized.
- if (subStr.length < 2) {
- return key;
- }
-
- StringBuilder sb = new StringBuilder(subStr[0]);
- for (int i = 1; i < subStr.length; ++i) {
- // Strips the language code if contained.
- String languageCode = null;
- if (i == 1 && subStr[i].contains(DASH_DELIM)) {
- String[] s = subStr[i].split(DASH_DELIM);
- subStr[i] = s[0];
- languageCode = s[1];
- }
+ String subStr[] = key.toString().split(SLASH_DELIM);
- String normalizedSubKey = getSubKey(new LookupKey.Builder(sb.toString()).build(),
- subStr[i]);
+ // Root key does not need to be normalized.
+ if (subStr.length < 2) {
+ return key;
+ }
- // Can't find normalized sub-key; assembles the lookup key with the
- // remaining sub-keys and returns it.
- if (normalizedSubKey == null) {
- for (; i < subStr.length; ++i) {
- sb.append(SLASH_DELIM).append(subStr[i]);
- }
- break;
- }
- sb.append(SLASH_DELIM).append(normalizedSubKey);
- if (languageCode != null) {
- sb.append(DASH_DELIM).append(languageCode);
- }
+ StringBuilder sb = new StringBuilder(subStr[0]);
+ for (int i = 1; i < subStr.length; ++i) {
+ // Strips the language code if contained.
+ String languageCode = null;
+ if (i == 1 && subStr[i].contains(DASH_DELIM)) {
+ String[] s = subStr[i].split(DASH_DELIM);
+ subStr[i] = s[0];
+ languageCode = s[1];
+ }
+
+ String normalizedSubKey = getSubKey(new LookupKey.Builder(sb.toString()).build(),
+ subStr[i]);
+
+ // Can't find normalized sub-key; assembles the lookup key with the
+ // remaining sub-keys and returns it.
+ if (normalizedSubKey == null) {
+ for (; i < subStr.length; ++i) {
+ sb.append(SLASH_DELIM).append(subStr[i]);
}
- return new LookupKey.Builder(sb.toString()).build();
+ break;
+ }
+ sb.append(SLASH_DELIM).append(normalizedSubKey);
+ if (languageCode != null) {
+ sb.append(DASH_DELIM).append(languageCode);
+ }
}
+ return new LookupKey.Builder(sb.toString()).build();
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/FormOptions.java b/java/src/com/android/i18n/addressinput/FormOptions.java
index 07bc38e..ffa8c10 100644
--- a/java/src/com/android/i18n/addressinput/FormOptions.java
+++ b/java/src/com/android/i18n/addressinput/FormOptions.java
@@ -31,257 +31,257 @@ import java.util.Map;
*/
public class FormOptions {
- private final String mBaseId;
+ private final String baseId;
+
+ private final EnumSet<AddressField> hiddenFields;
+
+ private final EnumSet<AddressField> readonlyFields;
+
+ private final EnumSet<AddressField> requiredFields;
+
+ private final EnumMap<AddressField, String> customLabels =
+ new EnumMap<AddressField, String>(AddressField.class);
+
+ private final Map<String, AddressField[]> overrideFieldOrder =
+ new HashMap<String, AddressField[]>();
+
+ private final EnumMap<AddressField, Integer> maxLengths =
+ new EnumMap<AddressField, Integer>(AddressField.class);
+
+ private final String serverUrl;
+
+ private FormOptions(Builder builder) {
+ // copy values from builder
+ baseId = builder.baseId;
+ hiddenFields = EnumSet.copyOf(builder.hiddenFields);
+ readonlyFields = EnumSet.copyOf(builder.readonlyFields);
+ requiredFields = EnumSet.copyOf(builder.requiredFields);
+ customLabels.putAll(builder.customLabels);
+ overrideFieldOrder.putAll(builder.overrideFieldOrder);
+ maxLengths.putAll(builder.maxLengths);
+ serverUrl = builder.serverUrl;
+ }
+
+ /**
+ * Gets base ID of the address form. Default is "addressform".
+ */
+ String getBaseId() {
+ return baseId;
+ }
+
+ boolean isHidden(AddressField field) {
+ return hiddenFields.contains(field);
+ }
+
+ boolean isReadonly(AddressField field) {
+ return readonlyFields.contains(field);
+ }
+
+ boolean isRequired(AddressField field) {
+ return requiredFields.contains(field);
+ }
+
+ EnumSet<AddressField> getRequiredFields() {
+ return requiredFields;
+ }
+
+ /**
+ * Gets the customized label for the {@code field}, or returns null if none.
+ */
+ String getCustomLabel(AddressField field) {
+ return customLabels.get(field);
+ }
+
+ /**
+ * Gets the URL of the Address Data Server.
+ */
+ String getUrl() {
+ return serverUrl;
+ }
+
+ /**
+ * Gets the overridden field orders with their corresponding region code. Returns null if field
+ * orders for {@code regionCode} is not specified.
+ */
+ AddressField[] getCustomFieldOrder(String regionCode) {
+ if (regionCode == null) {
+ throw new RuntimeException("regionCode cannot be null.");
+ }
+ return overrideFieldOrder.get(regionCode);
+ }
- private final EnumSet<AddressField> mHiddenFields;
+ /**
+ * Gets the customized max length for the {@code field}, or null if none.
+ */
+ Integer getCustomMaxLength(AddressField field) {
+ return maxLengths.get(field);
+ }
- private final EnumSet<AddressField> mReadonlyFields;
+ /**
+ * Class to build the form, specifying the attributes for each field.
+ */
+ public static class Builder {
- private final EnumSet<AddressField> mRequiredFields;
+ private String baseId = "addressform";
- private final EnumMap<AddressField, String> mCustomLabels =
- new EnumMap<AddressField, String>(AddressField.class);
+ private final EnumSet<AddressField> requiredFields =
+ EnumSet.noneOf(AddressField.class);
- private final Map<String, AddressField[]> mOverrideFieldOrder =
- new HashMap<String, AddressField[]>();
+ private final EnumSet<AddressField> hiddenFields =
+ EnumSet.noneOf(AddressField.class);
- private final EnumMap<AddressField, Integer> mMaxLengths =
- new EnumMap<AddressField, Integer>(AddressField.class);
+ private final EnumSet<AddressField> readonlyFields =
+ EnumSet.noneOf(AddressField.class);
- private final String mServerUrl;
+ private final EnumMap<AddressField, String> customLabels =
+ new EnumMap<AddressField, String>(AddressField.class);
- private FormOptions(Builder builder) {
- // copy values from builder
- mBaseId = builder.mBaseId;
- mHiddenFields = EnumSet.copyOf(builder.mHiddenFields);
- mReadonlyFields = EnumSet.copyOf(builder.mReadonlyFields);
- mRequiredFields = EnumSet.copyOf(builder.mRequiredFields);
- mCustomLabels.putAll(builder.mCustomLabels);
- mOverrideFieldOrder.putAll(builder.mOverrideFieldOrder);
- mMaxLengths.putAll(builder.mMaxLengths);
- mServerUrl = builder.mServerUrl;
- }
+ private final Map<String, AddressField[]> overrideFieldOrder =
+ new HashMap<String, AddressField[]>();
+
+ private final EnumMap<AddressField, Integer> maxLengths =
+ new EnumMap<AddressField, Integer>(AddressField.class);
/**
- * Gets base ID of the address form. Default is "addressform".
+ * Uses the default server URL from CacheData.
*/
- String getBaseId() {
- return mBaseId;
- }
+ private String serverUrl = new CacheData().getUrl();
- boolean isHidden(AddressField field) {
- return mHiddenFields.contains(field);
- }
-
- boolean isReadonly(AddressField field) {
- return mReadonlyFields.contains(field);
+ /**
+ * Sets the base ID of the address form.
+ */
+ public Builder baseId(String baseId) {
+ if (baseId == null) {
+ throw new RuntimeException("baseId cannot be null.");
+ }
+ this.baseId = baseId;
+ return this;
}
- boolean isRequired(AddressField field) {
- return mRequiredFields.contains(field);
+ public Builder hide(AddressField field) {
+ if (field == null) {
+ throw new RuntimeException("AddressField field cannot be null.");
+ }
+ hiddenFields.add(field);
+ return this;
}
- EnumSet<AddressField> getRequiredFields() {
- return mRequiredFields;
+ /**
+ * Make a field read-only.
+ */
+ public Builder readonly(AddressField field) {
+ if (field == null) {
+ throw new RuntimeException("AddressField field cannot be null.");
+ }
+ readonlyFields.add(field);
+ return this;
}
/**
- * Gets the customized label for the {@code field}, or returns null if none.
+ * Make a field required.
*/
- String getCustomLabel(AddressField field) {
- return mCustomLabels.get(field);
+ public Builder required(AddressField field) {
+ if (field == null) {
+ throw new RuntimeException("AddressField field cannot be null.");
+ }
+ requiredFields.add(field);
+ return this;
}
/**
- * Gets the URL of the Address Data Server.
+ * Customizes label for an {@code AddressField}.
*/
- String getUrl() {
- return mServerUrl;
+ public Builder customizeLabel(AddressField field, String label) {
+ if (field == null) {
+ throw new RuntimeException("AddressField field cannot be null.");
+ }
+ if (label == null) {
+ throw new RuntimeException("Label cannot be null.");
+ }
+ customLabels.put(field, label);
+ return this;
}
/**
- * Gets the overridden field orders with their corresponding region code. Returns null if field
- * orders for {@code regionCode} is not specified.
+ * Sets the field order for a region code. The order you set here will override the
+ * predefined one. For example, you can set field order for US to be first {@code
+ * AddressField#ORGANIZATION} then {@code AddressField#RECIPIENT}. Repeated address fields
+ * in {@code fields} are not allowed. Size of {@code fields} has to be larger than one.
+ * Input {@code fields} can be partial or even contain field not needed in the specified
+ * {@code regionCode}. For example, German addresses contain the following fields
+ * (in order):<br/>
+ {@link AddressField#RECIPIENT}, {@link AddressField#ORGANIZATION}, {@link
+ * AddressField#STREET_ADDRESS}, {@link AddressField#POSTAL_CODE}, {@link
+ * AddressField#LOCALITY}. <br/>
+ *
+ * <p>With the following call: <br/>
+ *
+ * customizeFieldOrder("DE", AddressField.ORGANIZATION, AddressField.RECIPIENT,
+ * AddressField.ADMIN_AREA);
+ *
+ * <p>Field order for Germany will become: <br/> {@link AddressField#ORGANIZATION}, {@link
+ * AddressField#RECIPIENT}, {@link AddressField#STREET_ADDRESS}, {@link
+ * AddressField#POSTAL_CODE}, {@link AddressField#LOCALITY}. </p>
+ *
+ * <p>Notice that:<br/> <ol> <li>{@link AddressField#ORGANIZATION} comes before {@link
+ * AddressField#RECIPIENT} after reordering.</li>
+ * <li>Fields not specified stays the same.</li>
+ * <li>{@link AddressField#ADMIN_AREA} is specified but since it is not in German address
+ * format, it is simpled neglected.</li> </ol>
+ *
+ * @param fields the overridden field order.
*/
- AddressField[] getCustomFieldOrder(String regionCode) {
- if (regionCode == null) {
- throw new RuntimeException("regionCode cannot be null.");
+ public Builder customizeFieldOrder(String regionCode, AddressField... fields) {
+ if (regionCode == null) {
+ throw new RuntimeException("regionCode cannot be null.");
+ }
+ if (fields == null) {
+ throw new RuntimeException("Fields cannot be null.");
+ }
+ if (fields.length <= 1) {
+ throw new RuntimeException("There must be more than one field.");
+ }
+ HashSet<AddressField> checkList = new HashSet<AddressField>();
+ AddressField[] f = new AddressField[fields.length];
+ int i = 0;
+ for (AddressField field : fields) {
+ // Can't contain repeated address fields.
+ if (checkList.contains(field)) {
+ throw new RuntimeException("Address fields cannot be repeated.");
}
- return mOverrideFieldOrder.get(regionCode);
+ checkList.add(field);
+ f[i] = field;
+ i++;
+ }
+ overrideFieldOrder.put(regionCode, f);
+ return this;
}
/**
- * Gets the customized max length for the {@code field}, or null if none.
+ * Sets the URL of address data server. {@code url} cannot be null. This url will override
+ * the default address server url.
*/
- Integer getCustomMaxLength(AddressField field) {
- return mMaxLengths.get(field);
+ public Builder setUrl(String url) {
+ if (url == null) {
+ throw new RuntimeException("Can't set address server URL to null.");
+ }
+ serverUrl = url;
+ return this;
}
/**
- * Class to build the form, specifying the attributes for each field.
+ * Customizes max length for a {@code AddressField}.
*/
- public static class Builder {
-
- private String mBaseId = "addressform";
-
- private final EnumSet<AddressField> mRequiredFields =
- EnumSet.noneOf(AddressField.class);
-
- private final EnumSet<AddressField> mHiddenFields =
- EnumSet.noneOf(AddressField.class);
-
- private final EnumSet<AddressField> mReadonlyFields =
- EnumSet.noneOf(AddressField.class);
-
- private final EnumMap<AddressField, String> mCustomLabels =
- new EnumMap<AddressField, String>(AddressField.class);
-
- private final Map<String, AddressField[]> mOverrideFieldOrder =
- new HashMap<String, AddressField[]>();
-
- private final EnumMap<AddressField, Integer> mMaxLengths =
- new EnumMap<AddressField, Integer>(AddressField.class);
-
- /**
- * Uses the default server URL from CacheData.
- */
- private String mServerUrl = new CacheData().getUrl();
-
- /**
- * Sets the base ID of the address form.
- */
- public Builder baseId(String baseId) {
- if (baseId == null) {
- throw new RuntimeException("baseId cannot be null.");
- }
- mBaseId = baseId;
- return this;
- }
-
- public Builder hide(AddressField field) {
- if (field == null) {
- throw new RuntimeException("AddressField field cannot be null.");
- }
- mHiddenFields.add(field);
- return this;
- }
-
- /**
- * Make a field read-only.
- */
- public Builder readonly(AddressField field) {
- if (field == null) {
- throw new RuntimeException("AddressField field cannot be null.");
- }
- mReadonlyFields.add(field);
- return this;
- }
-
- /**
- * Make a field required.
- */
- public Builder required(AddressField field) {
- if (field == null) {
- throw new RuntimeException("AddressField field cannot be null.");
- }
- mRequiredFields.add(field);
- return this;
- }
-
- /**
- * Customizes label for an {@code AddressField}.
- */
- public Builder customizeLabel(AddressField field, String label) {
- if (field == null) {
- throw new RuntimeException("AddressField field cannot be null.");
- }
- if (label == null) {
- throw new RuntimeException("Label cannot be null.");
- }
- mCustomLabels.put(field, label);
- return this;
- }
-
- /**
- * Sets the field order for a region code. The order you set here will override the
- * predefined one. For example, you can set field order for US to be first {@code
- * AddressField#ORGANIZATION} then {@code AddressField#RECIPIENT}. Repeated address fields
- * in {@code fields} are not allowed. Size of {@code fields} has to be larger than one.
- * Input {@code fields} can be partial or even contain field not needed in the specified
- * {@code regionCode}. For example, German addresses contain the following fields
- * (in order):<br/>
- {@link AddressField#RECIPIENT}, {@link AddressField#ORGANIZATION}, {@link
- * AddressField#STREET_ADDRESS}, {@link AddressField#POSTAL_CODE}, {@link
- * AddressField#LOCALITY}. <br/>
- *
- * <p>With the following call: <br/>
- *
- * customizeFieldOrder("DE", AddressField.ORGANIZATION, AddressField.RECIPIENT,
- * AddressField.ADMIN_AREA);
- *
- * <p>Field order for Germany will become: <br/> {@link AddressField#ORGANIZATION}, {@link
- * AddressField#RECIPIENT}, {@link AddressField#STREET_ADDRESS}, {@link
- * AddressField#POSTAL_CODE}, {@link AddressField#LOCALITY}. </p>
- *
- * <p>Notice that:<br/> <ol> <li>{@link AddressField#ORGANIZATION} comes before {@link
- * AddressField#RECIPIENT} after reordering.</li>
- * <li>Fields not specified stays the same.</li>
- * <li>{@link AddressField#ADMIN_AREA} is specified but since it is not in German address
- * format, it is simpled neglected.</li> </ol>
- *
- * @param fields the overridden field order.
- */
- public Builder customizeFieldOrder(String regionCode, AddressField... fields) {
- if (regionCode == null) {
- throw new RuntimeException("regionCode cannot be null.");
- }
- if (fields == null) {
- throw new RuntimeException("Fields cannot be null.");
- }
- if (fields.length <= 1) {
- throw new RuntimeException("There must be more than one field.");
- }
- HashSet<AddressField> checkList = new HashSet<AddressField>();
- AddressField[] f = new AddressField[fields.length];
- int i = 0;
- for (AddressField field : fields) {
- // Can't contain repeated address fields.
- if (checkList.contains(field)) {
- throw new RuntimeException("Address fields cannot be repeated.");
- }
- checkList.add(field);
- f[i] = field;
- i++;
- }
- mOverrideFieldOrder.put(regionCode, f);
- return this;
- }
-
- /**
- * Sets the URL of address data server. {@code url} cannot be null. This url will override
- * the default address server url.
- */
- public Builder setUrl(String url) {
- if (url == null) {
- throw new RuntimeException("Can't set address server URL to null.");
- }
- mServerUrl = url;
- return this;
- }
-
- /**
- * Customizes max length for a {@code AddressField}.
- */
- public Builder customizeMaxLength(AddressField field, int maxLength) {
- if (field == null) {
- throw new RuntimeException("AddressField field cannot be null.");
- }
- mMaxLengths.put(field, maxLength);
- return this;
- }
+ public Builder customizeMaxLength(AddressField field, int maxLength) {
+ if (field == null) {
+ throw new RuntimeException("AddressField field cannot be null.");
+ }
+ maxLengths.put(field, maxLength);
+ return this;
+ }
- public FormOptions build() {
- return new FormOptions(this);
- }
+ public FormOptions build() {
+ return new FormOptions(this);
}
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/FormatInterpreter.java b/java/src/com/android/i18n/addressinput/FormatInterpreter.java
index ed7b2ac..8634cfb 100644
--- a/java/src/com/android/i18n/addressinput/FormatInterpreter.java
+++ b/java/src/com/android/i18n/addressinput/FormatInterpreter.java
@@ -25,260 +25,286 @@ import org.json.JSONTokener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Address format interpreter. A utility to find address format related info.
*/
class FormatInterpreter {
- private static final String NEW_LINE = "%n";
+ private static final String NEW_LINE = "%n";
- private final String mDefaultFormat;
+ private final String defaultFormat;
- private final FormOptions mFormOptions;
+ private final FormOptions formOptions;
- /**
- * Creates a new instance of {@link FormatInterpreter}.
- */
- FormatInterpreter(FormOptions options) {
- Util.checkNotNull(RegionDataConstants.getCountryFormatMap(),
- "null country name map not allowed");
- Util.checkNotNull(options);
- mFormOptions = options;
- mDefaultFormat = getJsonValue("ZZ", AddressDataKey.FMT);
- Util.checkNotNull(mDefaultFormat, "null default format not allowed");
+ /**
+ * Creates a new instance of {@link FormatInterpreter}.
+ */
+ FormatInterpreter(FormOptions options) {
+ Util.checkNotNull(RegionDataConstants.getCountryFormatMap(),
+ "null country name map not allowed");
+ Util.checkNotNull(options);
+ formOptions = options;
+ defaultFormat = getJsonValue("ZZ", AddressDataKey.FMT);
+ Util.checkNotNull(defaultFormat, "null default format not allowed");
+ }
+
+ /**
+ * Returns a list of address fields based on the format of {@code regionCode}. Script type is
+ * needed because some countries uses different address formats for local/Latin scripts.
+ *
+ * @param scriptType if {@link ScriptType#LOCAL}, use local format; else use Latin format.
+ */
+ List<AddressField> getAddressFieldOrder(ScriptType scriptType, String regionCode) {
+ Util.checkNotNull(scriptType);
+ Util.checkNotNull(regionCode);
+ List<AddressField> fieldOrder = new ArrayList<AddressField>();
+ for (String substring : getFormatSubStrings(scriptType, regionCode)) {
+ // Skips un-escaped characters and new lines.
+ if (!substring.matches("%.") || substring.equals(NEW_LINE)) {
+ continue;
+ }
+
+ AddressField field = AddressField.of(substring.charAt(1));
+ fieldOrder.add(field);
}
- /**
- * Returns a list of address fields based on the format of {@code regionCode}. Script type is
- * needed because some countries uses different address formats for local/Latin scripts.
- *
- * @param scriptType if {@link ScriptType#LOCAL}, use local format; else use Latin format.
- */
- List<AddressField> getAddressFieldOrder(ScriptType scriptType, String regionCode) {
- Util.checkNotNull(scriptType);
- Util.checkNotNull(regionCode);
- List<AddressField> fieldOrder = new ArrayList<AddressField>();
- for (String substring : getFormatSubStrings(scriptType, regionCode)) {
- // Skips un-escaped characters and new lines.
- if (!substring.matches("%.") || substring.equals(NEW_LINE)) {
- continue;
- }
-
- AddressField field = AddressField.of(substring.charAt(1));
- fieldOrder.add(field);
- }
+ overrideFieldOrder(regionCode, fieldOrder);
- overrideFieldOrder(regionCode, fieldOrder);
-
- // Uses two address lines instead of street address.
- List<AddressField> finalFieldOrder = new ArrayList<AddressField>();
- for (AddressField field : fieldOrder) {
- if (field == AddressField.STREET_ADDRESS) {
- finalFieldOrder.add(AddressField.ADDRESS_LINE_1);
- finalFieldOrder.add(AddressField.ADDRESS_LINE_2);
- } else {
- finalFieldOrder.add(field);
- }
- }
- return finalFieldOrder;
+ // Uses two address lines instead of street address.
+ List<AddressField> finalFieldOrder = new ArrayList<AddressField>();
+ for (AddressField field : fieldOrder) {
+ if (field == AddressField.STREET_ADDRESS) {
+ finalFieldOrder.add(AddressField.ADDRESS_LINE_1);
+ finalFieldOrder.add(AddressField.ADDRESS_LINE_2);
+ } else {
+ finalFieldOrder.add(field);
+ }
}
+ return finalFieldOrder;
+ }
- /**
- * Returns a list of address fields based on the format of {@code regionCode} -- assuming script
- * type is {@link ScriptType#LOCAL}.
- */
- List<AddressField> getAddressFieldOrder(String regionCode) {
- Util.checkNotNull(regionCode);
- return getAddressFieldOrder(ScriptType.LOCAL, regionCode);
+ /**
+ * Returns a list of address fields based on the format of {@code regionCode} -- assuming script
+ * type is {@link ScriptType#LOCAL}.
+ */
+ List<AddressField> getAddressFieldOrder(String regionCode) {
+ Util.checkNotNull(regionCode);
+ return getAddressFieldOrder(ScriptType.LOCAL, regionCode);
+ }
+
+ private void overrideFieldOrder(String regionCode, List<AddressField> fieldOrder) {
+ if (formOptions.getCustomFieldOrder(regionCode) == null) {
+ return;
}
- private void overrideFieldOrder(String regionCode, List<AddressField> fieldOrder) {
- if (mFormOptions.getCustomFieldOrder(regionCode) == null) {
- return;
- }
+ // Constructs a hash for overridden field order.
+ final Map<AddressField, Integer> fieldPriority = new HashMap<AddressField, Integer>();
+ int i = 0;
+ for (AddressField field : formOptions.getCustomFieldOrder(regionCode)) {
+ fieldPriority.put(field, i);
+ i++;
+ }
- // Constructs a hash for overridden field order.
- final Map<AddressField, Integer> fieldPriority = new HashMap<AddressField, Integer>();
- int i = 0;
- for (AddressField field : mFormOptions.getCustomFieldOrder(regionCode)) {
- fieldPriority.put(field, i);
- i++;
- }
+ // Finds union of input fields and priority list.
+ List<AddressField> union = new ArrayList<AddressField>();
+ List<Integer> slots = new ArrayList<Integer>();
+ i = 0;
+ for (AddressField field : fieldOrder) {
+ if (fieldPriority.containsKey(field)) {
+ union.add(field);
+ slots.add(i);
+ }
+ i++;
+ }
- // Finds union of input fields and priority list.
- List<AddressField> union = new ArrayList<AddressField>();
- List<Integer> slots = new ArrayList<Integer>();
- i = 0;
- for (AddressField field : fieldOrder) {
- if (fieldPriority.containsKey(field)) {
- union.add(field);
- slots.add(i);
- }
- i++;
- }
+ // Overrides field order with priority list.
+ Collections.sort(union, new Comparator<AddressField>() {
+ @Override
+ public int compare(AddressField o1, AddressField o2) {
+ return fieldPriority.get(o1) - fieldPriority.get(o2);
+ }
+ });
- // Overrides field order with priority list.
- Collections.sort(union, new Comparator<AddressField>() {
- @Override
- public int compare(AddressField o1, AddressField o2) {
- return fieldPriority.get(o1) - fieldPriority.get(o2);
- }
- });
-
- // Puts reordered fields in slots.
- for (int j = 0; j < union.size(); ++j) {
- fieldOrder.set(slots.get(j), union.get(j));
- }
+ // Puts reordered fields in slots.
+ for (int j = 0; j < union.size(); ++j) {
+ fieldOrder.set(slots.get(j), union.get(j));
+ }
+ }
+
+ /**
+ * Returns the fields that are required to be filled in for this country. This is based upon the
+ * "required" field in RegionDataConstants for {@code regionCode}, and handles falling back to
+ * the default data if necessary.
+ */
+ static Set<AddressField> getRequiredFields(String regionCode) {
+ Util.checkNotNull(regionCode);
+ String requireString = getRequiredString(regionCode);
+
+ EnumSet<AddressField> required = EnumSet.of(AddressField.COUNTRY);
+ for (char c : requireString.toCharArray()) {
+ required.add(AddressField.of(c));
}
+ return required;
+ }
- /**
- * Gets formatted address. For example,
- *
- * <p> John Doe<br> Dnar Corp<br> 5th St<br> Santa Monica CA 90123 </p>
- *
- * This method does not validate addresses. Also, it will "normalize" the result strings by
- * removing redundant spaces and empty lines.
- */
- List<String> getEnvelopeAddress(AddressData address) {
- Util.checkNotNull(address, "null input address not allowed");
- String regionCode = address.getPostalCountry();
-
- String lc = address.getLanguageCode();
- ScriptType scriptType = ScriptType.LOCAL;
- if (lc != null) {
- scriptType = Util.isExplicitLatinScript(lc) ? ScriptType.LATIN : ScriptType.LOCAL;
+ private static String getRequiredString(String regionCode) {
+ String required = getJsonValue(regionCode, AddressDataKey.REQUIRE);
+ if (required == null) {
+ required = getJsonValue("ZZ", AddressDataKey.REQUIRE);
+ }
+ return required;
+ }
+
+ /**
+ * Gets formatted address. For example,
+ *
+ * <p> John Doe<br> Dnar Corp<br> 5th St<br> Santa Monica CA 90123 </p>
+ *
+ * This method does not validate addresses. Also, it will "normalize" the result strings by
+ * removing redundant spaces and empty lines.
+ */
+ List<String> getEnvelopeAddress(AddressData address) {
+ Util.checkNotNull(address, "null input address not allowed");
+ String regionCode = address.getPostalCountry();
+
+ String lc = address.getLanguageCode();
+ ScriptType scriptType = ScriptType.LOCAL;
+ if (lc != null) {
+ scriptType = Util.isExplicitLatinScript(lc) ? ScriptType.LATIN : ScriptType.LOCAL;
+ }
+
+ List<String> lines = new ArrayList<String>();
+ StringBuilder currentLine = new StringBuilder();
+ for (String formatSymbol : getFormatSubStrings(scriptType, regionCode)) {
+ if (formatSymbol.equals(NEW_LINE)) {
+ String normalizedStr =
+ removeRedundantSpacesAndLeadingPunctuation(currentLine.toString());
+ if (normalizedStr.length() > 0) {
+ lines.add(normalizedStr);
+ currentLine.setLength(0);
}
+ } else if (formatSymbol.startsWith("%")) {
+ char c = formatSymbol.charAt(1);
+ AddressField field = AddressField.of(c);
+ Util.checkNotNull(field, "null address field for character " + c);
- List<String> lines = new ArrayList<String>();
- StringBuilder currentLine = new StringBuilder();
- for (String formatSymbol : getFormatSubStrings(scriptType, regionCode)) {
- if (formatSymbol.equals(NEW_LINE)) {
- String normalizedStr =
- removeRedundantSpacesAndLeadingPunctuation(currentLine.toString());
- if (normalizedStr.length() > 0) {
- lines.add(normalizedStr);
- currentLine.setLength(0);
- }
- } else if (formatSymbol.startsWith("%")) {
- char c = formatSymbol.charAt(1);
- AddressField field = AddressField.of(c);
- Util.checkNotNull(field, "null address field for character " + c);
-
- String value = null;
- switch (field) {
- case STREET_ADDRESS:
- value = Util.joinAndSkipNulls("\n",
- address.getAddressLine1(),
- address.getAddressLine2());
- break;
- case COUNTRY:
- // Country name is treated separately.
- break;
- case ADMIN_AREA:
- value = address.getAdministrativeArea();
- break;
- case LOCALITY:
- value = address.getLocality();
- break;
- case DEPENDENT_LOCALITY:
- value = address.getDependentLocality();
- break;
- case RECIPIENT:
- value = address.getRecipient();
- break;
- case ORGANIZATION:
- value = address.getOrganization();
- break;
- case POSTAL_CODE:
- value = address.getPostalCode();
- break;
- default:
- break;
- }
-
- if (value != null) {
- currentLine.append(value);
- }
- } else {
- currentLine.append(formatSymbol);
- }
+ String value = null;
+ switch (field) {
+ case STREET_ADDRESS:
+ value = Util.joinAndSkipNulls("\n",
+ address.getAddressLine1(),
+ address.getAddressLine2());
+ break;
+ case COUNTRY:
+ // Country name is treated separately.
+ break;
+ case ADMIN_AREA:
+ value = address.getAdministrativeArea();
+ break;
+ case LOCALITY:
+ value = address.getLocality();
+ break;
+ case DEPENDENT_LOCALITY:
+ value = address.getDependentLocality();
+ break;
+ case RECIPIENT:
+ value = address.getRecipient();
+ break;
+ case ORGANIZATION:
+ value = address.getOrganization();
+ break;
+ case POSTAL_CODE:
+ value = address.getPostalCode();
+ break;
+ default:
+ break;
}
- String normalizedStr = removeRedundantSpacesAndLeadingPunctuation(currentLine.toString());
- if (normalizedStr.length() > 0) {
- lines.add(normalizedStr);
+
+ if (value != null) {
+ currentLine.append(value);
}
- return lines;
+ } else {
+ currentLine.append(formatSymbol);
+ }
+ }
+ String normalizedStr = removeRedundantSpacesAndLeadingPunctuation(currentLine.toString());
+ if (normalizedStr.length() > 0) {
+ lines.add(normalizedStr);
}
+ return lines;
+ }
- /**
- * Tokenizes the format string and returns the token string list. "%" is treated as an escape
- * character. So for example "%n%a%nxyz" will be split into "%n", "%a", "%n", "x", "y", and "z".
- * Escaped tokens correspond to either new line or address fields.
- */
- private List<String> getFormatSubStrings(ScriptType scriptType, String regionCode) {
- String formatString = getFormatString(scriptType, regionCode);
- List<String> parts = new ArrayList<String>();
-
- boolean escaped = false;
- for (char c : formatString.toCharArray()) {
- if (escaped) {
- escaped = false;
- if (NEW_LINE.equals("%" + c)) {
- parts.add(NEW_LINE);
- } else {
- Util.checkNotNull(AddressField.of(c), "Unrecognized character '" + c
- + "' in format pattern: " + formatString);
- parts.add("%" + c);
- }
- } else if (c == '%') {
- escaped = true;
- } else {
- parts.add(c + "");
- }
+ /**
+ * Tokenizes the format string and returns the token string list. "%" is treated as an escape
+ * character. So for example "%n%a%nxyz" will be split into "%n", "%a", "%n", "x", "y", and "z".
+ * Escaped tokens correspond to either new line or address fields.
+ */
+ private List<String> getFormatSubStrings(ScriptType scriptType, String regionCode) {
+ String formatString = getFormatString(scriptType, regionCode);
+ List<String> parts = new ArrayList<String>();
+
+ boolean escaped = false;
+ for (char c : formatString.toCharArray()) {
+ if (escaped) {
+ escaped = false;
+ if (NEW_LINE.equals("%" + c)) {
+ parts.add(NEW_LINE);
+ } else {
+ Util.checkNotNull(AddressField.of(c), "Unrecognized character '" + c
+ + "' in format pattern: " + formatString);
+ parts.add("%" + c);
}
- return parts;
+ } else if (c == '%') {
+ escaped = true;
+ } else {
+ parts.add(c + "");
+ }
}
+ return parts;
+ }
- private static String removeRedundantSpacesAndLeadingPunctuation(String str) {
- // Remove leading commas and other punctuation that might have been added by the formatter
- // in the case of missing data.
- str = str.replaceFirst("^[-,\\s]+", "");
- str = str.trim();
- str = str.replaceAll(" +", " ");
- return str;
- }
+ private static String removeRedundantSpacesAndLeadingPunctuation(String str) {
+ // Remove leading commas and other punctuation that might have been added by the formatter
+ // in the case of missing data.
+ str = str.replaceFirst("^[-,\\s]+", "");
+ str = str.trim();
+ str = str.replaceAll(" +", " ");
+ return str;
+ }
- private static String getFormatString(ScriptType scriptType, String regionCode) {
- String format = (scriptType == ScriptType.LOCAL)
- ? getJsonValue(regionCode, AddressDataKey.FMT)
- : getJsonValue(regionCode, AddressDataKey.LFMT);
- if (format == null) {
- format = getJsonValue("ZZ", AddressDataKey.FMT);
- }
- return format;
+ private static String getFormatString(ScriptType scriptType, String regionCode) {
+ String format = (scriptType == ScriptType.LOCAL)
+ ? getJsonValue(regionCode, AddressDataKey.FMT)
+ : getJsonValue(regionCode, AddressDataKey.LFMT);
+ if (format == null) {
+ format = getJsonValue("ZZ", AddressDataKey.FMT);
}
+ return format;
+ }
- private static String getJsonValue(String regionCode, AddressDataKey key) {
- Util.checkNotNull(regionCode);
- String jsonString = RegionDataConstants.getCountryFormatMap().get(regionCode);
- Util.checkNotNull(jsonString, "no json data for region code " + regionCode);
-
- try {
- JSONObject jsonObj = new JSONObject(new JSONTokener(jsonString));
- if (!jsonObj.has(key.name().toLowerCase())) {
- // Key not found. Return null.
- return null;
- }
- // Gets the string for this key.
- String parsedJsonString = jsonObj.getString(key.name().toLowerCase());
- return parsedJsonString;
- } catch (JSONException e) {
- throw new RuntimeException("Invalid json for region code " + regionCode
- + ": " + jsonString);
- }
+ private static String getJsonValue(String regionCode, AddressDataKey key) {
+ Util.checkNotNull(regionCode);
+ String jsonString = RegionDataConstants.getCountryFormatMap().get(regionCode);
+ Util.checkNotNull(jsonString, "no json data for region code " + regionCode);
+
+ try {
+ JSONObject jsonObj = new JSONObject(new JSONTokener(jsonString));
+ if (!jsonObj.has(key.name().toLowerCase())) {
+ // Key not found. Return null.
+ return null;
+ }
+ // Gets the string for this key.
+ String parsedJsonString = jsonObj.getString(key.name().toLowerCase());
+ return parsedJsonString;
+ } catch (JSONException e) {
+ throw new RuntimeException("Invalid json for region code " + regionCode
+ + ": " + jsonString);
}
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/JsoMap.java b/java/src/com/android/i18n/addressinput/JsoMap.java
index fc5d16b..01e873b 100644
--- a/java/src/com/android/i18n/addressinput/JsoMap.java
+++ b/java/src/com/android/i18n/addressinput/JsoMap.java
@@ -29,256 +29,256 @@ import java.util.Iterator;
*/
class JsoMap extends JSONObject {
- /**
- * Construct a JsoMap object given some json text. This method directly evaluates the String
- * that you pass in; no error or safety checking is performed, so be very careful about the
- * source of your data.
- *
- * @param json JSON text describing an address format
- * @return a JsoMap object made from the supplied JSON.
- */
- static JsoMap buildJsoMap(String json) throws JSONException {
- return new JsoMap(new JSONTokener(json));
- }
+ /**
+ * Construct a JsoMap object given some json text. This method directly evaluates the String
+ * that you pass in; no error or safety checking is performed, so be very careful about the
+ * source of your data.
+ *
+ * @param json JSON text describing an address format
+ * @return a JsoMap object made from the supplied JSON.
+ */
+ static JsoMap buildJsoMap(String json) throws JSONException {
+ return new JsoMap(new JSONTokener(json));
+ }
- /**
- * Construct an empty JsoMap.
- *
- * @return the empty object.
- */
- static JsoMap createEmptyJsoMap() {
- return new JsoMap();
- }
+ /**
+ * Construct an empty JsoMap.
+ *
+ * @return the empty object.
+ */
+ static JsoMap createEmptyJsoMap() {
+ return new JsoMap();
+ }
- /**
- * constructor.
- */
- protected JsoMap() {
- }
+ /**
+ * constructor.
+ */
+ protected JsoMap() {
+ }
- private JsoMap(JSONTokener readFrom) throws JSONException {
- super(readFrom);
- }
+ private JsoMap(JSONTokener readFrom) throws JSONException {
+ super(readFrom);
+ }
- private JsoMap(JSONObject copyFrom, String[] names) throws JSONException {
- super(copyFrom, names);
- }
+ private JsoMap(JSONObject copyFrom, String[] names) throws JSONException {
+ super(copyFrom, names);
+ }
- /**
- * Remove the specified key.
- *
- * @param key key name.
- */
- void delKey(String key) {
- super.remove(key);
- }
+ /**
+ * Remove the specified key.
+ *
+ * @param key key name.
+ */
+ void delKey(String key) {
+ super.remove(key);
+ }
- /**
- * Retrieve the string value for specified key.
- *
- * @param key key name.
- * @return string value.
- * @throws ClassCastException, IllegalArgumentException.
- */
- @Override
- public String get(String key) { // throws ClassCastException, IllegalArgumentException
- try {
- Object o = super.get(key);
- if (o instanceof String) {
- return (String) o;
- } else if (o instanceof Integer) {
- throw new IllegalArgumentException();
- } else {
- throw new ClassCastException();
- }
- } catch (JSONException e) {
- return null;
- }
+ /**
+ * Retrieve the string value for specified key.
+ *
+ * @param key key name.
+ * @return string value.
+ * @throws ClassCastException, IllegalArgumentException.
+ */
+ @Override
+ public String get(String key) { // throws ClassCastException, IllegalArgumentException
+ try {
+ Object o = super.get(key);
+ if (o instanceof String) {
+ return (String) o;
+ } else if (o instanceof Integer) {
+ throw new IllegalArgumentException();
+ } else {
+ throw new ClassCastException();
+ }
+ } catch (JSONException e) {
+ return null;
}
+ }
- /**
- * Access JSONObject.get(String) which is shadowed by JsoMap.get(String).
- *
- * @param name A key string.
- * @return The object associated with the key.
- * @throws JSONException if the key is not found.
- */
- private Object getObject(String name) throws JSONException {
- return super.get(name);
- }
+ /**
+ * Access JSONObject.get(String) which is shadowed by JsoMap.get(String).
+ *
+ * @param name A key string.
+ * @return The object associated with the key.
+ * @throws JSONException if the key is not found.
+ */
+ private Object getObject(String name) throws JSONException {
+ return super.get(name);
+ }
- /**
- * Retrieves the integer value for specified key.
- *
- * @return integer value or -1 if value is undefined.
- */
- @Override
- public int getInt(String key) {
- try {
- Object o = super.get(key);
- if (o instanceof Integer) {
- return ((Integer) o).intValue();
- } else {
- throw new RuntimeException("Something other than an int was returned");
- }
- } catch (JSONException e) {
- return -1;
- }
+ /**
+ * Retrieves the integer value for specified key.
+ *
+ * @return integer value or -1 if value is undefined.
+ */
+ @Override
+ public int getInt(String key) {
+ try {
+ Object o = super.get(key);
+ if (o instanceof Integer) {
+ return ((Integer) o).intValue();
+ } else {
+ throw new RuntimeException("Something other than an int was returned");
+ }
+ } catch (JSONException e) {
+ return -1;
}
+ }
- /**
- * Collect all the keys and return as a JSONArray.
- *
- * @return A JSONArray that contains all the keys.
- */
- JSONArray getKeys() {
- return super.names();
- }
+ /**
+ * Collect all the keys and return as a JSONArray.
+ *
+ * @return A JSONArray that contains all the keys.
+ */
+ JSONArray getKeys() {
+ return super.names();
+ }
- /**
- * Retrieve the JsoMap object for specified key.
- *
- * @param key key name.
- * @return JsoMap object.
- * @throws ClassCastException, IllegalArgumentException.
- */
- @SuppressWarnings("unchecked")
- // JSONObject.keys() has no type information.
- JsoMap getObj(String key)
- throws ClassCastException, IllegalArgumentException {
+ /**
+ * Retrieve the JsoMap object for specified key.
+ *
+ * @param key key name.
+ * @return JsoMap object.
+ * @throws ClassCastException, IllegalArgumentException.
+ */
+ @SuppressWarnings("unchecked")
+ // JSONObject.keys() has no type information.
+ JsoMap getObj(String key)
+ throws ClassCastException, IllegalArgumentException {
try {
- Object o = super.get(key);
- if (o instanceof JSONObject) {
- JSONObject value = (JSONObject) o;
- ArrayList<String> keys = new ArrayList<String>(value.length());
- for (Iterator<String> it = value.keys(); it.hasNext();) {
- keys.add(it.next());
- }
- String[] names = new String[keys.size()];
- return new JsoMap(value, keys.toArray(names));
- } else if (o instanceof Integer) {
- throw new IllegalArgumentException();
- } else {
- throw new ClassCastException();
+ Object o = super.get(key);
+ if (o instanceof JSONObject) {
+ JSONObject value = (JSONObject) o;
+ ArrayList<String> keys = new ArrayList<String>(value.length());
+ for (Iterator<String> it = value.keys(); it.hasNext();) {
+ keys.add(it.next());
}
+ String[] names = new String[keys.size()];
+ return new JsoMap(value, keys.toArray(names));
+ } else if (o instanceof Integer) {
+ throw new IllegalArgumentException();
+ } else {
+ throw new ClassCastException();
+ }
} catch (JSONException e) {
- return null;
+ return null;
}
- }
-
- /**
- * Check if the object has specified key.
- *
- * @param key The key name to be checked.
- * @return true if key can be found.
- */
- boolean containsKey(String key) {
- return super.has(key);
- }
+ }
- /**
- * Merge those keys not found in this object from specified object.
- *
- * @param obj The other object to be merged.
- */
- void mergeData(JsoMap obj) {
- if (obj == null) {
- return;
- }
+ /**
+ * Check if the object has specified key.
+ *
+ * @param key The key name to be checked.
+ * @return true if key can be found.
+ */
+ boolean containsKey(String key) {
+ return super.has(key);
+ }
- JSONArray names = obj.names();
- if (names == null) {
- return;
- }
+ /**
+ * Merge those keys not found in this object from specified object.
+ *
+ * @param obj The other object to be merged.
+ */
+ void mergeData(JsoMap obj) {
+ if (obj == null) {
+ return;
+ }
- for (int i = 0; i < names.length(); i++) {
- try {
- String name = names.getString(i);
- try {
- if (!super.has(name)) {
- super.put(name, obj.getObject(name));
- }
- } catch (JSONException e) {
- throw new RuntimeException(e);
- }
- } catch (JSONException e) {
- // Ignored.
- }
- }
+ JSONArray names = obj.names();
+ if (names == null) {
+ return;
}
- /**
- * Save a string to string mapping into this map.
- *
- * @param key the string key.
- * @param value the String value.
- */
- void put(String key, String value) {
+ for (int i = 0; i < names.length(); i++) {
+ try {
+ String name = names.getString(i);
try {
- super.put(key, value);
+ if (!super.has(name)) {
+ super.put(name, obj.getObject(name));
+ }
} catch (JSONException e) {
- throw new RuntimeException(e);
+ throw new RuntimeException(e);
}
+ } catch (JSONException e) {
+ // Ignored.
+ }
}
+ }
- /**
- * Save a string to integer mapping into this map.
- *
- * @param key the string key.
- * @param value the integer value.
- */
- void putInt(String key, int value) {
- try {
- super.put(key, value);
- } catch (JSONException e) {
- throw new RuntimeException(e);
- }
+ /**
+ * Save a string to string mapping into this map.
+ *
+ * @param key the string key.
+ * @param value the String value.
+ */
+ void put(String key, String value) {
+ try {
+ super.put(key, value);
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
}
+ }
- /**
- * Save a string to JSONObject mapping into this map.
- *
- * @param key the string key.
- * @param value a JSONObject as value.
- */
- void putObj(String key, JSONObject value) {
- try {
- super.put(key, value);
- } catch (JSONException e) {
- throw new RuntimeException(e);
- }
+ /**
+ * Save a string to integer mapping into this map.
+ *
+ * @param key the string key.
+ * @param value the integer value.
+ */
+ void putInt(String key, int value) {
+ try {
+ super.put(key, value);
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
}
+ }
- String string() throws ClassCastException, IllegalArgumentException {
- StringBuilder sb = new StringBuilder("JsoMap[\n");
- JSONArray keys = getKeys();
- for (int i = 0; i < keys.length(); i++) {
- String key;
- try {
- key = keys.getString(i);
- } catch (JSONException e) {
- throw new RuntimeException(e);
- }
- sb.append('(').append(key).append(':').append(get(key)).append(')').append('\n');
- }
- sb.append(']');
- return sb.toString();
+ /**
+ * Save a string to JSONObject mapping into this map.
+ *
+ * @param key the string key.
+ * @param value a JSONObject as value.
+ */
+ void putObj(String key, JSONObject value) {
+ try {
+ super.put(key, value);
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
}
+ }
- String map() throws ClassCastException, IllegalArgumentException {
- StringBuilder sb = new StringBuilder("JsoMap[\n");
- JSONArray keys = getKeys();
- for (int i = 0; i < keys.length(); i++) {
- String key;
- try {
- key = keys.getString(i);
- } catch (JSONException e) {
- throw new RuntimeException(e);
- }
- sb.append('(').append(key).append(':').append(getObj(key).string()).append(')')
- .append('\n');
- }
- sb.append(']');
- return sb.toString();
+ String string() throws ClassCastException, IllegalArgumentException {
+ StringBuilder sb = new StringBuilder("JsoMap[\n");
+ JSONArray keys = getKeys();
+ for (int i = 0; i < keys.length(); i++) {
+ String key;
+ try {
+ key = keys.getString(i);
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
+ }
+ sb.append('(').append(key).append(':').append(get(key)).append(')').append('\n');
+ }
+ sb.append(']');
+ return sb.toString();
+ }
+
+ String map() throws ClassCastException, IllegalArgumentException {
+ StringBuilder sb = new StringBuilder("JsoMap[\n");
+ JSONArray keys = getKeys();
+ for (int i = 0; i < keys.length(); i++) {
+ String key;
+ try {
+ key = keys.getString(i);
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
+ }
+ sb.append('(').append(key).append(':').append(getObj(key).string()).append(')')
+ .append('\n');
}
+ sb.append(']');
+ return sb.toString();
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/JsonpRequestBuilder.java b/java/src/com/android/i18n/addressinput/JsonpRequestBuilder.java
index 0f40f15..d5bc608 100644
--- a/java/src/com/android/i18n/addressinput/JsonpRequestBuilder.java
+++ b/java/src/com/android/i18n/addressinput/JsonpRequestBuilder.java
@@ -33,98 +33,98 @@ import java.net.URLEncoder;
*/
class JsonpRequestBuilder {
- /**
- * Re-implementation of the com.google.gwt.user.client.rpc.AsyncCallback interface.
- */
- interface AsyncCallback<T> {
-
- public void onFailure(Throwable caught);
-
- public void onSuccess(T result);
- }
-
- /**
- * @param timeout The expected timeout (ms) for this request.
- */
- void setTimeout(int timeout) {
- HttpParams params = AsyncHttp.CLIENT.getParams();
- HttpConnectionParams.setConnectionTimeout(params, timeout);
- HttpConnectionParams.setSoTimeout(params, timeout);
+ /**
+ * Re-implementation of the com.google.gwt.user.client.rpc.AsyncCallback interface.
+ */
+ interface AsyncCallback<T> {
+
+ public void onFailure(Throwable caught);
+
+ public void onSuccess(T result);
+ }
+
+ /**
+ * @param timeout The expected timeout (ms) for this request.
+ */
+ void setTimeout(int timeout) {
+ HttpParams params = AsyncHttp.CLIENT.getParams();
+ HttpConnectionParams.setConnectionTimeout(params, timeout);
+ HttpConnectionParams.setSoTimeout(params, timeout);
+ }
+
+ /**
+ * Sends a JSONP request and expects a JsoMap object as a result.
+ */
+ void requestObject(String url, AsyncCallback<JsoMap> callback) {
+ HttpUriRequest request = new HttpGet(encodeUrl(url));
+ (new AsyncHttp(request, callback)).start();
+ }
+
+ /**
+ * Simple implementation of asynchronous HTTP GET.
+ */
+ private static class AsyncHttp extends Thread {
+
+ private static final HttpClient CLIENT = new DefaultHttpClient();
+
+ private HttpUriRequest request;
+
+ private AsyncCallback<JsoMap> callback;
+
+ protected AsyncHttp(HttpUriRequest request, AsyncCallback<JsoMap> callback) {
+ this.request = request;
+ this.callback = callback;
}
- /**
- * Sends a JSONP request and expects a JsoMap object as a result.
- */
- void requestObject(String url, AsyncCallback<JsoMap> callback) {
- HttpUriRequest request = new HttpGet(encodeUrl(url));
- (new AsyncHttp(request, callback)).start();
+ @Override
+ public void run() {
+ try {
+ final String response;
+ synchronized (CLIENT) {
+ response = CLIENT.execute(request, new BasicResponseHandler());
+ }
+ callback.onSuccess(JsoMap.buildJsoMap(response));
+ } catch (Exception e) {
+ callback.onFailure(e);
+ }
}
-
- /**
- * Simple implementation of asynchronous HTTP GET.
- */
- private static class AsyncHttp extends Thread {
-
- private static final HttpClient CLIENT = new DefaultHttpClient();
-
- private HttpUriRequest mRequest;
-
- private AsyncCallback<JsoMap> mCallback;
-
- protected AsyncHttp(HttpUriRequest request, AsyncCallback<JsoMap> callback) {
- mRequest = request;
- mCallback = callback;
+ }
+
+ /**
+ * A quick hack to transform a string into an RFC 3986 compliant URL.
+ *
+ * TODO: Refactor the code to stop passing URLs around as strings, to eliminate the need for
+ * this hack.
+ */
+ private static String encodeUrl(String url) {
+ int length = url.length();
+ StringBuilder tmp = new StringBuilder(length);
+
+ try {
+ for (int i = 0; i < length; i++) {
+ int j = i;
+ char c = '\0';
+ for (; j < length; j++) {
+ c = url.charAt(j);
+ if (c == ':' || c == '/') {
+ break;
+ }
}
-
- @Override
- public void run() {
- try {
- final String response;
- synchronized (CLIENT) {
- response = CLIENT.execute(mRequest, new BasicResponseHandler());
- }
- mCallback.onSuccess(JsoMap.buildJsoMap(response));
- } catch (Exception e) {
- mCallback.onFailure(e);
- }
+ if (j == length) {
+ tmp.append(URLEncoder.encode(url.substring(i), "UTF-8"));
+ break;
+ } else if (j > i) {
+ tmp.append(URLEncoder.encode(url.substring(i, j), "UTF-8"));
+ tmp.append(c);
+ i = j;
+ } else {
+ tmp.append(c);
}
+ }
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e); // Impossible.
}
- /**
- * A quick hack to transform a string into an RFC 3986 compliant URL.
- *
- * TODO: Refactor the code to stop passing URLs around as strings, to eliminate the need for
- * this hack.
- */
- private static String encodeUrl(String url) {
- int length = url.length();
- StringBuilder tmp = new StringBuilder(length);
-
- try {
- for (int i = 0; i < length; i++) {
- int j = i;
- char c = '\0';
- for (; j < length; j++) {
- c = url.charAt(j);
- if (c == ':' || c == '/') {
- break;
- }
- }
- if (j == length) {
- tmp.append(URLEncoder.encode(url.substring(i), "UTF-8"));
- break;
- } else if (j > i) {
- tmp.append(URLEncoder.encode(url.substring(i, j), "UTF-8"));
- tmp.append(c);
- i = j;
- } else {
- tmp.append(c);
- }
- }
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e); // Impossible.
- }
-
- return tmp.toString();
- }
+ return tmp.toString();
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/LookupKey.java b/java/src/com/android/i18n/addressinput/LookupKey.java
index 35aad1d..aea9847 100644
--- a/java/src/com/android/i18n/addressinput/LookupKey.java
+++ b/java/src/com/android/i18n/addressinput/LookupKey.java
@@ -34,403 +34,403 @@ import java.util.Map;
*/
final class LookupKey {
- /**
- * Key types. Address Widget organizes address info based on key types. For example, if you want
- * to know how to verify or format an US address, you need to use {@link KeyType#DATA} to get
- * that info; if you want to get an example address, you use {@link KeyType#EXAMPLES} instead.
- */
- enum KeyType {
-
- /**
- * Key type for getting address data.
- */
- DATA,
- /**
- * Key type for getting examples.
- */
- EXAMPLES
- }
+ /**
+ * Key types. Address Widget organizes address info based on key types. For example, if you want
+ * to know how to verify or format an US address, you need to use {@link KeyType#DATA} to get
+ * that info; if you want to get an example address, you use {@link KeyType#EXAMPLES} instead.
+ */
+ enum KeyType {
/**
- * Script types. This is used for countries that do not use Latin script, but accept it for
- * transcribing their addresses. For example, you can write a Japanese address in Latin script
- * instead of Japanese:
- *
- * <p> 7-2, Marunouchi 2-Chome, Chiyoda-ku, Tokyo 100-8799 </p>
- *
- * Notice that {@link ScriptType} is based on country/region, not language.
+ * Key type for getting address data.
*/
- enum ScriptType {
-
- /**
- * The script that uses Roman characters like ABC (as opposed to scripts like Cyrillic or
- * Arabic).
- */
- LATIN,
-
- /**
- * Local scripts. For Japan, it's Japanese (including Hiragana, Katagana, and Kanji); For
- * Saudi Arabia, it's Arabic. Notice that for US, the local script is actually Latin script
- * (The same goes for other countries that use Latin script). For these countries, we do not
- * provide two set of data (Latin and local) since they use only Latin script. You have to
- * specify the {@link ScriptType} as local instead Latin.
- */
- LOCAL
- }
-
+ DATA,
/**
- * The universal address hierarchy. Notice that sub-administrative area is neglected here since
- * it is not required to fill out address form.
+ * Key type for getting examples.
*/
- private static final AddressField[] HIERARCHY = {
- AddressField.COUNTRY,
- AddressField.ADMIN_AREA,
- AddressField.LOCALITY,
- AddressField.DEPENDENT_LOCALITY};
-
- private static final String SLASH_DELIM = "/";
-
- private static final String DASH_DELIM = "--";
-
- private static final String DEFAULT_LANGUAGE = "_default";
-
- private final KeyType mKeyType;
-
- private final ScriptType mScriptType;
-
- // Values for hierarchy address fields.
- private final Map<AddressField, String> mNodes;
-
- private final String mKeyString;
-
- private final String mLanguageCode;
-
- private LookupKey(Builder builder) {
- this.mKeyType = builder.keyType;
- this.mScriptType = builder.script;
- this.mNodes = builder.nodes;
- this.mLanguageCode = builder.languageCode;
- this.mKeyString = getKeyString();
- }
+ EXAMPLES
+ }
+
+ /**
+ * Script types. This is used for countries that do not use Latin script, but accept it for
+ * transcribing their addresses. For example, you can write a Japanese address in Latin script
+ * instead of Japanese:
+ *
+ * <p> 7-2, Marunouchi 2-Chome, Chiyoda-ku, Tokyo 100-8799 </p>
+ *
+ * Notice that {@link ScriptType} is based on country/region, not language.
+ */
+ enum ScriptType {
/**
- * Gets lookup key for the input address field. This method does not allow key with key type of
- * {@link KeyType#EXAMPLES}.
- *
- * @param field a field in the address hierarchy.
- * @return key of the specified address field. If address field is not in the hierarchy, or is
- * more granular than the current key has, returns null. For example, if your current
- * key is "data/US" (down to country level), and you want to get the key for Locality
- * (more granular than country), it will return null.
+ * The script that uses Roman characters like ABC (as opposed to scripts like Cyrillic or
+ * Arabic).
*/
- LookupKey getKeyForUpperLevelField(AddressField field) {
- if (mKeyType != KeyType.DATA) {
- // We only support getting the parent key for the data key type.
- throw new RuntimeException("Only support getting parent keys for the data key type.");
- }
- Builder newKeyBuilder = new Builder(this);
-
- boolean removeNode = false;
- boolean fieldInHierarchy = false;
- for (AddressField hierarchyField : HIERARCHY) {
- if (removeNode) {
- if (newKeyBuilder.nodes.containsKey(hierarchyField)) {
- newKeyBuilder.nodes.remove(hierarchyField);
- }
- }
- if (hierarchyField == field) {
- if (!newKeyBuilder.nodes.containsKey(hierarchyField)) {
- return null;
- }
- removeNode = true;
- fieldInHierarchy = true;
- }
- }
-
- if (!fieldInHierarchy) {
- return null;
- }
-
- newKeyBuilder.languageCode = mLanguageCode;
- newKeyBuilder.script = mScriptType;
-
- return newKeyBuilder.build();
- }
+ LATIN,
/**
- * Returns the string value of a field in a key for a particular
- * AddressField. For example, for the key "data/US/CA" and the address
- * field AddressField.COUNTRY, "US" would be returned. Returns an empty
- * string if the key does not have this field in it.
+ * Local scripts. For Japan, it's Japanese (including Hiragana, Katagana, and Kanji); For
+ * Saudi Arabia, it's Arabic. Notice that for US, the local script is actually Latin script
+ * (The same goes for other countries that use Latin script). For these countries, we do not
+ * provide two set of data (Latin and local) since they use only Latin script. You have to
+ * specify the {@link ScriptType} as local instead Latin.
*/
- String getValueForUpperLevelField(AddressField field) {
- // First, get the key for this field.
- LookupKey key = getKeyForUpperLevelField(field);
- // Now we know the last value in the string is the value for this field.
- if (key != null) {
- String keyString = key.toString();
- int lastSlashPosition = keyString.lastIndexOf(SLASH_DELIM);
- if (lastSlashPosition > 0 && lastSlashPosition != keyString.length()) {
- return keyString.substring(lastSlashPosition + 1);
- }
- }
- return "";
+ LOCAL
+ }
+
+ /**
+ * The universal address hierarchy. Notice that sub-administrative area is neglected here since
+ * it is not required to fill out address form.
+ */
+ private static final AddressField[] HIERARCHY = {
+ AddressField.COUNTRY,
+ AddressField.ADMIN_AREA,
+ AddressField.LOCALITY,
+ AddressField.DEPENDENT_LOCALITY};
+
+ private static final String SLASH_DELIM = "/";
+
+ private static final String DASH_DELIM = "--";
+
+ private static final String DEFAULT_LANGUAGE = "_default";
+
+ private final KeyType keyType;
+
+ private final ScriptType scriptType;
+
+ // Values for hierarchy address fields.
+ private final Map<AddressField, String> nodes;
+
+ private final String keyString;
+
+ private final String languageCode;
+
+ private LookupKey(Builder builder) {
+ this.keyType = builder.keyType;
+ this.scriptType = builder.script;
+ this.nodes = builder.nodes;
+ this.languageCode = builder.languageCode;
+ this.keyString = getKeyString();
+ }
+
+ /**
+ * Gets lookup key for the input address field. This method does not allow key with key type of
+ * {@link KeyType#EXAMPLES}.
+ *
+ * @param field a field in the address hierarchy.
+ * @return key of the specified address field. If address field is not in the hierarchy, or is
+ * more granular than the current key has, returns null. For example, if your current
+ * key is "data/US" (down to country level), and you want to get the key for Locality
+ * (more granular than country), it will return null.
+ */
+ LookupKey getKeyForUpperLevelField(AddressField field) {
+ if (keyType != KeyType.DATA) {
+ // We only support getting the parent key for the data key type.
+ throw new RuntimeException("Only support getting parent keys for the data key type.");
}
-
- /**
- * Gets parent key for data key. For example, parent key for "data/US/CA" is "data/US". This
- * method does not allow key with key type of {@link KeyType#EXAMPLES}.
- */
- LookupKey getParentKey() {
- if (mKeyType != KeyType.DATA) {
- throw new RuntimeException("Only support getting parent keys for the data key type.");
+ Builder newKeyBuilder = new Builder(this);
+
+ boolean removeNode = false;
+ boolean fieldInHierarchy = false;
+ for (AddressField hierarchyField : HIERARCHY) {
+ if (removeNode) {
+ if (newKeyBuilder.nodes.containsKey(hierarchyField)) {
+ newKeyBuilder.nodes.remove(hierarchyField);
}
- // Root key's parent should be null.
- if (!mNodes.containsKey(AddressField.COUNTRY)) {
- return null;
+ }
+ if (hierarchyField == field) {
+ if (!newKeyBuilder.nodes.containsKey(hierarchyField)) {
+ return null;
}
+ removeNode = true;
+ fieldInHierarchy = true;
+ }
+ }
- Builder parentKeyBuilder = new Builder(this);
- AddressField mostGranularField = AddressField.COUNTRY;
-
- for (AddressField hierarchyField : HIERARCHY) {
- if (!mNodes.containsKey(hierarchyField)) {
- break;
- }
- mostGranularField = hierarchyField;
- }
- parentKeyBuilder.nodes.remove(mostGranularField);
- return parentKeyBuilder.build();
+ if (!fieldInHierarchy) {
+ return null;
}
- KeyType getKeyType() {
- return mKeyType;
+ newKeyBuilder.languageCode = languageCode;
+ newKeyBuilder.script = scriptType;
+
+ return newKeyBuilder.build();
+ }
+
+ /**
+ * Returns the string value of a field in a key for a particular
+ * AddressField. For example, for the key "data/US/CA" and the address
+ * field AddressField.COUNTRY, "US" would be returned. Returns an empty
+ * string if the key does not have this field in it.
+ */
+ String getValueForUpperLevelField(AddressField field) {
+ // First, get the key for this field.
+ LookupKey key = getKeyForUpperLevelField(field);
+ // Now we know the last value in the string is the value for this field.
+ if (key != null) {
+ String keyString = key.toString();
+ int lastSlashPosition = keyString.lastIndexOf(SLASH_DELIM);
+ if (lastSlashPosition > 0 && lastSlashPosition != keyString.length()) {
+ return keyString.substring(lastSlashPosition + 1);
+ }
+ }
+ return "";
+ }
+
+ /**
+ * Gets parent key for data key. For example, parent key for "data/US/CA" is "data/US". This
+ * method does not allow key with key type of {@link KeyType#EXAMPLES}.
+ */
+ LookupKey getParentKey() {
+ if (keyType != KeyType.DATA) {
+ throw new RuntimeException("Only support getting parent keys for the data key type.");
+ }
+ // Root key's parent should be null.
+ if (!nodes.containsKey(AddressField.COUNTRY)) {
+ return null;
}
- /**
- * Gets a key in string format. E.g., "data/US/CA".
- */
- private String getKeyString() {
- StringBuilder keyBuilder = new StringBuilder(mKeyType.name().toLowerCase());
-
- if (mKeyType == KeyType.DATA) {
- for (AddressField field : HIERARCHY) {
- if (!mNodes.containsKey(field)) {
- break;
- }
- if (field == AddressField.COUNTRY && mLanguageCode != null) {
- keyBuilder.append(SLASH_DELIM)
- .append(mNodes.get(field)).append(DASH_DELIM)
- .append(mLanguageCode);
- } else {
- keyBuilder.append(SLASH_DELIM).append(mNodes.get(field));
- }
- }
+ Builder parentKeyBuilder = new Builder(this);
+ AddressField mostGranularField = AddressField.COUNTRY;
+
+ for (AddressField hierarchyField : HIERARCHY) {
+ if (!nodes.containsKey(hierarchyField)) {
+ break;
+ }
+ mostGranularField = hierarchyField;
+ }
+ parentKeyBuilder.nodes.remove(mostGranularField);
+ return parentKeyBuilder.build();
+ }
+
+ KeyType getKeyType() {
+ return keyType;
+ }
+
+ /**
+ * Gets a key in string format. E.g., "data/US/CA".
+ */
+ private String getKeyString() {
+ StringBuilder keyBuilder = new StringBuilder(keyType.name().toLowerCase());
+
+ if (keyType == KeyType.DATA) {
+ for (AddressField field : HIERARCHY) {
+ if (!nodes.containsKey(field)) {
+ break;
+ }
+ if (field == AddressField.COUNTRY && languageCode != null) {
+ keyBuilder.append(SLASH_DELIM)
+ .append(nodes.get(field)).append(DASH_DELIM)
+ .append(languageCode);
} else {
- if (mNodes.containsKey(AddressField.COUNTRY)) {
- // Example key. E.g., "examples/TW/local/_default".
- keyBuilder.append(SLASH_DELIM).append(mNodes.get(AddressField.COUNTRY))
- .append(SLASH_DELIM).append(mScriptType.name().toLowerCase())
- .append(SLASH_DELIM).append(DEFAULT_LANGUAGE);
- }
+ keyBuilder.append(SLASH_DELIM).append(nodes.get(field));
}
-
- return keyBuilder.toString();
+ }
+ } else {
+ if (nodes.containsKey(AddressField.COUNTRY)) {
+ // Example key. E.g., "examples/TW/local/_default".
+ keyBuilder.append(SLASH_DELIM).append(nodes.get(AddressField.COUNTRY))
+ .append(SLASH_DELIM).append(scriptType.name().toLowerCase())
+ .append(SLASH_DELIM).append(DEFAULT_LANGUAGE);
+ }
}
- /**
- * Gets a lookup key as a plain text string., e.g., "data/US/CA".
- */
- @Override
- public String toString() {
- return mKeyString;
+ return keyBuilder.toString();
+ }
+
+ /**
+ * Gets a lookup key as a plain text string., e.g., "data/US/CA".
+ */
+ @Override
+ public String toString() {
+ return keyString;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (obj.getClass() != this.getClass())) {
+ return false;
}
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if ((obj == null) || (obj.getClass() != this.getClass())) {
- return false;
- }
+ return ((LookupKey) obj).toString().equals(keyString);
+ }
- return ((LookupKey) obj).toString().equals(mKeyString);
- }
+ @Override
+ public int hashCode() {
+ return keyString.hashCode();
+ }
- @Override
- public int hashCode() {
- return mKeyString.hashCode();
+ static boolean hasValidKeyPrefix(String key) {
+ for (KeyType type : KeyType.values()) {
+ if (key.startsWith(type.name().toLowerCase())) {
+ return true;
+ }
}
+ return false;
+ }
- static boolean hasValidKeyPrefix(String key) {
- for (KeyType type : KeyType.values()) {
- if (key.startsWith(type.name().toLowerCase())) {
- return true;
- }
- }
- return false;
- }
+ /**
+ * Builds lookup keys.
+ */
+ static class Builder {
- /**
- * Builds lookup keys.
- */
- static class Builder {
+ private KeyType keyType;
- private KeyType keyType;
+ // Default to LOCAL script.
- // Default to LOCAL script.
+ private ScriptType script = ScriptType.LOCAL;
- private ScriptType script = ScriptType.LOCAL;
+ private Map<AddressField, String> nodes = new EnumMap<AddressField, String>(
+ AddressField.class);
- private Map<AddressField, String> nodes = new EnumMap<AddressField, String>(
- AddressField.class);
+ private String languageCode;
- private String languageCode;
+ /**
+ * Creates a new builder for the specified key type. keyType cannot be null.
+ */
+ Builder(KeyType keyType) {
+ this.keyType = keyType;
+ }
- /**
- * Creates a new builder for the specified key type. keyType cannot be null.
- */
- Builder(KeyType keyType) {
- this.keyType = keyType;
+ /**
+ * Creates a new builder for the specified key. oldKey cannot be null.
+ */
+ Builder(LookupKey oldKey) {
+ this.keyType = oldKey.keyType;
+ this.script = oldKey.scriptType;
+ this.languageCode = oldKey.languageCode;
+ for (AddressField field : HIERARCHY) {
+ if (!oldKey.nodes.containsKey(field)) {
+ break;
}
+ this.nodes.put(field, oldKey.nodes.get(field));
+ }
+ }
- /**
- * Creates a new builder for the specified key. oldKey cannot be null.
- */
- Builder(LookupKey oldKey) {
- this.keyType = oldKey.mKeyType;
- this.script = oldKey.mScriptType;
- this.languageCode = oldKey.mLanguageCode;
- for (AddressField field : HIERARCHY) {
- if (!oldKey.mNodes.containsKey(field)) {
- break;
- }
- this.nodes.put(field, oldKey.mNodes.get(field));
+ /**
+ * Builds the {@link LookupKey} with the input key string. Input string has to represent
+ * either a {@link KeyType#DATA} key or a {@link KeyType#EXAMPLES} key. Also, key hierarchy
+ * deeper than {@link AddressField#DEPENDENT_LOCALITY} is not allowed. Notice that if any
+ * node in the hierarchy is empty, all the descendant nodes' values will be neglected. For
+ * example, input string "data/US//Mt View" will become "data/US".
+ *
+ * @param keyString e.g., "data/US/CA"
+ */
+ Builder(String keyString) {
+ String[] parts = keyString.split(SLASH_DELIM);
+ // Check some pre-conditions.
+ if (!parts[0].equals(KeyType.DATA.name().toLowerCase()) &&
+ !parts[0].equals(KeyType.EXAMPLES.name().toLowerCase())) {
+ throw new RuntimeException("Wrong key type: " + parts[0]);
+ }
+ if (parts.length > HIERARCHY.length + 1) {
+ throw new RuntimeException(
+ "input key '" + keyString + "' deeper than supported hierarchy");
+ }
+ if (parts[0].equals("data")) {
+ keyType = KeyType.DATA;
+
+ // Parses country and language info.
+ if (parts.length > 1) {
+ String substr = Util.trimToNull(parts[1]);
+ if (substr.contains(DASH_DELIM)) {
+ String[] s = substr.split(DASH_DELIM);
+ if (s.length != 2) {
+ throw new RuntimeException(
+ "Wrong format: Substring should be country "
+ + "code--language code");
}
+ substr = s[0];
+ languageCode = s[1];
+ }
+ this.nodes.put(HIERARCHY[0], substr);
}
- /**
- * Builds the {@link LookupKey} with the input key string. Input string has to represent
- * either a {@link KeyType#DATA} key or a {@link KeyType#EXAMPLES} key. Also, key hierarchy
- * deeper than {@link AddressField#DEPENDENT_LOCALITY} is not allowed. Notice that if any
- * node in the hierarchy is empty, all the descendant nodes' values will be neglected. For
- * example, input string "data/US//Mt View" will become "data/US".
- *
- * @param keyString e.g., "data/US/CA"
- */
- Builder(String keyString) {
- String[] parts = keyString.split(SLASH_DELIM);
- // Check some pre-conditions.
- if (!parts[0].equals(KeyType.DATA.name().toLowerCase()) &&
- !parts[0].equals(KeyType.EXAMPLES.name().toLowerCase())) {
- throw new RuntimeException("Wrong key type: " + parts[0]);
- }
- if (parts.length > HIERARCHY.length + 1) {
- throw new RuntimeException(
- "input key '" + keyString + "' deeper than supported hierarchy");
- }
- if (parts[0].equals("data")) {
- keyType = KeyType.DATA;
-
- // Parses country and language info.
- if (parts.length > 1) {
- String substr = Util.trimToNull(parts[1]);
- if (substr.contains(DASH_DELIM)) {
- String[] s = substr.split(DASH_DELIM);
- if (s.length != 2) {
- throw new RuntimeException(
- "Wrong format: Substring should be country "
- + "code--language code");
- }
- substr = s[0];
- languageCode = s[1];
- }
- this.nodes.put(HIERARCHY[0], substr);
- }
-
- // Parses sub-country info.
- if (parts.length > 2) {
- for (int i = 2; i < parts.length; ++i) {
- String substr = Util.trimToNull(parts[i]);
- if (substr == null) {
- break;
- }
- this.nodes.put(HIERARCHY[i - 1], substr);
- }
- }
- } else if (parts[0].equals("examples")) {
- keyType = KeyType.EXAMPLES;
-
- // Parses country info.
- if (parts.length > 1) {
- this.nodes.put(AddressField.COUNTRY, parts[1]);
- }
-
- // Parses script types.
- if (parts.length > 2) {
- String scriptStr = parts[2];
- if (scriptStr.equals("local")) {
- this.script = ScriptType.LOCAL;
- } else if (scriptStr.equals("latin")) {
- this.script = ScriptType.LATIN;
- } else {
- throw new RuntimeException("Script type has to be either latin or local.");
- }
- }
-
- // Parses language code. Example: "zh_Hant" in
- // "examples/TW/local/zH_Hant".
- if (parts.length > 3 && !parts[3].equals(DEFAULT_LANGUAGE)) {
- languageCode = parts[3];
- }
+ // Parses sub-country info.
+ if (parts.length > 2) {
+ for (int i = 2; i < parts.length; ++i) {
+ String substr = Util.trimToNull(parts[i]);
+ if (substr == null) {
+ break;
}
+ this.nodes.put(HIERARCHY[i - 1], substr);
+ }
}
+ } else if (parts[0].equals("examples")) {
+ keyType = KeyType.EXAMPLES;
- Builder setLanguageCode(String languageCode) {
- this.languageCode = languageCode;
- return this;
+ // Parses country info.
+ if (parts.length > 1) {
+ this.nodes.put(AddressField.COUNTRY, parts[1]);
}
- /**
- * Sets key using {@link AddressData}. Notice that if any node in the hierarchy is empty,
- * all the descendant nodes' values will be neglected. For example, the following address
- * misses {@link AddressField#ADMIN_AREA}, thus its data key will be "data/US".
- *
- * <p> country: US<br> administrative area: null<br> locality: Mt. View </p>
- */
- Builder setAddressData(AddressData data) {
- languageCode = data.getLanguageCode();
- if (languageCode != null) {
- if (Util.isExplicitLatinScript(languageCode)) {
- script = ScriptType.LATIN;
- }
- }
-
- if (data.getPostalCountry() == null) {
- return this;
- }
- this.nodes.put(AddressField.COUNTRY, data.getPostalCountry());
+ // Parses script types.
+ if (parts.length > 2) {
+ String scriptStr = parts[2];
+ if (scriptStr.equals("local")) {
+ this.script = ScriptType.LOCAL;
+ } else if (scriptStr.equals("latin")) {
+ this.script = ScriptType.LATIN;
+ } else {
+ throw new RuntimeException("Script type has to be either latin or local.");
+ }
+ }
- if (data.getAdministrativeArea() == null) {
- return this;
- }
- this.nodes.put(AddressField.ADMIN_AREA, data.getAdministrativeArea());
+ // Parses language code. Example: "zh_Hant" in
+ // "examples/TW/local/zH_Hant".
+ if (parts.length > 3 && !parts[3].equals(DEFAULT_LANGUAGE)) {
+ languageCode = parts[3];
+ }
+ }
+ }
- if (data.getLocality() == null) {
- return this;
- }
- this.nodes.put(AddressField.LOCALITY, data.getLocality());
+ Builder setLanguageCode(String languageCode) {
+ this.languageCode = languageCode;
+ return this;
+ }
- if (data.getDependentLocality() == null) {
- return this;
- }
- this.nodes.put(AddressField.DEPENDENT_LOCALITY, data.getDependentLocality());
- return this;
+ /**
+ * Sets key using {@link AddressData}. Notice that if any node in the hierarchy is empty,
+ * all the descendant nodes' values will be neglected. For example, the following address
+ * misses {@link AddressField#ADMIN_AREA}, thus its data key will be "data/US".
+ *
+ * <p> country: US<br> administrative area: null<br> locality: Mt. View </p>
+ */
+ Builder setAddressData(AddressData data) {
+ languageCode = data.getLanguageCode();
+ if (languageCode != null) {
+ if (Util.isExplicitLatinScript(languageCode)) {
+ script = ScriptType.LATIN;
}
+ }
+
+ if (data.getPostalCountry() == null) {
+ return this;
+ }
+ this.nodes.put(AddressField.COUNTRY, data.getPostalCountry());
+
+ if (data.getAdministrativeArea() == null) {
+ return this;
+ }
+ this.nodes.put(AddressField.ADMIN_AREA, data.getAdministrativeArea());
+
+ if (data.getLocality() == null) {
+ return this;
+ }
+ this.nodes.put(AddressField.LOCALITY, data.getLocality());
+
+ if (data.getDependentLocality() == null) {
+ return this;
+ }
+ this.nodes.put(AddressField.DEPENDENT_LOCALITY, data.getDependentLocality());
+ return this;
+ }
- LookupKey build() {
- return new LookupKey(this);
- }
+ LookupKey build() {
+ return new LookupKey(this);
}
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/NotifyingListener.java b/java/src/com/android/i18n/addressinput/NotifyingListener.java
index 60a5f74..038a069 100644
--- a/java/src/com/android/i18n/addressinput/NotifyingListener.java
+++ b/java/src/com/android/i18n/addressinput/NotifyingListener.java
@@ -20,34 +20,34 @@ package com.android.i18n.addressinput;
* A helper class to let the calling thread wait until loading has finished.
*/
public class NotifyingListener implements DataLoadListener {
- private Object mSleeper;
- private boolean mDone;
+ private Object sleeper;
+ private boolean done;
- NotifyingListener(Object sleeper) {
- mSleeper = sleeper;
- mDone = false;
- }
+ NotifyingListener(Object sleeper) {
+ this.sleeper = sleeper;
+ this.done = false;
+ }
- @Override
- public void dataLoadingBegin() {
- }
+ @Override
+ public void dataLoadingBegin() {
+ }
- @Override
- public void dataLoadingEnd() {
- synchronized (this) {
- mDone = true;
- }
- synchronized (mSleeper) {
- mSleeper.notify();
- }
+ @Override
+ public void dataLoadingEnd() {
+ synchronized (this) {
+ done = true;
}
+ synchronized (sleeper) {
+ sleeper.notify();
+ }
+ }
- void waitLoadingEnd() throws InterruptedException {
- synchronized (this) {
- if (mDone) return;
- }
- synchronized (mSleeper) {
- mSleeper.wait();
- }
+ void waitLoadingEnd() throws InterruptedException {
+ synchronized (this) {
+ if (done) return;
+ }
+ synchronized (sleeper) {
+ sleeper.wait();
}
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/RegionData.java b/java/src/com/android/i18n/addressinput/RegionData.java
index 2b82c0a..62d3821 100644
--- a/java/src/com/android/i18n/addressinput/RegionData.java
+++ b/java/src/com/android/i18n/addressinput/RegionData.java
@@ -21,87 +21,87 @@ package com.android.i18n.addressinput;
*/
class RegionData {
- private String mKey;
- private String mName;
+ private String key;
+ private String name;
- /**
- * Create a new RegionData object.
- */
- private RegionData() {
- }
+ /**
+ * Create a new RegionData object.
+ */
+ private RegionData() {
+ }
- /**
- * Copy constructor. data should not be null.
- *
- * @param data A populated instance of RegionData
- */
- private RegionData(RegionData data) {
- Util.checkNotNull(data);
- mKey = data.mKey;
- mName = data.mName;
- }
+ /**
+ * Copy constructor. data should not be null.
+ *
+ * @param data A populated instance of RegionData
+ */
+ private RegionData(RegionData data) {
+ Util.checkNotNull(data);
+ key = data.key;
+ name = data.name;
+ }
- /**
- * Gets the key of the region. For example, California's key is "CA".
- */
- String getKey() {
- return mKey;
- }
+ /**
+ * Gets the key of the region. For example, California's key is "CA".
+ */
+ String getKey() {
+ return key;
+ }
- /**
- * Gets the name. Returns null if not specified.
- */
- String getName() {
- return mName;
+ /**
+ * Gets the name. Returns null if not specified.
+ */
+ String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the best display name. Returns the name if this is not null, otherwise the key.
+ */
+ public String getDisplayName() {
+ return (name != null) ? name : key;
+ }
+
+ /**
+ * Checks if the input subkey is the name (in Latin or local script) of the region. Returns
+ * false if subkey is not a valid name for the region, or the input subkey is null.
+ *
+ * @param subkey a string that refers to the name of a geo location. Like "California", "CA", or
+ * "Mountain View". Names in the local script are also supported.
+ */
+ boolean isValidName(String subkey) {
+ if (subkey == null) {
+ return false;
+ }
+ if (subkey.equalsIgnoreCase(key) || subkey.equalsIgnoreCase(name)) {
+ return true;
}
+ return false;
+ }
- /**
- * Gets the best display name. Returns the name if this is not null, otherwise the key.
- */
- public String getDisplayName() {
- return (mName != null) ? mName : mKey;
+ /**
+ * A builder class to facilitate the creation of RegionData objects.
+ */
+ static class Builder {
+ RegionData data = new RegionData();
+
+ RegionData build() {
+ return new RegionData(data);
}
- /**
- * Checks if the input subkey is the name (in Latin or local script) of the region. Returns
- * false if subkey is not a valid name for the region, or the input subkey is null.
- *
- * @param subkey a string that refers to the name of a geo location. Like "California", "CA", or
- * "Mountain View". Names in the local script are also supported.
- */
- boolean isValidName(String subkey) {
- if (subkey == null) {
- return false;
- }
- if (subkey.equalsIgnoreCase(mKey) || subkey.equalsIgnoreCase(mName)) {
- return true;
- }
- return false;
+ Builder setKey(String key) {
+ Util.checkNotNull(key, "Key should not be null.");
+ data.key = key;
+ return this;
}
/**
- * A builder class to facilitate the creation of RegionData objects.
+ * Sets name of the region. For example, "California". If the name is an empty string, sets
+ * it to null.
*/
- static class Builder {
- RegionData mData = new RegionData();
-
- RegionData build() {
- return new RegionData(mData);
- }
-
- Builder setKey(String key) {
- Util.checkNotNull(key, "Key should not be null.");
- mData.mKey = key;
- return this;
- }
-
- /**
- * Sets name of the region. For example, "California". If the name is an empty string, sets
- * it to null.
- */
- Builder setName(String name) {
- mData.mName = Util.trimToNull(name);
- return this;
- }
+ Builder setName(String name) {
+ data.name = Util.trimToNull(name);
+ return this;
}
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/RegionDataConstants.java b/java/src/com/android/i18n/addressinput/RegionDataConstants.java
index 4f4c5b7..bd453a8 100644
--- a/java/src/com/android/i18n/addressinput/RegionDataConstants.java
+++ b/java/src/com/android/i18n/addressinput/RegionDataConstants.java
@@ -29,1283 +29,1287 @@ import java.util.Map;
*/
class RegionDataConstants {
- private static final Map<String, String> COUNTRY_FORMAT_MAP =
- new HashMap<String, String>();
+ private static final Map<String, String> COUNTRY_FORMAT_MAP =
+ new HashMap<String, String>();
- private enum RegionDataEnum {
+ private enum RegionDataEnum {
- AC(new String[]{
- "name", "ASCENSION ISLAND",
- }),
- AD(new String[]{
- "name", "ANDORRA",
- "lang", "ca",
- "languages", "ca",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "require", "A",
- }),
- AE(new String[]{
- "name", "UNITED ARAB EMIRATES",
- "fmt", "%N%n%O%n%A%n%C",
- "require", "AC",
- }),
- AF(new String[]{
- "name", "AFGHANISTAN",
- }),
- AG(new String[]{
- "name", "ANTIGUA AND BARBUDA",
- "require", "A",
- }),
- AI(new String[]{
- "name", "ANGUILLA",
- }),
- AL(new String[]{
- "name", "ALBANIA",
- }),
- AM(new String[]{
- "name", "ARMENIA",
- "lang", "hy",
- "languages", "hy",
- "fmt", "%N%n%O%n%A%n%Z%n%C%n%S",
- "lfmt", "%N%n%O%n%A%n%Z%n%C%n%S",
- }),
- AN(new String[]{
- "name", "NETHERLANDS ANTILLES",
- }),
- AO(new String[]{
- "name", "ANGOLA",
- }),
- AQ(new String[]{
- "name", "ANTARCTICA",
- }),
- AR(new String[]{
- "name", "ARGENTINA",
- "lang", "es",
- "languages", "es",
- "fmt", "%N%n%O%n%A%n%Z %C%n%S",
- "upper", "ACZ",
- "state_name_type", "state",
- }),
- AS(new String[]{
- "name", "AMERICAN SAMOA",
- "fmt", "%N%n%O%n%A%n%C %S %Z",
- "require", "ACSZ",
- "upper", "ACNOS",
- "zip_name_type", "zip",
- "state_name_type", "state",
- }),
- AT(new String[]{
- "name", "AUSTRIA",
- "fmt", "%O%n%N%n%A%n%Z %C",
- "require", "ACZ",
- }),
- AU(new String[]{
- "name", "AUSTRALIA",
- "lang", "en",
- "languages", "en",
- "fmt", "%O%n%N%n%A%n%C %S %Z",
- "require", "ACSZ",
- "upper", "CS",
- "state_name_type", "state",
- }),
- AW(new String[]{
- "name", "ARUBA",
- }),
- AX(new String[]{
- "name", "FINLAND",
- "fmt", "%O%n%N%n%A%nAX-%Z %C%n\u00C5LAND",
- "require", "ACZ",
- "postprefix", "AX-",
- }),
- AZ(new String[]{
- "name", "AZERBAIJAN",
- "fmt", "%N%n%O%n%A%nAZ %Z %C",
- "postprefix", "AZ ",
- }),
- BA(new String[]{
- "name", "BOSNIA AND HERZEGOVINA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- BB(new String[]{
- "name", "BARBADOS",
- "state_name_type", "parish",
- }),
- BD(new String[]{
- "name", "BANGLADESH",
- "fmt", "%N%n%O%n%A%n%C - %Z",
- }),
- BE(new String[]{
- "name", "BELGIUM",
- "fmt", "%O%n%N%n%A%n%Z %C",
- "require", "ACZ",
- }),
- BF(new String[]{
- "name", "BURKINA FASO",
- "fmt", "%N%n%O%n%A%n%C %X",
- }),
- BG(new String[]{
- "name", "BULGARIA (REP.)",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- BH(new String[]{
- "name", "BAHRAIN",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- BI(new String[]{
- "name", "BURUNDI",
- }),
- BJ(new String[]{
- "name", "BENIN",
- "upper", "AC",
- }),
- BL(new String[]{
- "name", "SAINT BARTHELEMY",
- "fmt", "%O%n%N%n%A%n%Z %C %X",
- "upper", "ACX",
- "require", "ACZ",
- }),
- BM(new String[]{
- "name", "BERMUDA",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- BN(new String[]{
- "name", "BRUNEI DARUSSALAM",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- BO(new String[]{
- "name", "BOLIVIA",
- "upper", "AC",
- }),
- BR(new String[]{
- "name", "BRAZIL",
- "lang", "pt",
- "languages", "pt",
- "fmt", "%O%n%N%n%A%n%C-%S%n%Z",
- "require", "ASCZ",
- "upper", "CS",
- "state_name_type", "state",
- }),
- BS(new String[]{
- "name", "BAHAMAS",
- "lang", "en",
- "languages", "en",
- "fmt", "%N%n%O%n%A%n%C, %S",
- "state_name_type", "island",
- }),
- BT(new String[]{
- "name", "BHUTAN",
- }),
- BV(new String[]{
- "name", "BOUVET ISLAND",
- }),
- BW(new String[]{
- "name", "BOTSWANA",
- }),
- BY(new String[]{
- "name", "BELARUS",
- "fmt", "%S%n%Z %C %X%n%A%n%O%n%N",
- }),
- BZ(new String[]{
- "name", "BELIZE",
- }),
- CA(new String[]{
- "name", "CANADA",
- "lang", "en",
- "languages", "en~fr",
- "fmt", "%N%n%O%n%A%n%C %S %Z",
- "require", "ACSZ",
- "upper", "ACNOSZ",
- }),
- CC(new String[]{
- "name", "COCOS (KEELING) ISLANDS",
- "fmt", "%O%n%N%n%A%n%C %S %Z",
- "upper", "CS",
- }),
- CD(new String[]{
- "name", "CONGO (DEM. REP.)",
- "fmt", "%N%n%O%n%A%n%C %X",
- }),
- CF(new String[]{
- "name", "CENTRAL AFRICAN REPUBLIC",
- }),
- CG(new String[]{
- "name", "CONGO (REP.)",
- }),
- CH(new String[]{
- "name", "SWITZERLAND",
- "lang", "de",
- "languages", "de~fr~it",
- "fmt", "%O%n%N%n%A%nCH-%Z %C",
- "require", "ACZ",
- "upper", "",
- "postprefix", "CH-",
- }),
- CI(new String[]{
- "name", "COTE D'IVOIRE",
- "fmt", "%N%n%O%n%X %A %C %X",
- }),
- CK(new String[]{
- "name", "COOK ISLANDS",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- CL(new String[]{
- "name", "CHILE",
- "lang", "es",
- "languages", "es",
- "fmt", "%N%n%O%n%A%n%Z %C%n%S",
- "state_name_type", "state",
- }),
- CM(new String[]{
- "name", "CAMEROON",
- }),
- CN(new String[]{
- "name", "P.R. CHINA",
- "lang", "zh-hans",
- "languages", "zh-hans",
- "fmt", "%Z%n%S%C%D%n%A%n%O%n%N",
- "lfmt", "%N%n%O%n%A%n%D%n%C%n%S, %Z",
- "require", "ACSZ",
- "upper", "S",
- }),
- CO(new String[]{
- "name", "COLOMBIA",
- "fmt", "%N%n%O%n%A%n%C, %S",
- }),
- CR(new String[]{
- "name", "COSTA RICA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- CS(new String[]{
- "name", "SERBIA AND MONTENEGRO",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- CV(new String[]{
- "name", "CAPE VERDE",
- "lang", "pt",
- "languages", "pt",
- "fmt", "%N%n%O%n%A%n%Z %C%n%S",
- "state_name_type", "island",
- }),
- CX(new String[]{
- "name", "CHRISTMAS ISLAND",
- "fmt", "%O%n%N%n%A%n%C %S %Z",
- "upper", "CS",
- }),
- CY(new String[]{
- "name", "CYPRUS",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- CZ(new String[]{
- "name", "CZECH REP.",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- DE(new String[]{
- "name", "GERMANY",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "require", "ACZ",
- }),
- DJ(new String[]{
- "name", "DJIBOUTI",
- }),
- DK(new String[]{
- "name", "DENMARK",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "require", "ACZ",
- }),
- DM(new String[]{
- "name", "DOMINICA",
- }),
- DO(new String[]{
- "name", "DOMINICAN REP.",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- DZ(new String[]{
- "name", "ALGERIA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- EC(new String[]{
- "name", "ECUADOR",
- "fmt", "%N%n%O%n%A%n%Z%n%C",
- "upper", "CZ",
- }),
- EE(new String[]{
- "name", "ESTONIA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- EG(new String[]{
- "name", "EGYPT",
- "fmt", "%N%n%O%n%A%n%C%n%S%n%Z",
- "lfmt", "%N%n%O%n%A%n%C%n%S%n%Z",
- }),
- EH(new String[]{
- "name", "WESTERN SAHARA",
- }),
- ER(new String[]{
- "name", "ERITREA",
- }),
- ES(new String[]{
- "name", "SPAIN",
- "lang", "es",
- "languages", "es",
- "fmt", "%N%n%O%n%A%n%Z %C %S",
- "require", "ACSZ",
- "upper", "CS",
- }),
- ET(new String[]{
- "name", "ETHIOPIA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- FI(new String[]{
- "name", "FINLAND",
- "fmt", "%O%n%N%n%A%nFI-%Z %C",
- "require", "ACZ",
- "postprefix", "FI-",
- }),
- FJ(new String[]{
- "name", "FIJI",
- }),
- FK(new String[]{
- "name", "FALKLAND ISLANDS (MALVINAS)",
- "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
- "require", "ACZ",
- "upper", "CZ",
- }),
- FM(new String[]{
- "name", "MICRONESIA (Federated State of)",
- "fmt", "%N%n%O%n%A%n%C %S %Z",
- "require", "ACSZ",
- "upper", "ACNOS",
- "zip_name_type", "zip",
- "state_name_type", "state",
- }),
- FO(new String[]{
- "name", "FAROE ISLANDS",
- "fmt", "%N%n%O%n%A%nFO%Z %C",
- "postprefix", "FO",
- }),
- FR(new String[]{
- "name", "FRANCE",
- "fmt", "%O%n%N%n%A%n%Z %C %X",
- "require", "ACZ",
- "upper", "CX",
- }),
- GA(new String[]{
- "name", "GABON",
- }),
- GB(new String[]{
- "name", "UNITED KINGDOM",
- "fmt", "%N%n%O%n%A%n%C%n%S%n%Z",
- "require", "ACZ",
- "upper", "CZ",
- "state_name_type", "county",
- }),
- GD(new String[]{
- "name", "GRENADA (WEST INDIES)",
- }),
- GE(new String[]{
- "name", "GEORGIA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- GF(new String[]{
- "name", "FRENCH GUIANA",
- "fmt", "%O%n%N%n%A%n%Z %C %X",
- "require", "ACZ",
- "upper", "ACX",
- }),
- GG(new String[]{
- "name", "CHANNEL ISLANDS",
- "fmt", "%N%n%O%n%A%n%X%n%C%nGUERNSEY%n%Z",
- "require", "ACZ",
- "upper", "CZ",
- }),
- GH(new String[]{
- "name", "GHANA",
- }),
- GI(new String[]{
- "name", "GIBRALTAR",
- "fmt", "%N%n%O%n%A",
- "require", "A",
- }),
- GL(new String[]{
- "name", "GREENLAND",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "require", "ACZ",
- }),
- GM(new String[]{
- "name", "GAMBIA",
- }),
- GN(new String[]{
- "name", "GUINEA",
- "fmt", "%N%n%O%n%Z %A %C",
- }),
- GP(new String[]{
- "name", "GUADELOUPE",
- "fmt", "%O%n%N%n%A%n%Z %C %X",
- "require", "ACZ",
- "upper", "ACX",
- }),
- GQ(new String[]{
- "name", "EQUATORIAL GUINEA",
- }),
- GR(new String[]{
- "name", "GREECE",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "require", "ACZ",
- }),
- GS(new String[]{
- "name", "SOUTH GEORGIA",
- "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
- "require", "ACZ",
- "upper", "CZ",
- }),
- GT(new String[]{
- "name", "GUATEMALA",
- "fmt", "%N%n%O%n%A%n%Z- %C",
- }),
- GU(new String[]{
- "name", "GUAM",
- "fmt", "%N%n%O%n%A%n%C %S %Z",
- "require", "ACSZ",
- "upper", "ACNOS",
- "zip_name_type", "zip",
- "state_name_type", "state",
- }),
- GW(new String[]{
- "name", "GUINEA-BISSAU",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- GY(new String[]{
- "name", "GUYANA",
- }),
- HK(new String[]{
- "name", "HONG KONG",
- "lang", "zh",
- "languages", "zh",
- "fmt", "%S%n%A%n%O%n%N",
- "lfmt", "%N%n%O%n%A%n%S",
- "require", "AS",
- "upper", "S",
- "state_name_type", "area",
- }),
- HM(new String[]{
- "name", "HEARD AND MCDONALD ISLANDS",
- "fmt", "%O%n%N%n%A%n%C %S %Z",
- "upper", "CS",
- }),
- HN(new String[]{
- "name", "HONDURAS",
- "fmt", "%N%n%O%n%A%n%C, %S%n%Z",
- "require", "ACS",
- }),
- HR(new String[]{
- "name", "CROATIA",
- "fmt", "%N%n%O%n%A%nHR-%Z %C",
- "postprefix", "HR-",
- }),
- HT(new String[]{
- "name", "HAITI",
- "fmt", "%N%n%O%n%A%nHT%Z %C %X",
- "postprefix", "HT",
- }),
- HU(new String[]{
- "name", "HUNGARY (Rep.)",
- "fmt", "%N%n%O%n%C%n%A%n%Z",
- "upper", "ACNO",
- }),
- ID(new String[]{
- "name", "INDONESIA",
- "fmt", "%N%n%O%n%A%n%C %Z%n%S",
- }),
- IE(new String[]{
- "name", "IRELAND",
- "lang", "en",
- "languages", "en",
- "fmt", "%N%n%O%n%A%n%C%n%S",
- "state_name_type", "county",
- }),
- IL(new String[]{
- "name", "ISRAEL",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- IM(new String[]{
- "name", "ISLE OF MAN",
- "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
- "require", "ACZ",
- "upper", "CZ",
- }),
- IN(new String[]{
- "name", "INDIA",
- "lang", "en",
- "languages", "en",
- "fmt", "%N%n%O%n%A%n%C %Z%n%S",
- "require", "ACSZ",
- "state_name_type", "state",
- }),
- IO(new String[]{
- "name", "BRITISH INDIAN OCEAN TERRITORY",
- "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
- "require", "ACZ",
- "upper", "CZ",
- }),
- IQ(new String[]{
- "name", "IRAQ",
- "fmt", "%O%n%N%n%A%n%C, %S%n%Z",
- "require", "ACS",
- "upper", "CS",
- }),
- IS(new String[]{
- "name", "ICELAND",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- IT(new String[]{
- "name", "ITALY",
- "lang", "it",
- "languages", "it",
- "fmt", "%N%n%O%n%A%n%Z %C %S",
- "require", "ACSZ",
- "upper", "CS",
- }),
- JE(new String[]{
- "name", "CHANNEL ISLANDS",
- "fmt", "%N%n%O%n%A%n%X%n%C%nJERSEY%n%Z",
- "require", "ACZ",
- "upper", "CZ",
- }),
- JM(new String[]{
- "name", "JAMAICA",
- "lang", "en",
- "languages", "en",
- "fmt", "%N%n%O%n%A%n%C%n%S %X",
- "require", "ACS",
- "state_name_type", "parish",
- }),
- JO(new String[]{
- "name", "JORDAN",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- JP(new String[]{
- "name", "JAPAN",
- "lang", "ja",
- "languages", "ja",
- "fmt", "\u3012%Z%n%S%C%n%A%n%O%n%N",
- "lfmt", "%N%n%O%n%A%n%C, %S%n%Z",
- "require", "ACSZ",
- "upper", "S",
- "state_name_type", "prefecture",
- }),
- KE(new String[]{
- "name", "KENYA",
- "fmt", "%N%n%O%n%A%n%C%n%Z",
- }),
- KG(new String[]{
- "name", "KYRGYZSTAN",
- "fmt", "%Z %C %X%n%A%n%O%n%N",
- }),
- KH(new String[]{
- "name", "CAMBODIA",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- KI(new String[]{
- "name", "KIRIBATI",
- "fmt", "%N%n%O%n%A%n%S%n%C",
- "upper", "ACNOS",
- "state_name_type", "island",
- }),
- KM(new String[]{
- "name", "COMOROS",
- "upper", "AC",
- }),
- KN(new String[]{
- "name", "SAINT KITTS AND NEVIS",
- "lang", "en",
- "languages", "en",
- "fmt", "%N%n%O%n%A%n%C, %S",
- "require", "ACS",
- "state_name_type", "island",
- }),
- KR(new String[]{
- "name", "KOREA (REP.)",
- "lang", "ko",
- "languages", "ko",
- "fmt", "%S %C%D%n%A%n%O%n%N%nSEOUL %Z",
- "lfmt", "%N%n%O%n%A%n%D%n%C%n%S%nSEOUL %Z",
- "require", "ACSZ",
- "upper", "Z",
- "state_name_type", "do_si",
- }),
- KW(new String[]{
- "name", "KUWAIT",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- KY(new String[]{
- "name", "CAYMAN ISLANDS",
- "lang", "en",
- "languages", "en",
- "fmt", "%N%n%O%n%A%n%S",
- "require", "AS",
- "state_name_type", "island",
- }),
- KZ(new String[]{
- "name", "KAZAKHSTAN",
- "fmt", "%Z%n%S%n%C%n%A%n%O%n%N",
- }),
- LA(new String[]{
- "name", "LAO (PEOPLE'S DEM. REP.)",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- LB(new String[]{
- "name", "LEBANON",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- LC(new String[]{
- "name", "SAINT LUCIA",
- }),
- LI(new String[]{
- "name", "LIECHTENSTEIN",
- "fmt", "%O%n%N%n%A%nFL-%Z %C",
- "require", "ACZ",
- "postprefix", "FL-",
- }),
- LK(new String[]{
- "name", "SRI LANKA",
- "fmt", "%N%n%O%n%A%n%C%n%Z",
- }),
- LR(new String[]{
- "name", "LIBERIA",
- "fmt", "%N%n%O%n%A%n%Z %C %X",
- }),
- LS(new String[]{
- "name", "LESOTHO",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- LT(new String[]{
- "name", "LITHUANIA",
- "fmt", "%O%n%N%n%A%nLT-%Z %C",
- "postprefix", "LT-",
- }),
- LU(new String[]{
- "name", "LUXEMBOURG",
- "fmt", "%O%n%N%n%A%nL-%Z %C",
- "require", "ACZ",
- "postprefix", "L-",
- }),
- LV(new String[]{
- "name", "LATVIA",
- "fmt", "%N%n%O%n%A%n%C, %Z",
- }),
- LY(new String[]{
- "name", "LIBYA",
- }),
- MA(new String[]{
- "name", "MOROCCO",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- MC(new String[]{
- "name", "MONACO",
- "fmt", "%N%n%O%n%A%nMC-%Z %C %X",
- "postprefix", "MC-",
- }),
- MD(new String[]{
- "name", "Rep. MOLDOVA",
- "fmt", "%N%n%O%n%A%nMD-%Z %C",
- "postprefix", "MD-",
- }),
- ME(new String[]{
- "name", "MONTENEGRO",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- MF(new String[]{
- "name", "SAINT MARTIN",
- "fmt", "%O%n%N%n%A%n%Z %C %X",
- "upper", "ACX",
- "require", "ACZ",
- }),
- MG(new String[]{
- "name", "MADAGASCAR",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- MH(new String[]{
- "name", "MARSHALL ISLANDS",
- "fmt", "%N%n%O%n%A%n%C %S %Z",
- "require", "ACSZ",
- "upper", "ACNOS",
- "zip_name_type", "zip",
- "state_name_type", "state",
- }),
- MK(new String[]{
- "name", "MACEDONIA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- ML(new String[]{
- "name", "MALI",
- }),
- MN(new String[]{
- "name", "MONGOLIA",
- "fmt", "%N%n%O%n%A%n%S %C-%X%n%Z",
- }),
- MO(new String[]{
- "name", "MACAO",
- "lang", "zh-hant",
- "languages", "zh-hant",
- "fmt", "%A%n%O%n%N",
- "lfmt", "%N%n%O%n%A",
- "require", "A",
- }),
- MP(new String[]{
- "name", "NORTHERN MARIANA ISLANDS",
- "fmt", "%N%n%O%n%A%n%C %S %Z",
- "require", "ACSZ",
- "upper", "ACNOS",
- "zip_name_type", "zip",
- "state_name_type", "state",
- }),
- MQ(new String[]{
- "name", "MARTINIQUE",
- "fmt", "%O%n%N%n%A%n%Z %C %X",
- "require", "ACZ",
- "upper", "ACX",
- }),
- MR(new String[]{
- "name", "MAURITANIA",
- "upper", "AC",
- }),
- MS(new String[]{
- "name", "MONTSERRAT",
- }),
- MT(new String[]{
- "name", "MALTA",
- "fmt", "%N%n%O%n%A%n%C %Z",
- "upper", "CZ",
- }),
- MU(new String[]{
- "name", "MAURITIUS",
- "fmt", "%N%n%O%n%A%n%Z%n%C",
- "upper", "CZ",
- }),
- MV(new String[]{
- "name", "MALDIVES",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- MW(new String[]{
- "name", "MALAWI",
- "fmt", "%N%n%O%n%A%n%C %X",
- }),
- MX(new String[]{
- "name", "MEXICO",
- "lang", "es",
- "languages", "es",
- "fmt", "%N%n%O%n%A%n%Z %C, %S",
- "require", "ACZ",
- "upper", "CSZ",
- "state_name_type", "state",
- }),
- MY(new String[]{
- "name", "MALAYSIA",
- "lang", "ms",
- "languages", "ms",
- "fmt", "%N%n%O%n%A%n%Z %C, %S",
- "require", "ACZ",
- "upper", "CS",
- "state_name_type", "state",
- }),
- MZ(new String[]{
- "name", "MOZAMBIQUE",
- "fmt", "%N%n%O%n%A%n%C",
- }),
- NA(new String[]{
- "name", "NAMIBIA",
- }),
- NC(new String[]{
- "name", "NEW CALEDONIA",
- "fmt", "%O%n%N%n%A%n%Z %C %X",
- "require", "ACZ",
- "upper", "ACX",
- }),
- NE(new String[]{
- "name", "NIGER",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- NF(new String[]{
- "name", "NORFOLK ISLAND",
- "fmt", "%O%n%N%n%A%n%C %S %Z",
- "upper", "CS",
- }),
- NG(new String[]{
- "name", "NIGERIA",
- "lang", "fr",
- "languages", "fr",
- "fmt", "%N%n%O%n%A%n%C %Z%n%S",
- "upper", "CS",
- "state_name_type", "state",
- }),
- NI(new String[]{
- "name", "NICARAGUA",
- "lang", "es",
- "languages", "es",
- "fmt", "%N%n%O%n%A%n%Z%n%C, %S",
- "upper", "CS",
- "state_name_type", "department",
- }),
- NL(new String[]{
- "name", "NETHERLANDS",
- "fmt", "%O%n%N%n%A%n%Z %C",
- "require", "ACZ",
- }),
- NO(new String[]{
- "name", "NORWAY",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "require", "ACZ",
- }),
- NP(new String[]{
- "name", "NEPAL",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- NR(new String[]{
- "name", "NAURU CENTRAL PACIFIC",
- "lang", "en",
- "languages", "en",
- "fmt", "%N%n%O%n%A%n%S",
- "require", "AS",
- "state_name_type", "district",
- }),
- NU(new String[]{
- "name", "NIUE",
- }),
- NZ(new String[]{
- "name", "NEW ZEALAND",
- "fmt", "%N%n%O%n%A%n%C %Z",
- "require", "ACZ",
- }),
- OM(new String[]{
- "name", "OMAN",
- "fmt", "%N%n%O%n%A%n%Z%n%C",
- }),
- PA(new String[]{
- "name", "PANAMA (REP.)",
- "fmt", "%N%n%O%n%A%n%C%n%S",
- "upper", "CS",
- }),
- PE(new String[]{
- "name", "PERU",
- }),
- PF(new String[]{
- "name", "FRENCH POLYNESIA",
- "fmt", "%N%n%O%n%A%n%Z %C %S",
- "require", "ACSZ",
- "upper", "CS",
- "state_name_type", "island",
- }),
- PG(new String[]{
- "name", "PAPUA NEW GUINEA",
- "fmt", "%N%n%O%n%A%n%C %Z %S",
- "require", "ACS",
- }),
- PH(new String[]{
- "name", "PHILIPPINES",
- "fmt", "%N%n%O%n%A%n%Z %C%n%S",
- "require", "AC",
- }),
- PK(new String[]{
- "name", "PAKISTAN",
- "fmt", "%N%n%O%n%A%n%C-%Z",
- }),
- PL(new String[]{
- "name", "POLAND",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "require", "ACZ",
- }),
- PM(new String[]{
- "name", "ST. PIERRE AND MIQUELON",
- "fmt", "%O%n%N%n%A%n%Z %C %X",
- "require", "ACZ",
- "upper", "ACX",
- }),
- PN(new String[]{
- "name", "PITCAIRN",
- "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
- "require", "ACZ",
- "upper", "CZ",
- }),
- PR(new String[]{
- "name", "PUERTO RICO",
- "fmt", "%N%n%O%n%A%n%C PR %Z",
- "require", "ACZ",
- "upper", "ACNO",
- "zip_name_type", "zip",
- "postprefix", "PR",
- }),
- PS(new String[]{
- "name", "PALESTINIAN TERRITORY",
- }),
- PT(new String[]{
- "name", "PORTUGAL",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "require", "ACZ",
- }),
- PW(new String[]{
- "name", "PALAU",
- "fmt", "%N%n%O%n%A%n%C %S %Z",
- "require", "ACSZ",
- "upper", "ACNOS",
- "zip_name_type", "zip",
- "state_name_type", "state",
- }),
- PY(new String[]{
- "name", "PARAGUAY",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- QA(new String[]{
- "name", "QATAR",
- "upper", "AC",
- }),
- RE(new String[]{
- "name", "REUNION",
- "fmt", "%O%n%N%n%A%n%Z %C %X",
- "require", "ACZ",
- "upper", "ACX",
- }),
- RO(new String[]{
- "name", "ROMANIA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "upper", "AC",
- }),
- RS(new String[]{
- "name", "REPUBLIC OF SERBIA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- RU(new String[]{
- "name", "RUSSIAN FEDERATION",
- "fmt", "%N%n%O%n%A%n%C%n%S%n%Z",
- "require", "ACZ",
- "state_name_type", "oblast",
- "upper", "AC",
- }),
- RW(new String[]{
- "name", "RWANDA",
- "upper", "AC",
- }),
- SA(new String[]{
- "name", "SAUDI ARABIA",
- "fmt", "%N%n%O%n%A%n%C %Z",
- }),
- SB(new String[]{
- "name", "SOLOMON ISLANDS",
- }),
- SC(new String[]{
- "name", "SEYCHELLES",
- "fmt", "%N%n%O%n%A%n%C%n%S",
- "upper", "S",
- "state_name_type", "island",
- }),
- SE(new String[]{
- "name", "SWEDEN",
- "fmt", "%O%n%N%n%A%nSE-%Z %C",
- "require", "ACZ",
- "postprefix", "SE-",
- }),
- SG(new String[]{
- "name", "REP. OF SINGAPORE",
- "fmt", "%N%n%O%n%A%nSINGAPORE %Z",
- "require", "AZ",
- }),
- SH(new String[]{
- "name", "SAINT HELENA",
- "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
- "require", "ACZ",
- "upper", "CZ",
- }),
- SI(new String[]{
- "name", "SLOVENIA",
- "fmt", "%N%n%O%n%A%nSI- %Z %C",
- "postprefix", "SI-",
- }),
- SJ(new String[]{
- "name", "SVALBARD AND JAN MAYEN ISLANDS",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "require", "ACZ",
- }),
- SK(new String[]{
- "name", "SLOVAKIA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- SL(new String[]{
- "name", "SIERRA LEONE",
- }),
- SM(new String[]{
- "name", "SAN MARINO",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "require", "AZ",
- }),
- SN(new String[]{
- "name", "SENEGAL",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- SO(new String[]{
- "name", "SOMALIA",
- "lang", "so",
- "languages", "so",
- "fmt", "%N%n%O%n%A%n%C, %S %Z",
- "require", "ACS",
- "upper", "ACS",
- }),
- SR(new String[]{
- "name", "SURINAME",
- "lang", "nl",
- "languages", "nl",
- "fmt", "%N%n%O%n%A%n%C %X%n%S",
- "upper", "AS",
- }),
- ST(new String[]{
- "name", "SAO TOME AND PRINCIPE",
- "fmt", "%N%n%O%n%A%n%C %X",
- }),
- SV(new String[]{
- "name", "EL SALVADOR",
- "lang", "es",
- "languages", "es",
- "fmt", "%N%n%O%n%A%n%Z-%C%n%S",
- "require", "ACS",
- "upper", "CSZ",
- }),
- SZ(new String[]{
- "name", "SWAZILAND",
- "fmt", "%N%n%O%n%A%n%C%n%Z",
- "upper", "ACZ",
- }),
- TA(new String[]{
- "name", "TRISTAN DA CUNHA",
- }),
- TC(new String[]{
- "name", "TURKS AND CAICOS ISLANDS",
- "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
- "require", "ACZ",
- "upper", "CZ",
- }),
- TD(new String[]{
- "name", "CHAD",
- }),
- TF(new String[]{
- "name", "FRENCH SOUTHERN TERRITORIES",
- }),
- TG(new String[]{
- "name", "TOGO",
- }),
- TH(new String[]{
- "name", "THAILAND",
- "lang", "th",
- "languages", "th",
- "fmt", "%N%n%O%n%A%n%D %C%n%S %Z",
- "lfmt", "%N%n%O%n%A%n%D, %C%n%S %Z",
- "upper", "S",
- }),
- TJ(new String[]{
- "name", "TAJIKISTAN",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- TK(new String[]{
- "name", "TOKELAU",
- }),
- TL(new String[]{
- "name", "TIMOR-LESTE",
- }),
- TM(new String[]{
- "name", "TURKMENISTAN",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- TN(new String[]{
- "name", "TUNISIA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- TO(new String[]{
- "name", "TONGA",
- }),
- TR(new String[]{
- "name", "TURKEY",
- "fmt", "%N%n%O%n%A%n%Z %C/%S",
- "require", "ACZ",
- "locality_name_type", "district",
- }),
- TT(new String[]{
- "name", "TRINIDAD AND TOBAGO",
- }),
- TV(new String[]{
- "name", "TUVALU",
- "lang", "tyv",
- "languages", "tyv",
- "fmt", "%N%n%O%n%A%n%X%n%C%n%S",
- "upper", "ACS",
- "state_name_type", "island",
- }),
- TW(new String[]{
- "name", "TAIWAN",
- "lang", "zh-hant",
- "languages", "zh-hant",
- "fmt", "%Z%n%S%C%n%A%n%O%n%N",
- "lfmt", "%N%n%O%n%A%n%C, %S %Z",
- "require", "ACSZ",
- "state_name_type", "county",
- }),
- TZ(new String[]{
- "name", "TANZANIA (UNITED REP.)",
- }),
- UA(new String[]{
- "name", "UKRAINE",
- "fmt", "%Z %C%n%A%n%O%n%N",
- }),
- UG(new String[]{
- "name", "UGANDA",
- }),
- UM(new String[]{
- "name", "UNITED STATES MINOR OUTLYING ISLANDS",
- "fmt", "%N%n%O%n%A%n%C %S %Z",
- "require", "ACS",
- "upper", "ACNOS",
- "zip_name_type", "zip",
- "state_name_type", "state",
- }),
- US(new String[]{
- "name", "UNITED STATES",
- "lang", "en",
- "languages", "en",
- "fmt", "%N%n%O%n%A%n%C, %S %Z",
- "require", "ACSZ",
- "upper", "CS",
- "zip_name_type", "zip",
- "state_name_type", "state",
- }),
- UY(new String[]{
- "name", "URUGUAY",
- "lang", "es",
- "languages", "es",
- "fmt", "%N%n%O%n%A%n%Z %C %S",
- "upper", "CS",
- }),
- UZ(new String[]{
- "name", "UZBEKISTAN",
- "fmt", "%N%n%O%n%A%n%Z %C%n%S",
- "upper", "CS",
- }),
- VA(new String[]{
- "name", "VATICAN",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- VC(new String[]{
- "name", "SAINT VINCENT AND THE GRENADINES (ANTILLES)",
- }),
- VE(new String[]{
- "name", "VENEZUELA",
- "lang", "es",
- "languages", "es",
- "fmt", "%N%n%O%n%A%n%C %Z, %S",
- "require", "ACS",
- "upper", "CS",
- }),
- VG(new String[]{
- "name", "VIRGIN ISLANDS (BRITISH)",
- "require", "A",
- }),
- VI(new String[]{
- "name", "VIRGIN ISLANDS (U.S.)",
- "fmt", "%N%n%O%n%A%n%C %S %Z",
- "require", "ACSZ",
- "upper", "ACNOS",
- "zip_name_type", "zip",
- "state_name_type", "state",
- }),
- VN(new String[]{
- "name", "VIET NAM",
- "lang", "vi",
- "languages", "vi",
- "fmt", "%N%n%O%n%A%n%C%n%S",
- "lfmt", "%N%n%O%n%A%n%C%n%S",
- "require", "AC",
- }),
- VU(new String[]{
- "name", "VANUATU",
- }),
- WF(new String[]{
- "name", "WALLIS AND FUTUNA ISLANDS",
- "fmt", "%O%n%N%n%A%n%Z %C %X",
- "require", "ACZ",
- "upper", "ACX",
- }),
- WS(new String[]{
- "name", "SAMOA",
- }),
- XK(new String[]{
- "name", "KOSOVO",
- "fmt", "%N%n%O%n%A%n%Z %C"
- }),
- YE(new String[]{
- "name", "YEMEN",
- "require", "AC",
- }),
- YT(new String[]{
- "name", "MAYOTTE",
- "fmt", "%O%n%N%n%A%n%Z %C %X",
- "require", "ACZ",
- "upper", "ACX",
- }),
- YU(new String[]{
- "name", "SERBIA AND MONTENEGRO",
- "fmt", "%N%n%O%n%A%n%Z %C",
- }),
- ZA(new String[]{
- "name", "SOUTH AFRICA",
- "fmt", "%N%n%O%n%A%n%C%n%Z",
- "require", "ACZ",
- }),
- ZM(new String[]{
- "name", "ZAMBIA",
- "fmt", "%N%n%O%n%A%n%Z %C",
- "require", "AC",
- }),
- ZW(new String[]{
- "name", "ZIMBABWE",
- }),
- ZZ(new String[]{
- "fmt", "%N%n%O%n%A%n%C",
- "require", "AC",
- "upper", "C",
- "zip_name_type", "postal",
- "state_name_type", "province",
- "locality_name_type", "city",
- });
+ AC(new String[]{
+ "name", "ASCENSION ISLAND",
+ }),
+ AD(new String[]{
+ "name", "ANDORRA",
+ "lang", "ca",
+ "languages", "ca",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ "require", "A",
+ }),
+ AE(new String[]{
+ "name", "UNITED ARAB EMIRATES",
+ "fmt", "%N%n%O%n%A%n%C",
+ "require", "AC",
+ }),
+ AF(new String[]{
+ "name", "AFGHANISTAN",
+ }),
+ AG(new String[]{
+ "name", "ANTIGUA AND BARBUDA",
+ "require", "A",
+ }),
+ AI(new String[]{
+ "name", "ANGUILLA",
+ }),
+ AL(new String[]{
+ "name", "ALBANIA",
+ }),
+ AM(new String[]{
+ "name", "ARMENIA",
+ "lang", "hy",
+ "languages", "hy",
+ "fmt", "%N%n%O%n%A%n%Z%n%C%n%S",
+ "lfmt", "%N%n%O%n%A%n%Z%n%C%n%S",
+ }),
+ AO(new String[]{
+ "name", "ANGOLA",
+ }),
+ AQ(new String[]{
+ "name", "ANTARCTICA",
+ }),
+ AR(new String[]{
+ "name", "ARGENTINA",
+ "lang", "es",
+ "languages", "es",
+ "fmt", "%N%n%O%n%A%n%Z %C%n%S",
+ "upper", "ACZ",
+ "state_name_type", "state",
+ }),
+ AS(new String[]{
+ "name", "AMERICAN SAMOA",
+ "fmt", "%N%n%O%n%A%n%C %S %Z",
+ "require", "ACSZ",
+ "upper", "ACNOS",
+ "zip_name_type", "zip",
+ "state_name_type", "state",
+ }),
+ AT(new String[]{
+ "name", "AUSTRIA",
+ "fmt", "%O%n%N%n%A%n%Z %C",
+ "require", "ACZ",
+ }),
+ AU(new String[]{
+ "name", "AUSTRALIA",
+ "lang", "en",
+ "languages", "en",
+ "fmt", "%O%n%N%n%A%n%C %S %Z",
+ "require", "ACSZ",
+ "upper", "CS",
+ "state_name_type", "state",
+ }),
+ AW(new String[]{
+ "name", "ARUBA",
+ }),
+ AX(new String[]{
+ "name", "FINLAND",
+ "fmt", "%O%n%N%n%A%nAX-%Z %C%n\u00C5LAND",
+ "require", "ACZ",
+ "postprefix", "AX-",
+ }),
+ AZ(new String[]{
+ "name", "AZERBAIJAN",
+ "fmt", "%N%n%O%n%A%nAZ %Z %C",
+ "postprefix", "AZ ",
+ }),
+ BA(new String[]{
+ "name", "BOSNIA AND HERZEGOVINA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ BB(new String[]{
+ "name", "BARBADOS",
+ "state_name_type", "parish",
+ }),
+ BD(new String[]{
+ "name", "BANGLADESH",
+ "fmt", "%N%n%O%n%A%n%C - %Z",
+ }),
+ BE(new String[]{
+ "name", "BELGIUM",
+ "fmt", "%O%n%N%n%A%n%Z %C",
+ "require", "ACZ",
+ }),
+ BF(new String[]{
+ "name", "BURKINA FASO",
+ "fmt", "%N%n%O%n%A%n%C %X",
+ }),
+ BG(new String[]{
+ "name", "BULGARIA (REP.)",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ BH(new String[]{
+ "name", "BAHRAIN",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ }),
+ BI(new String[]{
+ "name", "BURUNDI",
+ }),
+ BJ(new String[]{
+ "name", "BENIN",
+ "upper", "AC",
+ }),
+ BL(new String[]{
+ "name", "SAINT BARTHELEMY",
+ "fmt", "%O%n%N%n%A%n%Z %C %X",
+ "upper", "ACX",
+ "require", "ACZ",
+ }),
+ BM(new String[]{
+ "name", "BERMUDA",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ }),
+ BN(new String[]{
+ "name", "BRUNEI DARUSSALAM",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ }),
+ BO(new String[]{
+ "name", "BOLIVIA",
+ "upper", "AC",
+ }),
+ BR(new String[]{
+ "name", "BRAZIL",
+ "lang", "pt",
+ "languages", "pt",
+ "fmt", "%O%n%N%n%A%n%D%n%C-%S%n%Z",
+ "require", "ASCZ",
+ "upper", "CS",
+ "state_name_type", "state",
+ "sublocality_name_type", "neighborhood",
+ }),
+ BS(new String[]{
+ "name", "BAHAMAS",
+ "lang", "en",
+ "languages", "en",
+ "fmt", "%N%n%O%n%A%n%C, %S",
+ "state_name_type", "island",
+ }),
+ BT(new String[]{
+ "name", "BHUTAN",
+ }),
+ BV(new String[]{
+ "name", "BOUVET ISLAND",
+ }),
+ BW(new String[]{
+ "name", "BOTSWANA",
+ }),
+ BY(new String[]{
+ "name", "BELARUS",
+ "fmt", "%S%n%Z %C %X%n%A%n%O%n%N",
+ }),
+ BZ(new String[]{
+ "name", "BELIZE",
+ }),
+ CA(new String[]{
+ "name", "CANADA",
+ "lang", "en",
+ "languages", "en~fr",
+ "fmt", "%N%n%O%n%A%n%C %S %Z",
+ "require", "ACSZ",
+ "upper", "ACNOSZ",
+ }),
+ CC(new String[]{
+ "name", "COCOS (KEELING) ISLANDS",
+ "fmt", "%O%n%N%n%A%n%C %S %Z",
+ "upper", "CS",
+ }),
+ CD(new String[]{
+ "name", "CONGO (DEM. REP.)",
+ "fmt", "%N%n%O%n%A%n%C %X",
+ }),
+ CF(new String[]{
+ "name", "CENTRAL AFRICAN REPUBLIC",
+ }),
+ CG(new String[]{
+ "name", "CONGO (REP.)",
+ }),
+ CH(new String[]{
+ "name", "SWITZERLAND",
+ "lang", "de",
+ "languages", "de~fr~it",
+ "fmt", "%O%n%N%n%A%nCH-%Z %C",
+ "require", "ACZ",
+ "upper", "",
+ "postprefix", "CH-",
+ }),
+ CI(new String[]{
+ "name", "COTE D'IVOIRE",
+ "fmt", "%N%n%O%n%X %A %C %X",
+ }),
+ CK(new String[]{
+ "name", "COOK ISLANDS",
+ }),
+ CL(new String[]{
+ "name", "CHILE",
+ "lang", "es",
+ "languages", "es",
+ "fmt", "%N%n%O%n%A%n%Z %C%n%S",
+ "state_name_type", "state",
+ }),
+ CM(new String[]{
+ "name", "CAMEROON",
+ }),
+ CN(new String[]{
+ "name", "P.R. CHINA",
+ "lang", "zh-Hans",
+ "languages", "zh-Hans",
+ "fmt", "%Z%n%S%C%D%n%A%n%O%n%N",
+ "lfmt", "%N%n%O%n%A%n%D%n%C%n%S, %Z",
+ "require", "ACSZ",
+ "upper", "S",
+ "sublocality_name_type", "district",
+ }),
+ CO(new String[]{
+ "name", "COLOMBIA",
+ "fmt", "%N%n%O%n%A%n%C, %S",
+ }),
+ CR(new String[]{
+ "name", "COSTA RICA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ CV(new String[]{
+ "name", "CAPE VERDE",
+ "lang", "pt",
+ "languages", "pt",
+ "fmt", "%N%n%O%n%A%n%Z %C%n%S",
+ "state_name_type", "island",
+ }),
+ CX(new String[]{
+ "name", "CHRISTMAS ISLAND",
+ "fmt", "%O%n%N%n%A%n%C %S %Z",
+ "upper", "CS",
+ }),
+ CY(new String[]{
+ "name", "CYPRUS",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ CZ(new String[]{
+ "name", "CZECH REP.",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ DE(new String[]{
+ "name", "GERMANY",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ "require", "ACZ",
+ }),
+ DJ(new String[]{
+ "name", "DJIBOUTI",
+ }),
+ DK(new String[]{
+ "name", "DENMARK",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ "require", "ACZ",
+ }),
+ DM(new String[]{
+ "name", "DOMINICA",
+ }),
+ DO(new String[]{
+ "name", "DOMINICAN REP.",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ DZ(new String[]{
+ "name", "ALGERIA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ EC(new String[]{
+ "name", "ECUADOR",
+ "fmt", "%N%n%O%n%A%n%Z%n%C",
+ "upper", "CZ",
+ }),
+ EE(new String[]{
+ "name", "ESTONIA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ EG(new String[]{
+ "name", "EGYPT",
+ "lang", "ar",
+ "languages", "ar",
+ "fmt", "%N%n%O%n%A%n%C%n%S%n%Z",
+ "lfmt", "%N%n%O%n%A%n%C%n%S%n%Z",
+ }),
+ EH(new String[]{
+ "name", "WESTERN SAHARA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ ER(new String[]{
+ "name", "ERITREA",
+ }),
+ ES(new String[]{
+ "name", "SPAIN",
+ "lang", "es",
+ "languages", "es",
+ "fmt", "%N%n%O%n%A%n%Z %C %S",
+ "require", "ACSZ",
+ "upper", "CS",
+ }),
+ ET(new String[]{
+ "name", "ETHIOPIA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ FI(new String[]{
+ "name", "FINLAND",
+ "fmt", "%O%n%N%n%A%nFI-%Z %C",
+ "require", "ACZ",
+ "postprefix", "FI-",
+ }),
+ FJ(new String[]{
+ "name", "FIJI",
+ }),
+ FK(new String[]{
+ "name", "FALKLAND ISLANDS (MALVINAS)",
+ "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
+ "require", "ACZ",
+ "upper", "CZ",
+ }),
+ FM(new String[]{
+ "name", "MICRONESIA (Federated State of)",
+ "fmt", "%N%n%O%n%A%n%C %S %Z",
+ "require", "ACSZ",
+ "upper", "ACNOS",
+ "zip_name_type", "zip",
+ "state_name_type", "state",
+ }),
+ FO(new String[]{
+ "name", "FAROE ISLANDS",
+ "fmt", "%N%n%O%n%A%nFO%Z %C",
+ "postprefix", "FO",
+ }),
+ FR(new String[]{
+ "name", "FRANCE",
+ "fmt", "%O%n%N%n%A%n%Z %C %X",
+ "require", "ACZ",
+ "upper", "CX",
+ }),
+ GA(new String[]{
+ "name", "GABON",
+ }),
+ GB(new String[]{
+ "name", "UNITED KINGDOM",
+ "fmt", "%N%n%O%n%A%n%C%n%S%n%Z",
+ "require", "ACZ",
+ "upper", "CZ",
+ "state_name_type", "county",
+ "locality_name_type", "post_town",
+ }),
+ GD(new String[]{
+ "name", "GRENADA (WEST INDIES)",
+ }),
+ GE(new String[]{
+ "name", "GEORGIA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ GF(new String[]{
+ "name", "FRENCH GUIANA",
+ "fmt", "%O%n%N%n%A%n%Z %C %X",
+ "require", "ACZ",
+ "upper", "ACX",
+ }),
+ GG(new String[]{
+ "name", "CHANNEL ISLANDS",
+ "fmt", "%N%n%O%n%A%n%X%n%C%nGUERNSEY%n%Z",
+ "require", "ACZ",
+ "upper", "CZ",
+ }),
+ GH(new String[]{
+ "name", "GHANA",
+ }),
+ GI(new String[]{
+ "name", "GIBRALTAR",
+ "fmt", "%N%n%O%n%A%nGIBRALTAR%n%Z",
+ "require", "A",
+ }),
+ GL(new String[]{
+ "name", "GREENLAND",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ "require", "ACZ",
+ }),
+ GM(new String[]{
+ "name", "GAMBIA",
+ }),
+ GN(new String[]{
+ "name", "GUINEA",
+ "fmt", "%N%n%O%n%Z %A %C",
+ }),
+ GP(new String[]{
+ "name", "GUADELOUPE",
+ "fmt", "%O%n%N%n%A%n%Z %C %X",
+ "require", "ACZ",
+ "upper", "ACX",
+ }),
+ GQ(new String[]{
+ "name", "EQUATORIAL GUINEA",
+ }),
+ GR(new String[]{
+ "name", "GREECE",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ "require", "ACZ",
+ }),
+ GS(new String[]{
+ "name", "SOUTH GEORGIA",
+ "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
+ "require", "ACZ",
+ "upper", "CZ",
+ }),
+ GT(new String[]{
+ "name", "GUATEMALA",
+ "fmt", "%N%n%O%n%A%n%Z- %C",
+ }),
+ GU(new String[]{
+ "name", "GUAM",
+ "fmt", "%N%n%O%n%A%n%C %S %Z",
+ "require", "ACSZ",
+ "upper", "ACNOS",
+ "zip_name_type", "zip",
+ "state_name_type", "state",
+ }),
+ GW(new String[]{
+ "name", "GUINEA-BISSAU",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ GY(new String[]{
+ "name", "GUYANA",
+ }),
+ HK(new String[]{
+ "name", "HONG KONG",
+ "lang", "zh-Hant",
+ "languages", "zh-Hant~en",
+ "fmt", "%S%n%C%n%A%n%O%n%N",
+ "lfmt", "%N%n%O%n%A%n%C%n%S",
+ "require", "AS",
+ "upper", "S",
+ "state_name_type", "area",
+ "locality_name_type", "district",
+ }),
+ HM(new String[]{
+ "name", "HEARD AND MCDONALD ISLANDS",
+ "fmt", "%O%n%N%n%A%n%C %S %Z",
+ "upper", "CS",
+ }),
+ HN(new String[]{
+ "name", "HONDURAS",
+ "fmt", "%N%n%O%n%A%n%C, %S%n%Z",
+ "require", "ACS",
+ }),
+ HR(new String[]{
+ "name", "CROATIA",
+ "fmt", "%N%n%O%n%A%nHR-%Z %C",
+ "postprefix", "HR-",
+ }),
+ HT(new String[]{
+ "name", "HAITI",
+ "fmt", "%N%n%O%n%A%nHT%Z %C %X",
+ "postprefix", "HT",
+ }),
+ HU(new String[]{
+ "name", "HUNGARY (Rep.)",
+ "fmt", "%N%n%O%n%C%n%A%n%Z",
+ "upper", "ACNO",
+ }),
+ ID(new String[]{
+ "name", "INDONESIA",
+ "lang", "id",
+ "languages", "id",
+ "fmt", "%N%n%O%n%A%n%C%n%S %Z",
+ }),
+ IE(new String[]{
+ "name", "IRELAND",
+ "lang", "en",
+ "languages", "en",
+ "fmt", "%N%n%O%n%A%n%C%n%S",
+ "state_name_type", "county",
+ }),
+ IL(new String[]{
+ "name", "ISRAEL",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ }),
+ IM(new String[]{
+ "name", "ISLE OF MAN",
+ "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
+ "require", "ACZ",
+ "upper", "CZ",
+ }),
+ IN(new String[]{
+ "name", "INDIA",
+ "lang", "en",
+ "languages", "en",
+ "fmt", "%N%n%O%n%A%n%C %Z%n%S",
+ "require", "ACSZ",
+ "state_name_type", "state",
+ }),
+ IO(new String[]{
+ "name", "BRITISH INDIAN OCEAN TERRITORY",
+ "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
+ "require", "ACZ",
+ "upper", "CZ",
+ }),
+ IQ(new String[]{
+ "name", "IRAQ",
+ "fmt", "%O%n%N%n%A%n%C, %S%n%Z",
+ "require", "ACS",
+ "upper", "CS",
+ }),
+ IS(new String[]{
+ "name", "ICELAND",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ IT(new String[]{
+ "name", "ITALY",
+ "lang", "it",
+ "languages", "it",
+ "fmt", "%N%n%O%n%A%n%Z %C %S",
+ "require", "ACSZ",
+ "upper", "CS",
+ }),
+ JE(new String[]{
+ "name", "CHANNEL ISLANDS",
+ "fmt", "%N%n%O%n%A%n%X%n%C%nJERSEY%n%Z",
+ "require", "ACZ",
+ "upper", "CZ",
+ }),
+ JM(new String[]{
+ "name", "JAMAICA",
+ "lang", "en",
+ "languages", "en",
+ "fmt", "%N%n%O%n%A%n%C%n%S %X",
+ "require", "ACS",
+ "state_name_type", "parish",
+ }),
+ JO(new String[]{
+ "name", "JORDAN",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ }),
+ JP(new String[]{
+ "name", "JAPAN",
+ "lang", "ja",
+ "languages", "ja",
+ "fmt", "\u3012%Z%n%S%C%n%A%n%O%n%N",
+ "lfmt", "%N%n%O%n%A%n%C, %S%n%Z",
+ "require", "ACSZ",
+ "upper", "S",
+ "state_name_type", "prefecture",
+ }),
+ KE(new String[]{
+ "name", "KENYA",
+ "fmt", "%N%n%O%n%A%n%C%n%Z",
+ }),
+ KG(new String[]{
+ "name", "KYRGYZSTAN",
+ "fmt", "%Z %C %X%n%A%n%O%n%N",
+ }),
+ KH(new String[]{
+ "name", "CAMBODIA",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ }),
+ KI(new String[]{
+ "name", "KIRIBATI",
+ "fmt", "%N%n%O%n%A%n%S%n%C",
+ "upper", "ACNOS",
+ "state_name_type", "island",
+ }),
+ KM(new String[]{
+ "name", "COMOROS",
+ "upper", "AC",
+ }),
+ KN(new String[]{
+ "name", "SAINT KITTS AND NEVIS",
+ "lang", "en",
+ "languages", "en",
+ "fmt", "%N%n%O%n%A%n%C, %S",
+ "require", "ACS",
+ "state_name_type", "island",
+ }),
+ KR(new String[]{
+ "name", "KOREA (REP.)",
+ "lang", "ko",
+ "languages", "ko",
+ "fmt", "%S %C%D%n%A%n%O%n%N%n%Z",
+ "lfmt", "%N%n%O%n%A%n%D%n%C%n%S%n%Z",
+ "require", "ACSZ",
+ "upper", "Z",
+ "state_name_type", "do_si",
+ "sublocality_name_type", "district",
+ }),
+ KW(new String[]{
+ "name", "KUWAIT",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ KY(new String[]{
+ "name", "CAYMAN ISLANDS",
+ "lang", "en",
+ "languages", "en",
+ "fmt", "%N%n%O%n%A%n%S %Z",
+ "require", "AS",
+ "state_name_type", "island",
+ }),
+ KZ(new String[]{
+ "name", "KAZAKHSTAN",
+ "fmt", "%Z%n%S%n%C%n%A%n%O%n%N",
+ }),
+ LA(new String[]{
+ "name", "LAO (PEOPLE'S DEM. REP.)",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ LB(new String[]{
+ "name", "LEBANON",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ }),
+ LC(new String[]{
+ "name", "SAINT LUCIA",
+ }),
+ LI(new String[]{
+ "name", "LIECHTENSTEIN",
+ "fmt", "%O%n%N%n%A%nFL-%Z %C",
+ "require", "ACZ",
+ "postprefix", "FL-",
+ }),
+ LK(new String[]{
+ "name", "SRI LANKA",
+ "fmt", "%N%n%O%n%A%n%C%n%Z",
+ }),
+ LR(new String[]{
+ "name", "LIBERIA",
+ "fmt", "%N%n%O%n%A%n%Z %C %X",
+ }),
+ LS(new String[]{
+ "name", "LESOTHO",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ }),
+ LT(new String[]{
+ "name", "LITHUANIA",
+ "fmt", "%O%n%N%n%A%nLT-%Z %C",
+ "postprefix", "LT-",
+ }),
+ LU(new String[]{
+ "name", "LUXEMBOURG",
+ "fmt", "%O%n%N%n%A%nL-%Z %C",
+ "require", "ACZ",
+ "postprefix", "L-",
+ }),
+ LV(new String[]{
+ "name", "LATVIA",
+ "fmt", "%N%n%O%n%A%n%C, %Z",
+ }),
+ LY(new String[]{
+ "name", "LIBYA",
+ }),
+ MA(new String[]{
+ "name", "MOROCCO",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ MC(new String[]{
+ "name", "MONACO",
+ "fmt", "%N%n%O%n%A%nMC-%Z %C %X",
+ "postprefix", "MC-",
+ }),
+ MD(new String[]{
+ "name", "Rep. MOLDOVA",
+ "fmt", "%N%n%O%n%A%nMD-%Z %C",
+ "postprefix", "MD-",
+ }),
+ ME(new String[]{
+ "name", "MONTENEGRO",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ MF(new String[]{
+ "name", "SAINT MARTIN",
+ "fmt", "%O%n%N%n%A%n%Z %C %X",
+ "upper", "ACX",
+ "require", "ACZ",
+ }),
+ MG(new String[]{
+ "name", "MADAGASCAR",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ MH(new String[]{
+ "name", "MARSHALL ISLANDS",
+ "fmt", "%N%n%O%n%A%n%C %S %Z",
+ "require", "ACSZ",
+ "upper", "ACNOS",
+ "zip_name_type", "zip",
+ "state_name_type", "state",
+ }),
+ MK(new String[]{
+ "name", "MACEDONIA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ ML(new String[]{
+ "name", "MALI",
+ }),
+ MN(new String[]{
+ "name", "MONGOLIA",
+ "fmt", "%N%n%O%n%A%n%S %C-%X%n%Z",
+ }),
+ MO(new String[]{
+ "name", "MACAO",
+ "lang", "zh-Hant",
+ "languages", "zh-Hant",
+ "fmt", "%A%n%O%n%N",
+ "lfmt", "%N%n%O%n%A",
+ "require", "A",
+ }),
+ MP(new String[]{
+ "name", "NORTHERN MARIANA ISLANDS",
+ "fmt", "%N%n%O%n%A%n%C %S %Z",
+ "require", "ACSZ",
+ "upper", "ACNOS",
+ "zip_name_type", "zip",
+ "state_name_type", "state",
+ }),
+ MQ(new String[]{
+ "name", "MARTINIQUE",
+ "fmt", "%O%n%N%n%A%n%Z %C %X",
+ "require", "ACZ",
+ "upper", "ACX",
+ }),
+ MR(new String[]{
+ "name", "MAURITANIA",
+ "upper", "AC",
+ }),
+ MS(new String[]{
+ "name", "MONTSERRAT",
+ }),
+ MT(new String[]{
+ "name", "MALTA",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ "upper", "CZ",
+ }),
+ MU(new String[]{
+ "name", "MAURITIUS",
+ "fmt", "%N%n%O%n%A%n%Z%n%C",
+ "upper", "CZ",
+ }),
+ MV(new String[]{
+ "name", "MALDIVES",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ }),
+ MW(new String[]{
+ "name", "MALAWI",
+ "fmt", "%N%n%O%n%A%n%C %X",
+ }),
+ MX(new String[]{
+ "name", "MEXICO",
+ "lang", "es",
+ "languages", "es",
+ "fmt", "%N%n%O%n%A%n%D%n%Z %C, %S",
+ "require", "ACZ",
+ "upper", "CSZ",
+ "state_name_type", "state",
+ "sublocality_name_type", "neighborhood",
+ }),
+ MY(new String[]{
+ "name", "MALAYSIA",
+ "lang", "ms",
+ "languages", "ms",
+ "fmt", "%N%n%O%n%A%n%D%n%Z %C%n%S",
+ "require", "ACZ",
+ "upper", "CS",
+ "state_name_type", "state",
+ "sublocality_name_type", "village_township",
+ }),
+ MZ(new String[]{
+ "name", "MOZAMBIQUE",
+ }),
+ NA(new String[]{
+ "name", "NAMIBIA",
+ }),
+ NC(new String[]{
+ "name", "NEW CALEDONIA",
+ "fmt", "%O%n%N%n%A%n%Z %C %X",
+ "require", "ACZ",
+ "upper", "ACX",
+ }),
+ NE(new String[]{
+ "name", "NIGER",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ NF(new String[]{
+ "name", "NORFOLK ISLAND",
+ "fmt", "%O%n%N%n%A%n%C %S %Z",
+ "upper", "CS",
+ }),
+ NG(new String[]{
+ "name", "NIGERIA",
+ "lang", "en",
+ "languages", "en",
+ "fmt", "%N%n%O%n%A%n%C %Z%n%S",
+ "upper", "CS",
+ "state_name_type", "state",
+ }),
+ NI(new String[]{
+ "name", "NICARAGUA",
+ "lang", "es",
+ "languages", "es",
+ "fmt", "%N%n%O%n%A%n%Z%n%C, %S",
+ "upper", "CS",
+ "state_name_type", "department",
+ }),
+ NL(new String[]{
+ "name", "NETHERLANDS",
+ "fmt", "%O%n%N%n%A%n%Z %C",
+ "require", "ACZ",
+ }),
+ NO(new String[]{
+ "name", "NORWAY",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ "require", "ACZ",
+ }),
+ NP(new String[]{
+ "name", "NEPAL",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ }),
+ NR(new String[]{
+ "name", "NAURU CENTRAL PACIFIC",
+ "lang", "en",
+ "languages", "en",
+ "fmt", "%N%n%O%n%A%n%S",
+ "require", "AS",
+ "state_name_type", "district",
+ }),
+ NU(new String[]{
+ "name", "NIUE",
+ }),
+ NZ(new String[]{
+ "name", "NEW ZEALAND",
+ "fmt", "%N%n%O%n%A%n%D%n%C %Z",
+ "require", "ACZ",
+ }),
+ OM(new String[]{
+ "name", "OMAN",
+ "fmt", "%N%n%O%n%A%n%Z%n%C",
+ }),
+ PA(new String[]{
+ "name", "PANAMA (REP.)",
+ "fmt", "%N%n%O%n%A%n%C%n%S",
+ "upper", "CS",
+ }),
+ PE(new String[]{
+ "name", "PERU",
+ }),
+ PF(new String[]{
+ "name", "FRENCH POLYNESIA",
+ "fmt", "%N%n%O%n%A%n%Z %C %S",
+ "require", "ACSZ",
+ "upper", "CS",
+ "state_name_type", "island",
+ }),
+ PG(new String[]{
+ "name", "PAPUA NEW GUINEA",
+ "fmt", "%N%n%O%n%A%n%C %Z %S",
+ "require", "ACS",
+ }),
+ PH(new String[]{
+ "name", "PHILIPPINES",
+ "lang", "en",
+ "languages", "en",
+ "fmt", "%N%n%O%n%A%n%D, %C%n%Z %S",
+ "require", "AC",
+ }),
+ PK(new String[]{
+ "name", "PAKISTAN",
+ "fmt", "%N%n%O%n%A%n%C-%Z",
+ }),
+ PL(new String[]{
+ "name", "POLAND",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ "require", "ACZ",
+ }),
+ PM(new String[]{
+ "name", "ST. PIERRE AND MIQUELON",
+ "fmt", "%O%n%N%n%A%n%Z %C %X",
+ "require", "ACZ",
+ "upper", "ACX",
+ }),
+ PN(new String[]{
+ "name", "PITCAIRN",
+ "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
+ "require", "ACZ",
+ "upper", "CZ",
+ }),
+ PR(new String[]{
+ "name", "PUERTO RICO",
+ "fmt", "%N%n%O%n%A%n%C PR %Z",
+ "require", "ACZ",
+ "upper", "ACNO",
+ "zip_name_type", "zip",
+ "postprefix", "PR",
+ }),
+ PS(new String[]{
+ "name", "PALESTINIAN TERRITORY",
+ }),
+ PT(new String[]{
+ "name", "PORTUGAL",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ "require", "ACZ",
+ }),
+ PW(new String[]{
+ "name", "PALAU",
+ "fmt", "%N%n%O%n%A%n%C %S %Z",
+ "require", "ACSZ",
+ "upper", "ACNOS",
+ "zip_name_type", "zip",
+ "state_name_type", "state",
+ }),
+ PY(new String[]{
+ "name", "PARAGUAY",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ QA(new String[]{
+ "name", "QATAR",
+ "upper", "AC",
+ }),
+ RE(new String[]{
+ "name", "REUNION",
+ "fmt", "%O%n%N%n%A%n%Z %C %X",
+ "require", "ACZ",
+ "upper", "ACX",
+ }),
+ RO(new String[]{
+ "name", "ROMANIA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ "upper", "AC",
+ }),
+ RS(new String[]{
+ "name", "REPUBLIC OF SERBIA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ RU(new String[]{
+ "name", "RUSSIAN FEDERATION",
+ "fmt", "%N%n%O%n%A%n%C%n%S%n%Z",
+ "require", "ACZ",
+ "upper", "AC",
+ "state_name_type", "oblast",
+ }),
+ RW(new String[]{
+ "name", "RWANDA",
+ "upper", "AC",
+ }),
+ SA(new String[]{
+ "name", "SAUDI ARABIA",
+ "fmt", "%N%n%O%n%A%n%C %Z",
+ }),
+ SB(new String[]{
+ "name", "SOLOMON ISLANDS",
+ }),
+ SC(new String[]{
+ "name", "SEYCHELLES",
+ "fmt", "%N%n%O%n%A%n%C%n%S",
+ "upper", "S",
+ "state_name_type", "island",
+ }),
+ SE(new String[]{
+ "name", "SWEDEN",
+ "fmt", "%O%n%N%n%A%nSE-%Z %C",
+ "require", "ACZ",
+ "postprefix", "SE-",
+ }),
+ SG(new String[]{
+ "name", "REP. OF SINGAPORE",
+ "fmt", "%N%n%O%n%A%nSINGAPORE %Z",
+ "require", "AZ",
+ }),
+ SH(new String[]{
+ "name", "SAINT HELENA",
+ "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
+ "require", "ACZ",
+ "upper", "CZ",
+ }),
+ SI(new String[]{
+ "name", "SLOVENIA",
+ "fmt", "%N%n%O%n%A%nSI- %Z %C",
+ "postprefix", "SI-",
+ }),
+ SJ(new String[]{
+ "name", "SVALBARD AND JAN MAYEN ISLANDS",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ "require", "ACZ",
+ }),
+ SK(new String[]{
+ "name", "SLOVAKIA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ SL(new String[]{
+ "name", "SIERRA LEONE",
+ }),
+ SM(new String[]{
+ "name", "SAN MARINO",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ "require", "AZ",
+ }),
+ SN(new String[]{
+ "name", "SENEGAL",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ SO(new String[]{
+ "name", "SOMALIA",
+ "lang", "so",
+ "languages", "so",
+ "fmt", "%N%n%O%n%A%n%C, %S %Z",
+ "require", "ACS",
+ "upper", "ACS",
+ }),
+ SR(new String[]{
+ "name", "SURINAME",
+ "lang", "nl",
+ "languages", "nl",
+ "fmt", "%N%n%O%n%A%n%C %X%n%S",
+ "upper", "AS",
+ }),
+ ST(new String[]{
+ "name", "SAO TOME AND PRINCIPE",
+ "fmt", "%N%n%O%n%A%n%C %X",
+ }),
+ SV(new String[]{
+ "name", "EL SALVADOR",
+ "lang", "es",
+ "languages", "es",
+ "fmt", "%N%n%O%n%A%n%Z-%C%n%S",
+ "require", "ACS",
+ "upper", "CSZ",
+ }),
+ SZ(new String[]{
+ "name", "SWAZILAND",
+ "fmt", "%N%n%O%n%A%n%C%n%Z",
+ "upper", "ACZ",
+ }),
+ TA(new String[]{
+ "name", "TRISTAN DA CUNHA",
+ }),
+ TC(new String[]{
+ "name", "TURKS AND CAICOS ISLANDS",
+ "fmt", "%N%n%O%n%A%n%X%n%C%n%Z",
+ "require", "ACZ",
+ "upper", "CZ",
+ }),
+ TD(new String[]{
+ "name", "CHAD",
+ }),
+ TF(new String[]{
+ "name", "FRENCH SOUTHERN TERRITORIES",
+ }),
+ TG(new String[]{
+ "name", "TOGO",
+ }),
+ TH(new String[]{
+ "name", "THAILAND",
+ "lang", "th",
+ "languages", "th",
+ "fmt", "%N%n%O%n%A%n%D %C%n%S %Z",
+ "lfmt", "%N%n%O%n%A%n%D, %C%n%S %Z",
+ "upper", "S",
+ }),
+ TJ(new String[]{
+ "name", "TAJIKISTAN",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ TK(new String[]{
+ "name", "TOKELAU",
+ }),
+ TL(new String[]{
+ "name", "TIMOR-LESTE",
+ }),
+ TM(new String[]{
+ "name", "TURKMENISTAN",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ TN(new String[]{
+ "name", "TUNISIA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ TO(new String[]{
+ "name", "TONGA",
+ }),
+ TR(new String[]{
+ "name", "TURKEY",
+ "lang", "tr",
+ "languages", "tr",
+ "fmt", "%N%n%O%n%A%n%Z %C/%S",
+ "require", "ACZ",
+ "locality_name_type", "district",
+ }),
+ TT(new String[]{
+ "name", "TRINIDAD AND TOBAGO",
+ }),
+ TV(new String[]{
+ "name", "TUVALU",
+ "lang", "tyv",
+ "languages", "tyv",
+ "fmt", "%N%n%O%n%A%n%X%n%C%n%S",
+ "upper", "ACS",
+ "state_name_type", "island",
+ }),
+ TW(new String[]{
+ "name", "TAIWAN",
+ "lang", "zh-Hant",
+ "languages", "zh-Hant",
+ "fmt", "%Z%n%S%C%n%A%n%O%n%N",
+ "lfmt", "%N%n%O%n%A%n%C, %S %Z",
+ "require", "ACSZ",
+ "state_name_type", "county",
+ }),
+ TZ(new String[]{
+ "name", "TANZANIA (UNITED REP.)",
+ }),
+ UA(new String[]{
+ "name", "UKRAINE",
+ "fmt", "%N%n%O%n%A%n%C%n%S%n%Z",
+ "require", "ACZ",
+ "state_name_type", "oblast",
+ }),
+ UG(new String[]{
+ "name", "UGANDA",
+ }),
+ UM(new String[]{
+ "name", "UNITED STATES MINOR OUTLYING ISLANDS",
+ "fmt", "%N%n%O%n%A%n%C %S %Z",
+ "require", "ACS",
+ "upper", "ACNOS",
+ "zip_name_type", "zip",
+ "state_name_type", "state",
+ }),
+ US(new String[]{
+ "name", "UNITED STATES",
+ "lang", "en",
+ "languages", "en",
+ "fmt", "%N%n%O%n%A%n%C, %S %Z",
+ "require", "ACSZ",
+ "upper", "CS",
+ "zip_name_type", "zip",
+ "state_name_type", "state",
+ }),
+ UY(new String[]{
+ "name", "URUGUAY",
+ "lang", "es",
+ "languages", "es",
+ "fmt", "%N%n%O%n%A%n%Z %C %S",
+ "upper", "CS",
+ }),
+ UZ(new String[]{
+ "name", "UZBEKISTAN",
+ "fmt", "%N%n%O%n%A%n%Z %C%n%S",
+ "upper", "CS",
+ }),
+ VA(new String[]{
+ "name", "VATICAN",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ VC(new String[]{
+ "name", "SAINT VINCENT AND THE GRENADINES (ANTILLES)",
+ }),
+ VE(new String[]{
+ "name", "VENEZUELA",
+ "lang", "es",
+ "languages", "es",
+ "fmt", "%N%n%O%n%A%n%C %Z, %S",
+ "require", "ACS",
+ "upper", "CS",
+ }),
+ VG(new String[]{
+ "name", "VIRGIN ISLANDS (BRITISH)",
+ "fmt", "%N%n%O%n%A%n%C%n%Z",
+ "require", "A",
+ }),
+ VI(new String[]{
+ "name", "VIRGIN ISLANDS (U.S.)",
+ "fmt", "%N%n%O%n%A%n%C %S %Z",
+ "require", "ACSZ",
+ "upper", "ACNOS",
+ "zip_name_type", "zip",
+ "state_name_type", "state",
+ }),
+ VN(new String[]{
+ "name", "VIET NAM",
+ "lang", "vi",
+ "languages", "vi",
+ "fmt", "%N%n%O%n%A%n%C%n%S %Z",
+ "lfmt", "%N%n%O%n%A%n%C%n%S %Z",
+ }),
+ VU(new String[]{
+ "name", "VANUATU",
+ }),
+ WF(new String[]{
+ "name", "WALLIS AND FUTUNA ISLANDS",
+ "fmt", "%O%n%N%n%A%n%Z %C %X",
+ "require", "ACZ",
+ "upper", "ACX",
+ }),
+ WS(new String[]{
+ "name", "SAMOA",
+ }),
+ XK(new String[]{
+ "name", "KOSOVO",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ YE(new String[]{
+ "name", "YEMEN",
+ }),
+ YT(new String[]{
+ "name", "MAYOTTE",
+ "fmt", "%O%n%N%n%A%n%Z %C %X",
+ "require", "ACZ",
+ "upper", "ACX",
+ }),
+ ZA(new String[]{
+ "name", "SOUTH AFRICA",
+ "fmt", "%N%n%O%n%A%n%D%n%C%n%Z",
+ "require", "ACZ",
+ }),
+ ZM(new String[]{
+ "name", "ZAMBIA",
+ "fmt", "%N%n%O%n%A%n%Z %C",
+ }),
+ ZW(new String[]{
+ "name", "ZIMBABWE",
+ }),
+ ZZ(new String[]{
+ "fmt", "%N%n%O%n%A%n%C",
+ "require", "AC",
+ "upper", "C",
+ "zip_name_type", "postal",
+ "state_name_type", "province",
+ "locality_name_type", "city",
+ "sublocality_name_type", "suburb",
+ });
- private String jsonString;
+ private String jsonString;
- private RegionDataEnum(String[] inputArray) {
- jsonString = convertArrayToJsonString(inputArray);
- }
-
- String getJsonString() {
- return jsonString;
- }
+ private RegionDataEnum(String[] inputArray) {
+ jsonString = convertArrayToJsonString(inputArray);
}
- static {
- for (RegionDataEnum region : RegionDataEnum.values()) {
- COUNTRY_FORMAT_MAP.put(region.toString(), region.getJsonString());
- }
+ String getJsonString() {
+ return jsonString;
}
+ }
- static Map<String, String> getCountryFormatMap() {
- return COUNTRY_FORMAT_MAP;
+ static {
+ for (RegionDataEnum region : RegionDataEnum.values()) {
+ COUNTRY_FORMAT_MAP.put(region.toString(), region.getJsonString());
}
+ }
+
+ static Map<String, String> getCountryFormatMap() {
+ return COUNTRY_FORMAT_MAP;
+ }
- /**
- * Assumes the array is a well-formed array - i.e., there are no unmatched keys in the input.
- * Package-private so it can be accessed by tests.
- */
- static String convertArrayToJsonString(String[] input) {
- JSONObject object = new JSONObject();
- for (int i = 0; i < input.length; i += 2) {
- try {
- object.put(input[i], input[i + 1]);
- } catch (JSONException e) {
- // Ignore for now.
- }
- }
- return object.toString();
+ /**
+ * Assumes the array is a well-formed array - i.e., there are no unmatched keys in the input.
+ * Package-private so it can be accessed by tests.
+ */
+ static String convertArrayToJsonString(String[] input) {
+ JSONObject object = new JSONObject();
+ for (int i = 0; i < input.length; i += 2) {
+ try {
+ object.put(input[i], input[i + 1]);
+ } catch (JSONException e) {
+ // Ignore for now.
+ }
}
+ return object.toString();
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/SimpleClientCacheManager.java b/java/src/com/android/i18n/addressinput/SimpleClientCacheManager.java
index c8943ea..4e253c8 100644
--- a/java/src/com/android/i18n/addressinput/SimpleClientCacheManager.java
+++ b/java/src/com/android/i18n/addressinput/SimpleClientCacheManager.java
@@ -20,20 +20,20 @@ package com.android.i18n.addressinput;
* A simple implementation of ClientCacheManager which doesn't do any caching on its own.
*/
public class SimpleClientCacheManager implements ClientCacheManager {
- // URL to get public address data.
- private static final String PUBLIC_ADDRESS_SERVER = "http://i18napis.appspot.com/address";
+ // URL to get public address data.
+ private static final String PUBLIC_ADDRESS_SERVER = "http://i18napis.appspot.com/address";
- @Override
- public String get(String key) {
- return "";
- }
+ @Override
+ public String get(String key) {
+ return "";
+ }
- @Override
- public void put(String key, String data) {
- }
+ @Override
+ public void put(String key, String data) {
+ }
- @Override
- public String getAddressServerUrl() {
- return PUBLIC_ADDRESS_SERVER;
- }
+ @Override
+ public String getAddressServerUrl() {
+ return PUBLIC_ADDRESS_SERVER;
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/StandardAddressVerifier.java b/java/src/com/android/i18n/addressinput/StandardAddressVerifier.java
index fccb24b..96cf684 100644
--- a/java/src/com/android/i18n/addressinput/StandardAddressVerifier.java
+++ b/java/src/com/android/i18n/addressinput/StandardAddressVerifier.java
@@ -39,200 +39,197 @@ import java.util.Map;
*/
public class StandardAddressVerifier {
- protected final FieldVerifier mRootVerifier;
-
- protected final VerifierRefiner mRefiner;
-
- protected final Map<AddressField, List<AddressProblemType>> mProblemMap;
-
- /**
- * Uses the rootVerifier and {@link #DEFAULT_REFINER} to perform the standard checks on the
- * address fields, as defined in {@link StandardChecks}.
- */
- public StandardAddressVerifier(FieldVerifier rootVerifier) {
- this(rootVerifier, DEFAULT_REFINER, StandardChecks.PROBLEM_MAP);
- }
-
- /**
- * Uses the rootVerifier and the refiner to perform the standard checks on the address fields,
- * as defined in {@link StandardChecks}.
- */
- public StandardAddressVerifier(FieldVerifier rootVerifier, VerifierRefiner refiner) {
- this(rootVerifier, refiner, StandardChecks.PROBLEM_MAP);
- }
-
- /**
- * Uses the rootVerifier and {@link #DEFAULT_REFINER} to perform the given checks on the address
- * fields. A reference to problemMap is maintained. It is not modified by this class, and should
- * not be modified subsequent to this call.
- */
- public StandardAddressVerifier(FieldVerifier rootVerifier,
- Map<AddressField, List<AddressProblemType>> problemMap) {
- this(rootVerifier, DEFAULT_REFINER, problemMap);
+ protected final FieldVerifier rootVerifier;
+
+ protected final VerifierRefiner refiner;
+
+ protected final Map<AddressField, List<AddressProblemType>> problemMap;
+
+ /**
+ * Uses the rootVerifier and {@link #DEFAULT_REFINER} to perform the standard checks on the
+ * address fields, as defined in {@link StandardChecks}.
+ */
+ public StandardAddressVerifier(FieldVerifier rootVerifier) {
+ this(rootVerifier, DEFAULT_REFINER, StandardChecks.PROBLEM_MAP);
+ }
+
+ /**
+ * Uses the rootVerifier and the refiner to perform the standard checks on the address fields,
+ * as defined in {@link StandardChecks}.
+ */
+ public StandardAddressVerifier(FieldVerifier rootVerifier, VerifierRefiner refiner) {
+ this(rootVerifier, refiner, StandardChecks.PROBLEM_MAP);
+ }
+
+ /**
+ * Uses the rootVerifier and {@link #DEFAULT_REFINER} to perform the given checks on the address
+ * fields. A reference to problemMap is maintained. It is not modified by this class, and should
+ * not be modified subsequent to this call.
+ */
+ public StandardAddressVerifier(FieldVerifier rootVerifier,
+ Map<AddressField, List<AddressProblemType>> problemMap) {
+ this(rootVerifier, DEFAULT_REFINER, problemMap);
+ }
+
+ /**
+ * Uses the rootVerifier and the refiner to perform the given checks on the address fields. A
+ * reference to problemMap is maintained. It is not modified by this class, and should not be
+ * modified subsequent to this call.
+ */
+ public StandardAddressVerifier(FieldVerifier rootVerifier, VerifierRefiner refiner,
+ Map<AddressField, List<AddressProblemType>> problemMap) {
+ this.rootVerifier = rootVerifier;
+ this.refiner = refiner;
+ this.problemMap = StandardChecks.PROBLEM_MAP;
+ }
+
+ public void verify(AddressData address, AddressProblems problems) {
+ NotifyingListener listener = new NotifyingListener(this);
+ verifyAsync(address, problems, listener);
+ try {
+ listener.waitLoadingEnd();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
}
-
- /**
- * Uses the rootVerifier and the refiner to perform the given checks on the address fields. A
- * reference to problemMap is maintained. It is not modified by this class, and should not be
- * modified subsequent to this call.
- */
- public StandardAddressVerifier(FieldVerifier rootVerifier, VerifierRefiner refiner,
- Map<AddressField, List<AddressProblemType>> problemMap) {
- mRootVerifier = rootVerifier;
- mRefiner = refiner;
- mProblemMap = StandardChecks.PROBLEM_MAP;
+ }
+
+ public void verifyAsync(AddressData address, AddressProblems problems,
+ DataLoadListener listener) {
+ Thread verifier = new Thread(new Verifier(address, problems, listener));
+ verifier.start();
+ }
+
+ private class Verifier implements Runnable {
+ private AddressData address;
+ private AddressProblems problems;
+ private DataLoadListener listener;
+
+ Verifier(AddressData address, AddressProblems problems, DataLoadListener listener) {
+ this.address = address;
+ this.problems = problems;
+ this.listener = listener;
}
- public void verify(AddressData address, AddressProblems problems) {
- NotifyingListener listener = new NotifyingListener(this);
- verifyAsync(address, problems, listener);
- try {
- listener.waitLoadingEnd();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-
- public void verifyAsync(AddressData address, AddressProblems problems,
- DataLoadListener listener) {
- Thread verifier = new Thread(new Verifier(address, problems, listener));
- verifier.start();
- }
+ @Override
+ public void run() {
+ listener.dataLoadingBegin();
- private class Verifier implements Runnable {
- private AddressData mAddress;
- private AddressProblems mProblems;
- private DataLoadListener mListener;
+ FieldVerifier v = rootVerifier;
- Verifier(AddressData address, AddressProblems problems, DataLoadListener listener) {
- mAddress = address;
- mProblems = problems;
- mListener = listener;
+ ScriptType script = null;
+ if (address.getLanguageCode() != null) {
+ if (Util.isExplicitLatinScript(address.getLanguageCode())) {
+ script = ScriptType.LATIN;
+ } else {
+ script = ScriptType.LOCAL;
}
-
- @Override
- public void run() {
- mListener.dataLoadingBegin();
-
- FieldVerifier v = mRootVerifier;
-
- ScriptType script = null;
- if (mAddress.getLanguageCode() != null) {
- if (Util.isExplicitLatinScript(mAddress.getLanguageCode())) {
- script = ScriptType.LATIN;
- } else {
- script = ScriptType.LOCAL;
- }
- }
-
- // The first four calls refine the verifier, so must come first, and in this
- // order.
- verifyField(script, v, COUNTRY, mAddress.getPostalCountry(), mProblems);
- if (mProblems.isEmpty()) {
- v = v.refineVerifier(mAddress.getPostalCountry());
- verifyField(script, v, ADMIN_AREA, mAddress.getAdministrativeArea(), mProblems);
- if (mProblems.isEmpty()) {
- v = v.refineVerifier(mAddress.getAdministrativeArea());
- verifyField(script, v, LOCALITY, mAddress.getLocality(), mProblems);
- if (mProblems.isEmpty()) {
- v = v.refineVerifier(mAddress.getLocality());
- verifyField(script, v, DEPENDENT_LOCALITY,
- mAddress.getDependentLocality(), mProblems);
- if (mProblems.isEmpty()) {
- v = v.refineVerifier(mAddress.getDependentLocality());
- }
- }
- }
+ }
+
+ // The first four calls refine the verifier, so must come first, and in this
+ // order.
+ verifyField(script, v, COUNTRY, address.getPostalCountry(), problems);
+ if (problems.isEmpty()) {
+ v = v.refineVerifier(address.getPostalCountry());
+ verifyField(script, v, ADMIN_AREA, address.getAdministrativeArea(), problems);
+ if (problems.isEmpty()) {
+ v = v.refineVerifier(address.getAdministrativeArea());
+ verifyField(script, v, LOCALITY, address.getLocality(), problems);
+ if (problems.isEmpty()) {
+ v = v.refineVerifier(address.getLocality());
+ verifyField(script, v, DEPENDENT_LOCALITY,
+ address.getDependentLocality(), problems);
+ if (problems.isEmpty()) {
+ v = v.refineVerifier(address.getDependentLocality());
}
+ }
+ }
+ }
- String street = Util.joinAndSkipNulls("\n", mAddress.getAddressLine1(),
- mAddress.getAddressLine2());
+ String street = Util.joinAndSkipNulls("\n", address.getAddressLine1(),
+ address.getAddressLine2());
- // remaining calls don't change the field verifier
- verifyField(script, v, POSTAL_CODE, mAddress.getPostalCode(), mProblems);
- verifyField(script, v, STREET_ADDRESS, street, mProblems);
- verifyField(script, v, SORTING_CODE, mAddress.getSortingCode(), mProblems);
- verifyField(script, v, ORGANIZATION, mAddress.getOrganization(), mProblems);
- verifyField(script, v, RECIPIENT, mAddress.getRecipient(), mProblems);
+ // remaining calls don't change the field verifier
+ verifyField(script, v, POSTAL_CODE, address.getPostalCode(), problems);
+ verifyField(script, v, STREET_ADDRESS, street, problems);
+ verifyField(script, v, SORTING_CODE, address.getSortingCode(), problems);
+ verifyField(script, v, ORGANIZATION, address.getOrganization(), problems);
+ verifyField(script, v, RECIPIENT, address.getRecipient(), problems);
- postVerify(v, mAddress, mProblems);
+ postVerify(v, address, problems);
- mListener.dataLoadingEnd();
- }
+ listener.dataLoadingEnd();
}
-
- /**
- * Hook to perform any final processing using the final verifier. Default does no additional
- * verification.
- */
- protected void postVerify(FieldVerifier verifier, AddressData address,
- AddressProblems problems) {
+ }
+
+ /**
+ * Hook to perform any final processing using the final verifier. Default does no additional
+ * verification.
+ */
+ protected void postVerify(FieldVerifier verifier, AddressData address, AddressProblems problems) {
+ }
+
+ /**
+ * Hook called by verify with each verifiable field, in order. Override to provide pre- or
+ * post-checks for all fields.
+ */
+ protected boolean verifyField(LookupKey.ScriptType script, FieldVerifier verifier,
+ AddressField field, String value, AddressProblems problems) {
+ Iterator<AddressProblemType> iter = getProblemIterator(field);
+ while (iter.hasNext()) {
+ AddressProblemType prob = iter.next();
+ if (!verifyProblemField(script, verifier, prob, field, value, problems)) {
+ return false;
+ }
}
-
- /**
- * Hook called by verify with each verifiable field, in order. Override to provide pre- or
- * post-checks for all fields.
- */
- protected boolean verifyField(LookupKey.ScriptType script,
- FieldVerifier verifier, AddressField field, String value,
- AddressProblems problems) {
- Iterator<AddressProblemType> iter = getProblemIterator(field);
- while (iter.hasNext()) {
- AddressProblemType prob = iter.next();
- if (!verifyProblemField(script, verifier, prob, field, value, problems)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Hook for on-the-fly modification of the problem list. Override to change the problems to
- * check for a particular field. Generally, changing the problemMap passed to the constructor
- * is a better approach.
- */
- protected Iterator<AddressProblemType> getProblemIterator(AddressField field) {
- List<AddressProblemType> list = mProblemMap.get(field);
- if (list == null) {
- list = Collections.emptyList();
- }
- return list.iterator();
+ return true;
+ }
+
+ /**
+ * Hook for on-the-fly modification of the problem list. Override to change the problems to
+ * check for a particular field. Generally, changing the problemMap passed to the constructor
+ * is a better approach.
+ */
+ protected Iterator<AddressProblemType> getProblemIterator(AddressField field) {
+ List<AddressProblemType> list = problemMap.get(field);
+ if (list == null) {
+ list = Collections.emptyList();
}
+ return list.iterator();
+ }
+
+ /**
+ * Hook for adding special checks for particular problems and/or fields.
+ */
+ protected boolean verifyProblemField(LookupKey.ScriptType script,
+ FieldVerifier verifier, AddressProblemType problem, AddressField field,
+ String datum, AddressProblems problems) {
+ return verifier.check(script, problem, field, datum, problems);
+ }
+
+ /**
+ * This gets called with the hierarchical fields COUNTRY, ADMIN_AREA, LOCALITY,
+ * DEPENDENT_LOCALITY in order, returning the refined verifier at each step.
+ *
+ * <p>The default implementation is stateless, and delegates to the verifier to do the
+ * refinement.
+ */
+ public static class VerifierRefiner {
/**
- * Hook for adding special checks for particular problems and/or fields.
+ * Refines the verifier. This delegates to the verifier to perform the refinement.
*/
- protected boolean verifyProblemField(LookupKey.ScriptType script,
- FieldVerifier verifier, AddressProblemType problem, AddressField field,
- String datum, AddressProblems problems) {
- return verifier.check(script, problem, field, datum, problems);
+ public FieldVerifier refineVerifier(FieldVerifier v, AddressField field, String subkey) {
+ return v.refineVerifier(subkey);
}
/**
- * This gets called with the hierarchical fields COUNTRY, ADMIN_AREA, LOCALITY,
- * DEPENDENT_LOCALITY in order, returning the refined verifier at each step.
- *
- * <p>The default implementation is stateless, and delegates to the verifier to do the
- * refinement.
+ * Returns a clean version of the refiner. Since this implementation is stateless, returns
+ * this.
*/
- public static class VerifierRefiner {
-
- /**
- * Refines the verifier. This delegates to the verifier to perform the refinement.
- */
- public FieldVerifier refineVerifier(FieldVerifier v, AddressField field,
- String subkey) {
- return v.refineVerifier(subkey);
- }
-
- /**
- * Returns a clean version of the refiner. Since this implementation is stateless, returns
- * this.
- */
- public VerifierRefiner newInstance() {
- return this;
- }
+ public VerifierRefiner newInstance() {
+ return this;
}
+ }
- private static final VerifierRefiner DEFAULT_REFINER = new VerifierRefiner();
+ private static final VerifierRefiner DEFAULT_REFINER = new VerifierRefiner();
}
diff --git a/java/src/com/android/i18n/addressinput/StandardChecks.java b/java/src/com/android/i18n/addressinput/StandardChecks.java
index f243afd..a76591e 100644
--- a/java/src/com/android/i18n/addressinput/StandardChecks.java
+++ b/java/src/com/android/i18n/addressinput/StandardChecks.java
@@ -27,41 +27,41 @@ import java.util.Map;
*/
public class StandardChecks {
- private StandardChecks() {
- }
+ private StandardChecks() {
+ }
- public static final Map<AddressField, List<AddressProblemType>> PROBLEM_MAP;
+ public static final Map<AddressField, List<AddressProblemType>> PROBLEM_MAP;
- static {
- Map<AddressField, List<AddressProblemType>> map =
- new HashMap<AddressField, List<AddressProblemType>>();
+ static {
+ Map<AddressField, List<AddressProblemType>> map =
+ new HashMap<AddressField, List<AddressProblemType>>();
- addToMap(map, AddressField.COUNTRY, AddressProblemType.USING_UNUSED_FIELD,
- AddressProblemType.MISSING_REQUIRED_FIELD, AddressProblemType.UNKNOWN_VALUE);
- addToMap(map, AddressField.ADMIN_AREA, AddressProblemType.USING_UNUSED_FIELD,
- AddressProblemType.MISSING_REQUIRED_FIELD, AddressProblemType.UNKNOWN_VALUE);
- addToMap(map, AddressField.LOCALITY, AddressProblemType.USING_UNUSED_FIELD,
- AddressProblemType.MISSING_REQUIRED_FIELD, AddressProblemType.UNKNOWN_VALUE);
- addToMap(map, AddressField.DEPENDENT_LOCALITY, AddressProblemType.USING_UNUSED_FIELD,
- AddressProblemType.MISSING_REQUIRED_FIELD, AddressProblemType.UNKNOWN_VALUE);
- addToMap(map, AddressField.POSTAL_CODE, AddressProblemType.USING_UNUSED_FIELD,
- AddressProblemType.MISSING_REQUIRED_FIELD, AddressProblemType.UNRECOGNIZED_FORMAT,
- AddressProblemType.MISMATCHING_VALUE);
- addToMap(map, AddressField.STREET_ADDRESS, AddressProblemType.USING_UNUSED_FIELD,
- AddressProblemType.MISSING_REQUIRED_FIELD);
- addToMap(map, AddressField.SORTING_CODE, AddressProblemType.USING_UNUSED_FIELD,
- AddressProblemType.MISSING_REQUIRED_FIELD);
- addToMap(map, AddressField.ORGANIZATION, AddressProblemType.USING_UNUSED_FIELD,
- AddressProblemType.MISSING_REQUIRED_FIELD);
- addToMap(map, AddressField.RECIPIENT, AddressProblemType.USING_UNUSED_FIELD,
- AddressProblemType.MISSING_REQUIRED_FIELD);
+ addToMap(map, AddressField.COUNTRY, AddressProblemType.USING_UNUSED_FIELD,
+ AddressProblemType.MISSING_REQUIRED_FIELD, AddressProblemType.UNKNOWN_VALUE);
+ addToMap(map, AddressField.ADMIN_AREA, AddressProblemType.USING_UNUSED_FIELD,
+ AddressProblemType.MISSING_REQUIRED_FIELD, AddressProblemType.UNKNOWN_VALUE);
+ addToMap(map, AddressField.LOCALITY, AddressProblemType.USING_UNUSED_FIELD,
+ AddressProblemType.MISSING_REQUIRED_FIELD, AddressProblemType.UNKNOWN_VALUE);
+ addToMap(map, AddressField.DEPENDENT_LOCALITY, AddressProblemType.USING_UNUSED_FIELD,
+ AddressProblemType.MISSING_REQUIRED_FIELD, AddressProblemType.UNKNOWN_VALUE);
+ addToMap(map, AddressField.POSTAL_CODE, AddressProblemType.USING_UNUSED_FIELD,
+ AddressProblemType.MISSING_REQUIRED_FIELD, AddressProblemType.UNRECOGNIZED_FORMAT,
+ AddressProblemType.MISMATCHING_VALUE);
+ addToMap(map, AddressField.STREET_ADDRESS, AddressProblemType.USING_UNUSED_FIELD,
+ AddressProblemType.MISSING_REQUIRED_FIELD);
+ addToMap(map, AddressField.SORTING_CODE, AddressProblemType.USING_UNUSED_FIELD,
+ AddressProblemType.MISSING_REQUIRED_FIELD);
+ addToMap(map, AddressField.ORGANIZATION, AddressProblemType.USING_UNUSED_FIELD,
+ AddressProblemType.MISSING_REQUIRED_FIELD);
+ addToMap(map, AddressField.RECIPIENT, AddressProblemType.USING_UNUSED_FIELD,
+ AddressProblemType.MISSING_REQUIRED_FIELD);
- PROBLEM_MAP = Collections.unmodifiableMap(map);
- }
+ PROBLEM_MAP = Collections.unmodifiableMap(map);
+ }
- private static void addToMap(Map<AddressField, List<AddressProblemType>> map,
- AddressField field,
- AddressProblemType... problems) {
- map.put(field, Collections.unmodifiableList(Arrays.asList(problems)));
- }
+ private static void addToMap(Map<AddressField, List<AddressProblemType>> map,
+ AddressField field,
+ AddressProblemType... problems) {
+ map.put(field, Collections.unmodifiableList(Arrays.asList(problems)));
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/Util.java b/java/src/com/android/i18n/addressinput/Util.java
index 0547543..f883c3b 100644
--- a/java/src/com/android/i18n/addressinput/Util.java
+++ b/java/src/com/android/i18n/addressinput/Util.java
@@ -26,201 +26,201 @@ import java.util.regex.Pattern;
* Utility functions used by the address widget.
*/
class Util {
- /**
- * This variable is in upper-case, since we convert the language code to upper case before doing
- * string comparison.
- */
- private static final String LATIN_SCRIPT = "LATN";
+ /**
+ * This variable is in upper-case, since we convert the language code to upper case before doing
+ * string comparison.
+ */
+ private static final String LATIN_SCRIPT = "LATN";
- /**
- * Map of countries that have non-latin local names, with the language that their local names
- * are in. We only list a country here if we have the appropriate data. Only language sub-tags
- * are listed.
- */
- private static final Map<String, String> nonLatinLocalLanguageCountries =
- new HashMap<String, String>();
- static {
- nonLatinLocalLanguageCountries.put("AM", "hy");
- nonLatinLocalLanguageCountries.put("CN", "zh");
- nonLatinLocalLanguageCountries.put("HK", "zh");
- nonLatinLocalLanguageCountries.put("JP", "ja");
- nonLatinLocalLanguageCountries.put("KP", "ko");
- nonLatinLocalLanguageCountries.put("KR", "ko");
- nonLatinLocalLanguageCountries.put("MO", "zh");
- nonLatinLocalLanguageCountries.put("TH", "th");
- nonLatinLocalLanguageCountries.put("TW", "zh");
- nonLatinLocalLanguageCountries.put("VN", "vi");
- }
+ /**
+ * Map of countries that have non-latin local names, with the language that their local names
+ * are in. We only list a country here if we have the appropriate data. Only language sub-tags
+ * are listed.
+ */
+ private static final Map<String, String> nonLatinLocalLanguageCountries =
+ new HashMap<String, String>();
+ static {
+ nonLatinLocalLanguageCountries.put("AM", "hy");
+ nonLatinLocalLanguageCountries.put("CN", "zh");
+ nonLatinLocalLanguageCountries.put("HK", "zh");
+ nonLatinLocalLanguageCountries.put("JP", "ja");
+ nonLatinLocalLanguageCountries.put("KP", "ko");
+ nonLatinLocalLanguageCountries.put("KR", "ko");
+ nonLatinLocalLanguageCountries.put("MO", "zh");
+ nonLatinLocalLanguageCountries.put("TH", "th");
+ nonLatinLocalLanguageCountries.put("TW", "zh");
+ nonLatinLocalLanguageCountries.put("VN", "vi");
+ }
- /**
- * Cannot instantiate this class - private constructor.
- */
- private Util() {
- }
+ /**
+ * Cannot instantiate this class - private constructor.
+ */
+ private Util() {
+ }
- /**
- * Returns true if the language code is explicitly marked to be in the latin script. For
- * example, "zh-Latn" would return true, but "zh-TW", "en" and "zh" would all return false.
- */
- static boolean isExplicitLatinScript(String languageCode) {
- // Convert to upper-case for easier comparison.
- languageCode = languageCode.toUpperCase();
- // Check to see if the language code contains a script modifier.
- final Pattern languageCodePattern = Pattern.compile("\\w{2,3}[-_](\\w{4})");
- Matcher m = languageCodePattern.matcher(languageCode);
- if (m.lookingAt()) {
- String script = m.group(1);
- if (script.equals(LATIN_SCRIPT)) {
- return true;
- }
- }
- return false;
+ /**
+ * Returns true if the language code is explicitly marked to be in the latin script. For
+ * example, "zh-Latn" would return true, but "zh-TW", "en" and "zh" would all return false.
+ */
+ static boolean isExplicitLatinScript(String languageCode) {
+ // Convert to upper-case for easier comparison.
+ languageCode = languageCode.toUpperCase();
+ // Check to see if the language code contains a script modifier.
+ final Pattern languageCodePattern = Pattern.compile("\\w{2,3}[-_](\\w{4})");
+ Matcher m = languageCodePattern.matcher(languageCode);
+ if (m.lookingAt()) {
+ String script = m.group(1);
+ if (script.equals(LATIN_SCRIPT)) {
+ return true;
+ }
}
+ return false;
+ }
- /**
- * Returns the language subtag of a language code. For example, returns "zh" if given "zh-Hans",
- * "zh-CN" or other "zh" variants. If no language subtag can be found or the language tag is
- * malformed, returns "und".
- */
- static String getLanguageSubtag(String languageCode) {
- final Pattern languageCodePattern = Pattern
- .compile("(\\w{2,3})(?:[-_]\\w{4})?(?:[-_]\\w{2})?");
- Matcher m = languageCodePattern.matcher(languageCode);
- if (m.matches()) {
- return m.group(1).toLowerCase();
- }
- return "und";
+ /**
+ * Returns the language subtag of a language code. For example, returns "zh" if given "zh-Hans",
+ * "zh-CN" or other "zh" variants. If no language subtag can be found or the language tag is
+ * malformed, returns "und".
+ */
+ static String getLanguageSubtag(String languageCode) {
+ final Pattern languageCodePattern = Pattern
+ .compile("(\\w{2,3})(?:[-_]\\w{4})?(?:[-_]\\w{2})?");
+ Matcher m = languageCodePattern.matcher(languageCode);
+ if (m.matches()) {
+ return m.group(1).toLowerCase();
}
+ return "und";
+ }
- /**
- * Trims the string. If the field is empty after trimming, returns null instead. Note that this
- * only trims ASCII white-space.
- */
- static String trimToNull(String originalStr) {
- if (originalStr == null) {
- return null;
- }
- String trimmedString = originalStr.trim();
- return (trimmedString.length() == 0) ? null : trimmedString;
+ /**
+ * Trims the string. If the field is empty after trimming, returns null instead. Note that this
+ * only trims ASCII white-space.
+ */
+ static String trimToNull(String originalStr) {
+ if (originalStr == null) {
+ return null;
}
+ String trimmedString = originalStr.trim();
+ return (trimmedString.length() == 0) ? null : trimmedString;
+ }
- /**
- * Throws an exception if the object is null, with a generic error message.
- */
- static void checkNotNull(Object o) throws NullPointerException {
- checkNotNull(o, "This object should not be null.");
- }
+ /**
+ * Throws an exception if the object is null, with a generic error message.
+ */
+ static void checkNotNull(Object o) throws NullPointerException {
+ checkNotNull(o, "This object should not be null.");
+ }
- /**
- * Throws an exception if the object is null, with the error message supplied.
- */
- static void checkNotNull(Object o, String message) throws NullPointerException {
- if (o == null) {
- throw new NullPointerException(message);
- }
+ /**
+ * Throws an exception if the object is null, with the error message supplied.
+ */
+ static void checkNotNull(Object o, String message) throws NullPointerException {
+ if (o == null) {
+ throw new NullPointerException(message);
}
+ }
- /**
- * Joins input string with the given separator. If an input string is null, it will be skipped.
- */
- static String joinAndSkipNulls(String separator, String... strings) {
- StringBuilder sb = null;
- for (String s : strings) {
- if (s != null) {
- s = s.trim();
- if (s.length() > 0) {
- if (sb == null) {
- sb = new StringBuilder(s);
- } else {
- sb.append(separator).append(s);
- }
- }
- }
+ /**
+ * Joins input string with the given separator. If an input string is null, it will be skipped.
+ */
+ static String joinAndSkipNulls(String separator, String... strings) {
+ StringBuilder sb = null;
+ for (String s : strings) {
+ if (s != null) {
+ s = s.trim();
+ if (s.length() > 0) {
+ if (sb == null) {
+ sb = new StringBuilder(s);
+ } else {
+ sb.append(separator).append(s);
+ }
}
- return sb == null ? null : sb.toString();
+ }
}
+ return sb == null ? null : sb.toString();
+ }
- /**
- * Builds a map of the lower-cased values of the keys, names and local names provided. Each name
- * and local name is mapped to its respective key in the map.
- *
- * @throws IllegalStateException if the names or lnames array is greater than the keys array.
- */
- static Map<String, String> buildNameToKeyMap(String[] keys, String[] names, String[] lnames) {
- if (keys == null) {
- return null;
- }
+ /**
+ * Builds a map of the lower-cased values of the keys, names and local names provided. Each name
+ * and local name is mapped to its respective key in the map.
+ *
+ * @throws IllegalStateException if the names or lnames array is greater than the keys array.
+ */
+ static Map<String, String> buildNameToKeyMap(String[] keys, String[] names, String[] lnames) {
+ if (keys == null) {
+ return null;
+ }
- Map<String, String> nameToKeyMap = new HashMap<String, String>();
+ Map<String, String> nameToKeyMap = new HashMap<String, String>();
- int keyLength = keys.length;
- for (String k : keys) {
- nameToKeyMap.put(k.toLowerCase(), k);
- }
- if (names != null) {
- if (names.length > keyLength) {
- throw new IllegalStateException(
- "names length (" + names.length + ") is greater than keys length (" +
- keys.length + ")");
- }
- for (int i = 0; i < keyLength; i++) {
- // If we have less names than keys, we ignore all missing names. This happens
- // generally because reg-ex splitting methods on different platforms (java, js etc)
- // behave differently in the default case. Since missing names are fine, we opt to
- // be more robust here.
- if (i < names.length && names[i].length() > 0) {
- nameToKeyMap.put(names[i].toLowerCase(), keys[i]);
- }
- }
+ int keyLength = keys.length;
+ for (String k : keys) {
+ nameToKeyMap.put(k.toLowerCase(), k);
+ }
+ if (names != null) {
+ if (names.length > keyLength) {
+ throw new IllegalStateException(
+ "names length (" + names.length + ") is greater than keys length (" +
+ keys.length + ")");
+ }
+ for (int i = 0; i < keyLength; i++) {
+ // If we have less names than keys, we ignore all missing names. This happens
+ // generally because reg-ex splitting methods on different platforms (java, js etc)
+ // behave differently in the default case. Since missing names are fine, we opt to
+ // be more robust here.
+ if (i < names.length && names[i].length() > 0) {
+ nameToKeyMap.put(names[i].toLowerCase(), keys[i]);
}
- if (lnames != null) {
- if (lnames.length > keyLength) {
- throw new IllegalStateException(
- "lnames length (" + lnames.length + ") is greater than keys length (" +
- keys.length + ")");
- }
- for (int i = 0; i < keyLength; i++) {
- if (i < lnames.length && lnames[i].length() > 0) {
- nameToKeyMap.put(lnames[i].toLowerCase(), keys[i]);
- }
- }
+ }
+ }
+ if (lnames != null) {
+ if (lnames.length > keyLength) {
+ throw new IllegalStateException(
+ "lnames length (" + lnames.length + ") is greater than keys length (" +
+ keys.length + ")");
+ }
+ for (int i = 0; i < keyLength; i++) {
+ if (i < lnames.length && lnames[i].length() > 0) {
+ nameToKeyMap.put(lnames[i].toLowerCase(), keys[i]);
}
- return nameToKeyMap;
+ }
}
+ return nameToKeyMap;
+ }
- /**
- * Returns a language code that the widget can use when fetching data, based on a {@link
- * java.util.Locale} language and the current selected country in the address widget. This
- * method is necessary since we have to determine later whether a language is "local" or "latin"
- * for certain countries.
- *
- * @param language the current user language
- * @param currentCountry the current selected country
- * @return a language code string in BCP-47 format (e.g. "en", "zh-Latn", "zh-Hans" or
- * "en-US").
- */
- static String getWidgetCompatibleLanguageCode(Locale language, String currentCountry) {
- String country = currentCountry.toUpperCase();
- // Only do something if the country is one of those where we have names in the local
- // language as well as in latin script.
- if (nonLatinLocalLanguageCountries.containsKey(country)) {
- String languageTag = language.getLanguage();
- // Only do something if the language tag is _not_ the local language.
- if (!languageTag.equals(nonLatinLocalLanguageCountries.get(country))) {
- // Build up the language tag with the country and language specified, and add in the
- // script-tag of "Latn" explicitly, since this is _not_ a local language. This means
- // that we might create a language tag of "th-Latn", which is not what the actual
- // language being used is, but it indicates that we prefer "Latn" names to whatever
- // the local alternative was.
- StringBuilder languageTagBuilder = new StringBuilder(languageTag);
- languageTagBuilder.append("_latn");
- if (language.getCountry().length() > 0) {
- languageTagBuilder.append("_");
- languageTagBuilder.append(language.getCountry());
- }
- return languageTagBuilder.toString();
- }
+ /**
+ * Returns a language code that the widget can use when fetching data, based on a {@link
+ * java.util.Locale} language and the current selected country in the address widget. This
+ * method is necessary since we have to determine later whether a language is "local" or "latin"
+ * for certain countries.
+ *
+ * @param language the current user language
+ * @param currentCountry the current selected country
+ * @return a language code string in BCP-47 format (e.g. "en", "zh-Latn", "zh-Hans" or
+ * "en-US").
+ */
+ static String getWidgetCompatibleLanguageCode(Locale language, String currentCountry) {
+ String country = currentCountry.toUpperCase();
+ // Only do something if the country is one of those where we have names in the local
+ // language as well as in latin script.
+ if (nonLatinLocalLanguageCountries.containsKey(country)) {
+ String languageTag = language.getLanguage();
+ // Only do something if the language tag is _not_ the local language.
+ if (!languageTag.equals(nonLatinLocalLanguageCountries.get(country))) {
+ // Build up the language tag with the country and language specified, and add in the
+ // script-tag of "Latn" explicitly, since this is _not_ a local language. This means
+ // that we might create a language tag of "th-Latn", which is not what the actual
+ // language being used is, but it indicates that we prefer "Latn" names to whatever
+ // the local alternative was.
+ StringBuilder languageTagBuilder = new StringBuilder(languageTag);
+ languageTagBuilder.append("_latn");
+ if (language.getCountry().length() > 0) {
+ languageTagBuilder.append("_");
+ languageTagBuilder.append(language.getCountry());
}
- return language.toString();
+ return languageTagBuilder.toString();
+ }
}
+ return language.toString();
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/testing/AddressDataMapLoader.java b/java/src/com/android/i18n/addressinput/testing/AddressDataMapLoader.java
index 3310ea4..072356d 100644
--- a/java/src/com/android/i18n/addressinput/testing/AddressDataMapLoader.java
+++ b/java/src/com/android/i18n/addressinput/testing/AddressDataMapLoader.java
@@ -27,30 +27,30 @@ import java.util.Map;
*/
public class AddressDataMapLoader {
- private static final String DATA_PATH = "/countryinfo.txt";
+ private static final String DATA_PATH = "/countryinfo.txt";
- private AddressDataMapLoader() {
- }
+ private AddressDataMapLoader() {
+ }
- public static final Map<String, String> DATA;
+ public static final Map<String, String> DATA;
- static {
- DATA = new HashMap<String, String>();
- try {
- BufferedReader br = new BufferedReader(
- new InputStreamReader(AddressDataMapLoader.class.getResourceAsStream(DATA_PATH),
- "utf-8"));
- String line = null;
- while (null != (line = br.readLine())) {
- line = line.trim();
- if (line.length() == 0 || line.charAt(0) == '#') {
- continue;
- }
- int x = line.indexOf('=');
- DATA.put(line.substring(0, x), line.substring(x + 1));
- }
- } catch (IOException e) {
- System.err.println("unable to create map: " + e.getMessage());
+ static {
+ DATA = new HashMap<String, String>();
+ try {
+ BufferedReader br = new BufferedReader(
+ new InputStreamReader(AddressDataMapLoader.class.getResourceAsStream(DATA_PATH),
+ "utf-8"));
+ String line = null;
+ while (null != (line = br.readLine())) {
+ line = line.trim();
+ if (line.length() == 0 || line.charAt(0) == '#') {
+ continue;
}
+ int x = line.indexOf('=');
+ DATA.put(line.substring(0, x), line.substring(x + 1));
+ }
+ } catch (IOException e) {
+ System.err.println("unable to create map: " + e.getMessage());
}
+ }
}
diff --git a/java/src/com/android/i18n/addressinput/testing/AsyncTestCase.java b/java/src/com/android/i18n/addressinput/testing/AsyncTestCase.java
index 69c3020..d8a5a43 100644
--- a/java/src/com/android/i18n/addressinput/testing/AsyncTestCase.java
+++ b/java/src/com/android/i18n/addressinput/testing/AsyncTestCase.java
@@ -25,51 +25,51 @@ import java.util.concurrent.TimeoutException;
* like the corresponding methods in GWTTestCase for testing asynchronous code.
*/
public abstract class AsyncTestCase extends TestCase {
- /**
- * Tracks whether this test is completely done.
- */
- private boolean mTestIsFinished;
+ /**
+ * Tracks whether this test is completely done.
+ */
+ private boolean testIsFinished;
- /**
- * The system time in milliseconds when the test should time out.
- */
- private long mTestTimeoutMillis;
+ /**
+ * The system time in milliseconds when the test should time out.
+ */
+ private long testTimeoutMillis;
- /**
- * Puts the current test in asynchronous mode.
- *
- * @param timeoutMillis time to wait before failing the test for timing out
- */
- protected void delayTestFinish(int timeoutMillis) {
- mTestTimeoutMillis = System.currentTimeMillis() + timeoutMillis;
- }
+ /**
+ * Puts the current test in asynchronous mode.
+ *
+ * @param timeoutMillis time to wait before failing the test for timing out
+ */
+ protected void delayTestFinish(int timeoutMillis) {
+ testTimeoutMillis = System.currentTimeMillis() + timeoutMillis;
+ }
- /**
- * Causes this test to succeed during asynchronous mode.
- */
- protected void finishTest() {
- mTestIsFinished = true;
- synchronized (this) {
- notify();
- }
+ /**
+ * Causes this test to succeed during asynchronous mode.
+ */
+ protected void finishTest() {
+ testIsFinished = true;
+ synchronized (this) {
+ notify();
}
+ }
- @Override
- protected void runTest() throws Throwable {
- mTestIsFinished = false;
- mTestTimeoutMillis = 0;
- super.runTest();
+ @Override
+ protected void runTest() throws Throwable {
+ testIsFinished = false;
+ testTimeoutMillis = 0;
+ super.runTest();
- if (mTestTimeoutMillis > 0) {
- long timeoutMillis = mTestTimeoutMillis - System.currentTimeMillis();
- if (timeoutMillis > 0) {
- synchronized (this) {
- wait(timeoutMillis);
- }
- }
- if (!mTestIsFinished) {
- throw new TimeoutException("Waited " + timeoutMillis + " ms!");
- }
+ if (testTimeoutMillis > 0) {
+ long timeoutMillis = testTimeoutMillis - System.currentTimeMillis();
+ if (timeoutMillis > 0) {
+ synchronized (this) {
+ wait(timeoutMillis);
}
+ }
+ if (!testIsFinished) {
+ throw new TimeoutException("Waited " + timeoutMillis + " ms!");
+ }
}
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/AddressDataTest.java b/java/test/com/android/i18n/addressinput/AddressDataTest.java
index 7b211b4..870b318 100644
--- a/java/test/com/android/i18n/addressinput/AddressDataTest.java
+++ b/java/test/com/android/i18n/addressinput/AddressDataTest.java
@@ -22,45 +22,45 @@ import junit.framework.TestCase;
* Tests for the AddressData class.
*/
public class AddressDataTest extends TestCase {
- private static final String ADDRESS_LINE = "First address line";
+ private static final String ADDRESS_LINE = "First address line";
- public void testSetAddressLine() {
- AddressData.Builder builder = new AddressData.Builder();
- builder = builder.setAddress("\n " + ADDRESS_LINE);
- AddressData ad = builder.build();
- assertEquals(ADDRESS_LINE, ad.getAddressLine1());
- assertEquals(null, ad.getAddressLine2());
- }
+ public void testSetAddressLine() {
+ AddressData.Builder builder = new AddressData.Builder();
+ builder = builder.setAddress("\n " + ADDRESS_LINE);
+ AddressData ad = builder.build();
+ assertEquals(ADDRESS_LINE, ad.getAddressLine1());
+ assertEquals(null, ad.getAddressLine2());
+ }
- public void testAddressLineNormalisation() {
- AddressData address = new AddressData.Builder().setAddressLine1(null)
- .setAddressLine2(ADDRESS_LINE).build();
- AddressData copiedAddress = new AddressData.Builder(address).build();
- assertEquals(ADDRESS_LINE, copiedAddress.getAddressLine1());
- assertEquals(null, copiedAddress.getAddressLine2());
- }
+ public void testAddressLineNormalisation() {
+ AddressData address = new AddressData.Builder().setAddressLine1(null)
+ .setAddressLine2(ADDRESS_LINE).build();
+ AddressData copiedAddress = new AddressData.Builder(address).build();
+ assertEquals(ADDRESS_LINE, copiedAddress.getAddressLine1());
+ assertEquals(null, copiedAddress.getAddressLine2());
+ }
- public void testAddressLineNormalisationWithNewLineCharacters() {
- AddressData address =
- new AddressData.Builder().setAddressLine1(ADDRESS_LINE + "\n" + ADDRESS_LINE).build();
- AddressData copiedAddress = new AddressData.Builder(address).build();
- assertEquals(ADDRESS_LINE, copiedAddress.getAddressLine1());
- assertEquals(ADDRESS_LINE, copiedAddress.getAddressLine2());
- }
+ public void testAddressLineNormalisationWithNewLineCharacters() {
+ AddressData address =
+ new AddressData.Builder().setAddressLine1(ADDRESS_LINE + "\n" + ADDRESS_LINE).build();
+ AddressData copiedAddress = new AddressData.Builder(address).build();
+ assertEquals(ADDRESS_LINE, copiedAddress.getAddressLine1());
+ assertEquals(ADDRESS_LINE, copiedAddress.getAddressLine2());
+ }
- public void testNoAdminArea() {
- AddressData address = new AddressData.Builder().build();
- assertEquals(null, address.getAdministrativeArea());
- }
+ public void testNoAdminArea() {
+ AddressData address = new AddressData.Builder().build();
+ assertEquals(null, address.getAdministrativeArea());
+ }
- public void testSetLanguageCode() throws Exception {
- AddressData address = new AddressData.Builder().setCountry("TW")
- // Taipei City
- .setAdminArea("\u53F0\u5317\u5E02")
- // Da-an District
- .setLocality("\u5927\u5B89\u5340")
- .build();
- address = new AddressData.Builder(address).setLanguageCode("zh-latn").build();
- assertEquals("zh-latn", address.getLanguageCode());
- }
+ public void testSetLanguageCode() throws Exception {
+ AddressData address = new AddressData.Builder().setCountry("TW")
+ // Taipei City
+ .setAdminArea("\u53F0\u5317\u5E02")
+ // Da-an District
+ .setLocality("\u5927\u5B89\u5340")
+ .build();
+ address = new AddressData.Builder(address).setLanguageCode("zh-latn").build();
+ assertEquals("zh-latn", address.getLanguageCode());
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/AddressFieldTest.java b/java/test/com/android/i18n/addressinput/AddressFieldTest.java
index aa0a741..8009bd5 100644
--- a/java/test/com/android/i18n/addressinput/AddressFieldTest.java
+++ b/java/test/com/android/i18n/addressinput/AddressFieldTest.java
@@ -23,11 +23,11 @@ import junit.framework.TestCase;
*/
public class AddressFieldTest extends TestCase {
- public void testOf() throws Exception {
- assertEquals(AddressField.COUNTRY, AddressField.of('R'));
- }
+ public void testOf() throws Exception {
+ assertEquals(AddressField.COUNTRY, AddressField.of('R'));
+ }
- public void testGetChar() throws Exception {
- assertEquals('R', AddressField.COUNTRY.getChar());
- }
+ public void testGetChar() throws Exception {
+ assertEquals('R', AddressField.COUNTRY.getChar());
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/AddressProblemsTest.java b/java/test/com/android/i18n/addressinput/AddressProblemsTest.java
index 14cef05..8f6740b 100644
--- a/java/test/com/android/i18n/addressinput/AddressProblemsTest.java
+++ b/java/test/com/android/i18n/addressinput/AddressProblemsTest.java
@@ -22,16 +22,16 @@ import junit.framework.TestCase;
* Tests for the AddressProblems class.
*/
public class AddressProblemsTest extends TestCase {
- public void testAddError() {
- AddressProblems ap = new AddressProblems();
- ap.add(AddressField.POSTAL_CODE, AddressProblemType.MISSING_REQUIRED_FIELD);
- assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
- ap.getProblem(AddressField.POSTAL_CODE));
- }
+ public void testAddError() {
+ AddressProblems ap = new AddressProblems();
+ ap.add(AddressField.POSTAL_CODE, AddressProblemType.MISSING_REQUIRED_FIELD);
+ assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
+ ap.getProblem(AddressField.POSTAL_CODE));
+ }
- public void testEmptyErrorList() {
- AddressProblems ap = new AddressProblems();
- assertNull(ap.getProblem(AddressField.POSTAL_CODE));
- assertTrue(ap.isEmpty());
- }
+ public void testEmptyErrorList() {
+ AddressProblems ap = new AddressProblems();
+ assertNull(ap.getProblem(AddressField.POSTAL_CODE));
+ assertTrue(ap.isEmpty());
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/AddressVerificationDataTest.java b/java/test/com/android/i18n/addressinput/AddressVerificationDataTest.java
index b57955a..40521ab 100644
--- a/java/test/com/android/i18n/addressinput/AddressVerificationDataTest.java
+++ b/java/test/com/android/i18n/addressinput/AddressVerificationDataTest.java
@@ -25,80 +25,80 @@ import junit.framework.TestCase;
*/
public class AddressVerificationDataTest extends TestCase {
- private static final AddressVerificationData ADDRESS_DATA =
- new AddressVerificationData(AddressDataMapLoader.DATA);
-
- public void testParseAllData() {
- for (String key : ADDRESS_DATA.keys()) {
- AddressVerificationNodeData nodeData = ADDRESS_DATA.get(key);
- assertNotNull(key + " maps to null value.", nodeData);
- assertNotNull("Id is required", nodeData.get(AddressDataKey.ID));
- }
- }
-
- public void testLoadingCountries() {
- AddressVerificationNodeData nodeData = ADDRESS_DATA.get("data");
- String[] countries = nodeData.get(AddressDataKey.COUNTRIES).split("~");
- assertTrue(countries.length > 0);
- }
-
- public void testUsData() {
- AddressVerificationNodeData nodeData = ADDRESS_DATA.get("data/US");
- assertEquals("data/US", nodeData.get(AddressDataKey.ID));
- assertNotNull(nodeData.get(AddressDataKey.SUB_KEYS));
- assertNotNull(nodeData.get(AddressDataKey.SUB_NAMES));
- assertEquals("en", nodeData.get(AddressDataKey.LANG));
+ private static final AddressVerificationData ADDRESS_DATA =
+ new AddressVerificationData(AddressDataMapLoader.DATA);
+
+ public void testParseAllData() {
+ for (String key : ADDRESS_DATA.keys()) {
+ AddressVerificationNodeData nodeData = ADDRESS_DATA.get(key);
+ assertNotNull(key + " maps to null value.", nodeData);
+ assertNotNull("Id is required", nodeData.get(AddressDataKey.ID));
}
-
- public void testCaData() {
- AddressVerificationNodeData nodeData = ADDRESS_DATA.get("data/CA");
- String names = nodeData.get(AddressDataKey.SUB_NAMES);
- String keys = nodeData.get(AddressDataKey.SUB_KEYS);
-
- assertEquals("data/CA", nodeData.get(AddressDataKey.ID));
- assertEquals("en", nodeData.get(AddressDataKey.LANG));
-
- assertEquals("AB~BC~MB~NB~NL~NT~NS~NU~ON~PE~QC~SK~YT", keys);
- assertEquals("Alberta~British Columbia~Manitoba~New Brunswick" +
- "~Newfoundland and Labrador~Northwest Territories~Nova Scotia~Nunavut" +
- "~Ontario~Prince Edward Island~Quebec~Saskatchewan~Yukon",
- names);
- }
-
- public void testCaFrenchData() {
- AddressVerificationNodeData nodeData = ADDRESS_DATA.get("data/CA--fr");
- String names = nodeData.get(AddressDataKey.SUB_NAMES);
- String keys = nodeData.get(AddressDataKey.SUB_KEYS);
-
- assertEquals("data/CA--fr", nodeData.get(AddressDataKey.ID));
- assertEquals("fr", nodeData.get(AddressDataKey.LANG));
- assertEquals("AB~BC~PE~MB~NB~NS~NU~ON~QC~SK~NL~NT~YT", keys);
- assertTrue(names.contains("Colombie"));
- }
-
- public void testBackSlashUnEscaped() {
- for (String lookupKey : ADDRESS_DATA.keys()) {
- AddressVerificationNodeData nodeData = ADDRESS_DATA.get(lookupKey);
- for (AddressDataKey dataKey : AddressDataKey.values()) {
- String val = nodeData.get(dataKey);
- if (val != null) {
- assertFalse("Backslashes need to be unescaped: " + val, val.contains("\\\\"));
- }
- }
+ }
+
+ public void testLoadingCountries() {
+ AddressVerificationNodeData nodeData = ADDRESS_DATA.get("data");
+ String[] countries = nodeData.get(AddressDataKey.COUNTRIES).split("~");
+ assertTrue(countries.length > 0);
+ }
+
+ public void testUsData() {
+ AddressVerificationNodeData nodeData = ADDRESS_DATA.get("data/US");
+ assertEquals("data/US", nodeData.get(AddressDataKey.ID));
+ assertNotNull(nodeData.get(AddressDataKey.SUB_KEYS));
+ assertNotNull(nodeData.get(AddressDataKey.SUB_NAMES));
+ assertEquals("en", nodeData.get(AddressDataKey.LANG));
+ }
+
+ public void testCaData() {
+ AddressVerificationNodeData nodeData = ADDRESS_DATA.get("data/CA");
+ String names = nodeData.get(AddressDataKey.SUB_NAMES);
+ String keys = nodeData.get(AddressDataKey.SUB_KEYS);
+
+ assertEquals("data/CA", nodeData.get(AddressDataKey.ID));
+ assertEquals("en", nodeData.get(AddressDataKey.LANG));
+
+ assertEquals("AB~BC~MB~NB~NL~NT~NS~NU~ON~PE~QC~SK~YT", keys);
+ assertEquals("Alberta~British Columbia~Manitoba~New Brunswick" +
+ "~Newfoundland and Labrador~Northwest Territories~Nova Scotia~Nunavut" +
+ "~Ontario~Prince Edward Island~Quebec~Saskatchewan~Yukon",
+ names);
+ }
+
+ public void testCaFrenchData() {
+ AddressVerificationNodeData nodeData = ADDRESS_DATA.get("data/CA--fr");
+ String names = nodeData.get(AddressDataKey.SUB_NAMES);
+ String keys = nodeData.get(AddressDataKey.SUB_KEYS);
+
+ assertEquals("data/CA--fr", nodeData.get(AddressDataKey.ID));
+ assertEquals("fr", nodeData.get(AddressDataKey.LANG));
+ assertEquals("AB~BC~PE~MB~NB~NS~NU~ON~QC~SK~NL~NT~YT", keys);
+ assertTrue(names.contains("Colombie"));
+ }
+
+ public void testBackSlashUnEscaped() {
+ for (String lookupKey : ADDRESS_DATA.keys()) {
+ AddressVerificationNodeData nodeData = ADDRESS_DATA.get(lookupKey);
+ for (AddressDataKey dataKey : AddressDataKey.values()) {
+ String val = nodeData.get(dataKey);
+ if (val != null) {
+ assertFalse("Backslashes need to be unescaped: " + val, val.contains("\\\\"));
}
-
- // Spot check.
- assertEquals("Kazhakstan's postal code pattern mismatched", "\\d{6}",
- ADDRESS_DATA.get("data/KZ").get(AddressDataKey.ZIP));
+ }
}
- public void testExampleData() {
- assertNotNull("Expects example data.", AddressDataMapLoader.DATA.get("examples"));
- assertNotNull("Expects example US address.",
- AddressDataMapLoader.DATA.get("examples/US/local/en"));
- assertEquals("'examples/TW/local/zh_Hant' and 'examples/TW/local/_default' should " +
- "return same value.",
- AddressDataMapLoader.DATA.get("examples/TW/local/zh_Hant"),
- AddressDataMapLoader.DATA.get("examples/TW/local/_default"));
- }
+ // Spot check.
+ assertEquals("Kazhakstan's postal code pattern mismatched", "\\d{6}",
+ ADDRESS_DATA.get("data/KZ").get(AddressDataKey.ZIP));
+ }
+
+ public void testExampleData() {
+ assertNotNull("Expects example data.", AddressDataMapLoader.DATA.get("examples"));
+ assertNotNull("Expects example US address.",
+ AddressDataMapLoader.DATA.get("examples/US/local/en"));
+ assertEquals("'examples/TW/local/zh_Hant' and 'examples/TW/local/_default' should " +
+ "return same value.",
+ AddressDataMapLoader.DATA.get("examples/TW/local/zh_Hant"),
+ AddressDataMapLoader.DATA.get("examples/TW/local/_default"));
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/AddressWidgetUiComponentProviderTest.java b/java/test/com/android/i18n/addressinput/AddressWidgetUiComponentProviderTest.java
index b9c08bd..d519728 100644
--- a/java/test/com/android/i18n/addressinput/AddressWidgetUiComponentProviderTest.java
+++ b/java/test/com/android/i18n/addressinput/AddressWidgetUiComponentProviderTest.java
@@ -34,120 +34,118 @@ import junit.framework.Assert;
/**
* Test class for {@link AddressWidgetUiComponentProvider}.
*/
-public class AddressWidgetUiComponentProviderTest
- extends ActivityInstrumentationTestCase2<TestActivity> {
- private AddressWidget widget;
- private AddressWidgetUiComponentProvider componentProvider;
- private LinearLayout container;
- private AddressData address;
- private Context context;
- private int customTextViewCounter;
- private int customProgressDialogCounter;
-
- public AddressWidgetUiComponentProviderTest() {
- super(TestActivity.class);
+public class AddressWidgetUiComponentProviderTest
+ extends ActivityInstrumentationTestCase2<TestActivity> {
+ private AddressWidget widget;
+ private AddressWidgetUiComponentProvider componentProvider;
+ private LinearLayout container;
+ private AddressData address;
+ private Context context;
+ private int customTextViewCounter;
+ private int customProgressDialogCounter;
+
+ public AddressWidgetUiComponentProviderTest() {
+ super(TestActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ AddressData.Builder builder = new AddressData.Builder()
+ .setCountry("US")
+ .setLanguageCode("en")
+ .setAddressLine1("1098 Alta Ave")
+ .setAdminArea("CA");
+ address = builder.build();
+ context = getActivity();
+ container = new LinearLayout(context);
+ }
+
+ public void testCustomWidgets() {
+ customTextViewCounter = 0;
+ customProgressDialogCounter = 0;
+ componentProvider = new TestComponentProvider(context);
+ widget = new AddressWidget(context, container, new FormOptions.Builder().build(),
+ new SimpleClientCacheManager(), componentProvider);
+ widget.renderFormWithSavedAddress(address);
+
+ for (AddressField field : AddressField.values()) {
+ if (field.equals(AddressField.COUNTRY)) {
+ continue;
+ }
+
+ View view = widget.getViewForField(field);
+ if (view instanceof EditText) {
+ assertTrue("Field " + field + " does not use customized edit text widget.",
+ view instanceof CustomEditText);
+ } else if (view instanceof Spinner) {
+ assertTrue("Field " + field + " does not use customized spinner widget.",
+ view instanceof CustomSpinner);
+ assertTrue("Field " + field + " does not use customized ArrayAdapter.",
+ ((Spinner) view).getAdapter() instanceof CustomArrayAdapter);
+ }
}
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- AddressData.Builder builder = new AddressData.Builder()
- .setCountry("US")
- .setLanguageCode("en")
- .setAddressLine1("1098 Alta Ave")
- .setAdminArea("CA");
- address = builder.build();
- context = getActivity();
- container = new LinearLayout(context);
+
+ assertTrue("Custom TextView label not used.", customTextViewCounter > 0);
+ assertTrue("Custom ProgressDialog not used.", customProgressDialogCounter > 0);
+ }
+
+ private void increaseTextViewCounter() {
+ customTextViewCounter++;
+ }
+
+ private void increaseProgressDialogCounter() {
+ customProgressDialogCounter++;
+ }
+
+ private class CustomEditText extends EditText {
+ CustomEditText(Context context) {
+ super(context);
}
-
- public void testCustomWidgets() {
- customTextViewCounter = 0;
- customProgressDialogCounter = 0;
- componentProvider = new TestComponentProvider(context);
- widget = new AddressWidget(context, container, new FormOptions.Builder().build(),
- new SimpleClientCacheManager(), componentProvider);
- widget.renderFormWithSavedAddress(address);
-
- for (AddressField field : AddressField.values()) {
- if (field.equals(AddressField.COUNTRY)) {
- continue;
- }
-
- View view = widget.getViewForField(field);
- if (view instanceof EditText) {
- assertTrue("Field " + field + " does not use customized edit text widget.",
- view instanceof CustomEditText);
- } else if (view instanceof Spinner) {
- assertTrue("Field " + field + " does not use customized spinner widget.",
- view instanceof CustomSpinner);
- assertTrue("Field " + field + " does not use customized ArrayAdapter.",
- ((Spinner) view).getAdapter() instanceof CustomArrayAdapter);
- }
- }
-
- assertTrue("Custom TextView label not used.", customTextViewCounter > 0);
- assertTrue("Custom ProgressDialog not used.", customProgressDialogCounter > 0);
+ }
+
+ private class CustomSpinner extends Spinner {
+ CustomSpinner(Context context) {
+ super(context);
+ }
+ }
+
+ private class CustomArrayAdapter<String> extends ArrayAdapter {
+ CustomArrayAdapter(Context context, int id) {
+ super(context, id);
}
-
- private void increaseTextViewCounter() {
- customTextViewCounter++;
+ }
+
+ private class TestComponentProvider extends AddressWidgetUiComponentProvider {
+ TestComponentProvider(Context context) {
+ super(context);
}
-
- private void increaseProgressDialogCounter() {
- customProgressDialogCounter++;
+
+ protected TextView createUiLabel(CharSequence label, AddressField.WidthType widthType) {
+ TextView result = new TextView(mContext);
+ result.setText(label);
+ AddressWidgetUiComponentProviderTest.this.increaseTextViewCounter();
+ return result;
}
-
- private class CustomEditText extends EditText {
- CustomEditText(Context context) {
- super(context);
- }
+
+ protected EditText createUiTextField(AddressField.WidthType widthType) {
+ return new CustomEditText(mContext);
}
- private class CustomSpinner extends Spinner {
- CustomSpinner(Context context) {
- super(context);
- }
+ protected Spinner createUiPickerSpinner(AddressField.WidthType widthType) {
+ return new CustomSpinner(mContext);
}
-
- private class CustomArrayAdapter<String> extends ArrayAdapter {
- CustomArrayAdapter(Context context, int id) {
- super(context, id);
- }
+
+ protected ArrayAdapter<String> createUiPickerAdapter(AddressField.WidthType widthType) {
+ ArrayAdapter<String> result = new CustomArrayAdapter<String>(
+ context, android.R.layout.simple_spinner_item);
+ result.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ return result;
}
-
- private class TestComponentProvider extends AddressWidgetUiComponentProvider {
- TestComponentProvider(Context context) {
- super(context);
- }
-
- protected TextView createUiLabel(CharSequence label, AddressField.WidthType widthType) {
- TextView result = new TextView(mContext);
- result.setText(label);
- AddressWidgetUiComponentProviderTest.this.increaseTextViewCounter();
- return result;
- }
-
- protected EditText createUiTextField(AddressField.WidthType widthType) {
- return new CustomEditText(mContext);
- }
-
- protected Spinner createUiPickerSpinner(AddressField.WidthType widthType) {
- return new CustomSpinner(mContext);
- }
-
- protected ArrayAdapter<String> createUiPickerAdapter(AddressField.WidthType widthType) {
- ArrayAdapter<String> result =
- new CustomArrayAdapter<String>(
- mContext, android.R.layout.simple_spinner_item);
- result.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- return result;
- }
-
- protected ProgressDialog getUiActivityIndicatorView() {
- AddressWidgetUiComponentProviderTest.this.increaseProgressDialogCounter();
- return super.getUiActivityIndicatorView();
- }
+
+ protected ProgressDialog getUiActivityIndicatorView() {
+ AddressWidgetUiComponentProviderTest.this.increaseProgressDialogCounter();
+ return super.getUiActivityIndicatorView();
}
+ }
}
- \ No newline at end of file
diff --git a/java/test/com/android/i18n/addressinput/AsyncTestCaseTest.java b/java/test/com/android/i18n/addressinput/AsyncTestCaseTest.java
index 23fad88..36833b8 100644
--- a/java/test/com/android/i18n/addressinput/AsyncTestCaseTest.java
+++ b/java/test/com/android/i18n/addressinput/AsyncTestCaseTest.java
@@ -25,41 +25,41 @@ import java.util.concurrent.TimeoutException;
public class AsyncTestCaseTest extends AsyncTestCase {
public void testSuccess() {
- delayTestFinish(1000);
- AsyncCallback.execute(500, new Runnable() {
- @Override
- public void run() {
- finishTest();
- }
- });
+ delayTestFinish(1000);
+ AsyncCallback.execute(500, new Runnable() {
+ @Override
+ public void run() {
+ finishTest();
+ }
+ });
}
public void testFailure() {
- expectTimeout = true;
- delayTestFinish(1000);
- AsyncCallback.execute(1500, new Runnable() {
- @Override
- public void run() {
- finishTest();
- }
- });
+ expectTimeout = true;
+ delayTestFinish(1000);
+ AsyncCallback.execute(1500, new Runnable() {
+ @Override
+ public void run() {
+ finishTest();
+ }
+ });
}
@Override
protected void runTest() throws Throwable {
- expectTimeout = false;
- try {
- super.runTest();
- } catch (TimeoutException e) {
- if (expectTimeout) {
- return;
- } else {
- throw e;
- }
- }
+ expectTimeout = false;
+ try {
+ super.runTest();
+ } catch (TimeoutException e) {
if (expectTimeout) {
- throw new AssertionFailedError("Test case did not time out.");
+ return;
+ } else {
+ throw e;
}
+ }
+ if (expectTimeout) {
+ throw new AssertionFailedError("Test case did not time out.");
+ }
}
private boolean expectTimeout;
@@ -68,28 +68,28 @@ public class AsyncTestCaseTest extends AsyncTestCase {
* Helper class to perform an asynchronous callback after a specified delay.
*/
private static class AsyncCallback extends Thread {
- public static void execute(long waitMillis, Runnable callback) {
- (new AsyncCallback(waitMillis, callback)).start();
- }
+ private long waitMillis;
+ private Runnable callback;
- @Override
- public void run() {
- try {
- synchronized (this) {
- wait(mWaitMillis);
- }
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- mCallback.run();
+ private AsyncCallback(long waitMillis, Runnable callback) {
+ this.waitMillis = waitMillis;
+ this.callback = callback;
}
- private AsyncCallback(long waitMillis, Runnable callback) {
- this.mWaitMillis = waitMillis;
- this.mCallback = callback;
+ public static void execute(long waitMillis, Runnable callback) {
+ (new AsyncCallback(waitMillis, callback)).start();
}
- private long mWaitMillis;
- private Runnable mCallback;
+ @Override
+ public void run() {
+ try {
+ synchronized (this) {
+ wait(this.waitMillis);
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ this.callback.run();
+ }
}
}
diff --git a/java/test/com/android/i18n/addressinput/CacheDataTest.java b/java/test/com/android/i18n/addressinput/CacheDataTest.java
index c346882..7b72e47 100644
--- a/java/test/com/android/i18n/addressinput/CacheDataTest.java
+++ b/java/test/com/android/i18n/addressinput/CacheDataTest.java
@@ -23,304 +23,304 @@ import org.json.JSONException;
import org.json.JSONObject;
public class CacheDataTest extends AsyncTestCase {
- private CacheData cache;
+ private CacheData cache;
- private static final String DELIM = "~";
+ private static final String DELIM = "~";
- private static final String CANADA_KEY = "data/CA";
+ private static final String CANADA_KEY = "data/CA";
- private static final String US_KEY = "data/US";
+ private static final String US_KEY = "data/US";
- private static final String CALIFORNIA_KEY = "data/US/CA";
+ private static final String CALIFORNIA_KEY = "data/US/CA";
- private static final String RANDOM_COUNTRY_KEY = "data/asIOSDxcowW";
+ private static final String RANDOM_COUNTRY_KEY = "data/asIOSDxcowW";
- private static final String EXAMPLE_LOCAL_US_KEY = "examples/US/local/_default";
+ private static final String EXAMPLE_LOCAL_US_KEY = "examples/US/local/_default";
- // Data key for Da-an District, Taipei Taiwan
- private static final String TW_KEY = "data/TW/\u53F0\u5317\u5E02/\u5927\u5B89\u5340";
+ // Data key for Da-an District, Taipei Taiwan
+ private static final String TW_KEY = "data/TW/\u53F0\u5317\u5E02/\u5927\u5B89\u5340";
- private static final String FRANCE_KEY = "data/FR";
+ private static final String FRANCE_KEY = "data/FR";
- private static Integer listenerInvokeCount = 0;
+ private static Integer listenerInvokeCount = 0;
- private static boolean reachedMaxCount = false;
+ private static boolean reachedMaxCount = false;
- @Override
- public void setUp() {
- cache = new CacheData();
- }
-
- public void testJsonConstructor() {
- // Creating cache with content.
- String id = "data/CA";
- JSONObject jsonObject = null;
- try {
- jsonObject = new JSONObject(AddressDataMapLoader.DATA.get(id));
- } catch (JSONException jsonException) {
- // If this throws an exception the test fails.
- fail("Can't parse json object");
- }
- cache.addToJsoMap(id, jsonObject);
- String toBackup = cache.getJsonString();
-
- // Creating cache from saved data.
- cache = new CacheData(toBackup);
- assertTrue(cache.containsKey(id));
- }
-
- public void testJsonConstructorTruncatedProperString() {
- // Creating cache with content.
- String id = "data/CA";
- try {
- JSONObject jsonObject = new JSONObject(AddressDataMapLoader.DATA.get(id));
- String jsonString = jsonObject.toString();
- jsonString = jsonString.substring(0, jsonString.length() / 2);
-
- cache = new CacheData(jsonString);
- assertTrue(cache.toString(), cache.isEmpty());
- } catch (JSONException jsonException) {
- // If this throws an exception the test fails.
- fail("Can't parse json object");
- }
- }
-
- public void testSimpleFetching() {
- final LookupKey key = new LookupKey.Builder(CANADA_KEY).build();
-
- delayTestFinish(10000);
-
- cache.fetchDynamicData(key, null, new DataLoadListener() {
- boolean beginCalled = false;
-
- @Override
- public void dataLoadingBegin() {
- beginCalled = true;
- }
-
- @Override
- public void dataLoadingEnd() {
- assertTrue("dataLoadingBegin should be called", beginCalled);
- JsoMap map = cache.getObj(CANADA_KEY);
-
- assertTrue(map.containsKey(AddressDataKey.ID.name().toLowerCase()));
- assertTrue(map.containsKey(AddressDataKey.LANG.name().toLowerCase()));
- assertTrue(map.containsKey(AddressDataKey.ZIP.name().toLowerCase()));
- assertTrue(map.containsKey(AddressDataKey.FMT.name().toLowerCase()));
- assertTrue(map.containsKey(AddressDataKey.SUB_KEYS.name().toLowerCase()));
- assertTrue(map.containsKey(AddressDataKey.SUB_NAMES.name().toLowerCase()));
- assertFalse(map.containsKey(AddressDataKey.SUB_LNAMES.name().toLowerCase()));
-
- int namesSize =
- map.get(AddressDataKey.SUB_NAMES.name().toLowerCase()).split(DELIM).length;
- int keysSize =
- map.get(AddressDataKey.SUB_KEYS.name().toLowerCase()).split(DELIM).length;
-
- assertEquals("Expect 13 states in Canada.", 13, namesSize);
- assertEquals(namesSize, keysSize);
- finishTest();
- }
- });
- }
-
- public void testFetchingTaiwanData() {
- final LookupKey key = new LookupKey.Builder(TW_KEY).build();
-
- delayTestFinish(10000);
-
- cache.fetchDynamicData(key, null, new DataLoadListener() {
- boolean beginCalled = false;
-
- @Override
- public void dataLoadingBegin() {
- beginCalled = true;
- }
-
- @Override
- public void dataLoadingEnd() {
- assertTrue("dataLoadingBegin should be called", beginCalled);
-
- JsoMap map = cache.getObj(TW_KEY);
-
- assertTrue(map.containsKey(AddressDataKey.ID.name().toLowerCase()));
- assertTrue(map.containsKey(AddressDataKey.KEY.name().toLowerCase()));
- assertTrue(map.containsKey(AddressDataKey.LANG.name().toLowerCase()));
- assertTrue(map.containsKey(AddressDataKey.ZIP.name().toLowerCase()));
- assertFalse(map.containsKey(AddressDataKey.FMT.name().toLowerCase()));
- assertFalse(map.containsKey(AddressDataKey.SUB_KEYS.name().toLowerCase()));
- assertFalse(map.containsKey(AddressDataKey.SUB_NAMES.name().toLowerCase()));
- assertFalse(map.containsKey(AddressDataKey.SUB_LNAMES.name().toLowerCase()));
-
- // Da-an district.
- assertEquals("\u5927\u5B89\u5340",
- map.get(AddressDataKey.KEY.name().toLowerCase()));
+ @Override
+ public void setUp() {
+ cache = new CacheData();
+ }
- assertEquals("zh-hant", map.get(AddressDataKey.LANG.name().toLowerCase()));
-
- finishTest();
- }
- });
+ public void testJsonConstructor() {
+ // Creating cache with content.
+ String id = "data/CA";
+ JSONObject jsonObject = null;
+ try {
+ jsonObject = new JSONObject(AddressDataMapLoader.DATA.get(id));
+ } catch (JSONException jsonException) {
+ // If this throws an exception the test fails.
+ fail("Can't parse json object");
}
-
- public void testFetchingExamples() {
- final LookupKey key = new LookupKey.Builder(EXAMPLE_LOCAL_US_KEY).build();
-
- delayTestFinish(10000);
-
- cache.fetchDynamicData(key, null, new DataLoadListener() {
- boolean beginCalled = false;
-
- @Override
- public void dataLoadingBegin() {
- beginCalled = true;
- }
-
- @Override
- public void dataLoadingEnd() {
- assertTrue("dataLoadingBegin should be called", beginCalled);
-
- JsoMap map = cache.getObj(EXAMPLE_LOCAL_US_KEY);
- assertTrue(map.containsKey("name"));
- finishTest();
- }
- });
+ cache.addToJsoMap(id, jsonObject);
+ String toBackup = cache.getJsonString();
+
+ // Creating cache from saved data.
+ cache = new CacheData(toBackup);
+ assertTrue(cache.containsKey(id));
+ }
+
+ public void testJsonConstructorTruncatedProperString() {
+ // Creating cache with content.
+ String id = "data/CA";
+ try {
+ JSONObject jsonObject = new JSONObject(AddressDataMapLoader.DATA.get(id));
+ String jsonString = jsonObject.toString();
+ jsonString = jsonString.substring(0, jsonString.length() / 2);
+
+ cache = new CacheData(jsonString);
+ assertTrue(cache.toString(), cache.isEmpty());
+ } catch (JSONException jsonException) {
+ // If this throws an exception the test fails.
+ fail("Can't parse json object");
}
+ }
+
+ public void testSimpleFetching() {
+ final LookupKey key = new LookupKey.Builder(CANADA_KEY).build();
+
+ delayTestFinish(10000);
- public void testFetchingOneKeyManyTimes() {
- final LookupKey key = new LookupKey.Builder(CALIFORNIA_KEY).build();
- final int maxCount = 10;
-
- class CounterListener implements DataLoadListener {
- @Override
- public void dataLoadingBegin() {
- listenerInvokeCount++;
- if (listenerInvokeCount == maxCount) {
- reachedMaxCount = true;
- }
- assertTrue("CounterListener's dataLoadingBegin should not be invoked for more " +
- "than " + maxCount + " times",
- listenerInvokeCount <= maxCount);
- }
-
- @Override
- public void dataLoadingEnd() {
- listenerInvokeCount--;
- assertTrue(listenerInvokeCount >= 0);
- if (listenerInvokeCount == 0) {
- assertTrue("Expect to see key " + key + " cached when CounterListener's " +
- " dataLoadingEnd is invoked",
- cache.containsKey(key.toString()));
- assertTrue("Expect CounterListener's dataLoadingEnd to be triggered " +
- maxCount + " times in total", reachedMaxCount);
- finishTest();
- }
- }
+ cache.fetchDynamicData(key, null, new DataLoadListener() {
+ boolean beginCalled = false;
+
+ @Override
+ public void dataLoadingBegin() {
+ beginCalled = true;
+ }
+
+ @Override
+ public void dataLoadingEnd() {
+ assertTrue("dataLoadingBegin should be called", beginCalled);
+ JsoMap map = cache.getObj(CANADA_KEY);
+
+ assertTrue(map.containsKey(AddressDataKey.ID.name().toLowerCase()));
+ assertTrue(map.containsKey(AddressDataKey.LANG.name().toLowerCase()));
+ assertTrue(map.containsKey(AddressDataKey.ZIP.name().toLowerCase()));
+ assertTrue(map.containsKey(AddressDataKey.FMT.name().toLowerCase()));
+ assertTrue(map.containsKey(AddressDataKey.SUB_KEYS.name().toLowerCase()));
+ assertTrue(map.containsKey(AddressDataKey.SUB_NAMES.name().toLowerCase()));
+ assertFalse(map.containsKey(AddressDataKey.SUB_LNAMES.name().toLowerCase()));
+
+ int namesSize =
+ map.get(AddressDataKey.SUB_NAMES.name().toLowerCase()).split(DELIM).length;
+ int keysSize =
+ map.get(AddressDataKey.SUB_KEYS.name().toLowerCase()).split(DELIM).length;
+
+ assertEquals("Expect 13 states in Canada.", 13, namesSize);
+ assertEquals(namesSize, keysSize);
+ finishTest();
+ }
+ });
+ }
+
+ public void testFetchingTaiwanData() {
+ final LookupKey key = new LookupKey.Builder(TW_KEY).build();
+
+ delayTestFinish(10000);
+
+ cache.fetchDynamicData(key, null, new DataLoadListener() {
+ boolean beginCalled = false;
+
+ @Override
+ public void dataLoadingBegin() {
+ beginCalled = true;
+ }
+
+ @Override
+ public void dataLoadingEnd() {
+ assertTrue("dataLoadingBegin should be called", beginCalled);
+
+ JsoMap map = cache.getObj(TW_KEY);
+
+ assertTrue(map.containsKey(AddressDataKey.ID.name().toLowerCase()));
+ assertTrue(map.containsKey(AddressDataKey.KEY.name().toLowerCase()));
+ assertTrue(map.containsKey(AddressDataKey.LANG.name().toLowerCase()));
+ assertTrue(map.containsKey(AddressDataKey.ZIP.name().toLowerCase()));
+ assertFalse(map.containsKey(AddressDataKey.FMT.name().toLowerCase()));
+ assertFalse(map.containsKey(AddressDataKey.SUB_KEYS.name().toLowerCase()));
+ assertFalse(map.containsKey(AddressDataKey.SUB_NAMES.name().toLowerCase()));
+ assertFalse(map.containsKey(AddressDataKey.SUB_LNAMES.name().toLowerCase()));
+
+ // Da-an district.
+ assertEquals("\u5927\u5B89\u5340",
+ map.get(AddressDataKey.KEY.name().toLowerCase()));
+
+ assertEquals("zh-hant", map.get(AddressDataKey.LANG.name().toLowerCase()));
+
+ finishTest();
+ }
+ });
+ }
+
+ public void testFetchingExamples() {
+ final LookupKey key = new LookupKey.Builder(EXAMPLE_LOCAL_US_KEY).build();
+
+ delayTestFinish(10000);
+
+ cache.fetchDynamicData(key, null, new DataLoadListener() {
+ boolean beginCalled = false;
+
+ @Override
+ public void dataLoadingBegin() {
+ beginCalled = true;
+ }
+
+ @Override
+ public void dataLoadingEnd() {
+ assertTrue("dataLoadingBegin should be called", beginCalled);
+
+ JsoMap map = cache.getObj(EXAMPLE_LOCAL_US_KEY);
+ assertTrue(map.containsKey("name"));
+ finishTest();
+ }
+ });
+ }
+
+ public void testFetchingOneKeyManyTimes() {
+ final LookupKey key = new LookupKey.Builder(CALIFORNIA_KEY).build();
+ final int maxCount = 10;
+
+ class CounterListener implements DataLoadListener {
+ @Override
+ public void dataLoadingBegin() {
+ listenerInvokeCount++;
+ if (listenerInvokeCount == maxCount) {
+ reachedMaxCount = true;
}
-
- delayTestFinish(10000);
-
- for (int i = 0; i < maxCount; ++i) {
- cache.fetchDynamicData(key, null, new CounterListener());
+ assertTrue("CounterListener's dataLoadingBegin should not be invoked for more " +
+ "than " + maxCount + " times",
+ listenerInvokeCount <= maxCount);
+ }
+
+ @Override
+ public void dataLoadingEnd() {
+ listenerInvokeCount--;
+ assertTrue(listenerInvokeCount >= 0);
+ if (listenerInvokeCount == 0) {
+ assertTrue("Expect to see key " + key + " cached when CounterListener's " +
+ " dataLoadingEnd is invoked",
+ cache.containsKey(key.toString()));
+ assertTrue("Expect CounterListener's dataLoadingEnd to be triggered " +
+ maxCount + " times in total", reachedMaxCount);
+ finishTest();
}
-
- // Null listeners should not affect results.
- cache.fetchDynamicData(key, null, null);
- cache.fetchDynamicData(key, null, null);
- cache.fetchDynamicData(key, null, null);
+ }
}
- public void testFetchAgainRightAfterOneFetchStart() {
- final LookupKey key = new LookupKey.Builder(US_KEY).build();
+ delayTestFinish(10000);
- delayTestFinish(10000);
+ for (int i = 0; i < maxCount; ++i) {
+ cache.fetchDynamicData(key, null, new CounterListener());
+ }
- cache.fetchDynamicData(key, null, null);
+ // Null listeners should not affect results.
+ cache.fetchDynamicData(key, null, null);
+ cache.fetchDynamicData(key, null, null);
+ cache.fetchDynamicData(key, null, null);
+ }
- cache.fetchDynamicData(key, null, new DataLoadListener() {
- boolean beginCalled = false;
-
- @Override
- public void dataLoadingBegin() {
- assertFalse("data for key " + key + " should not be fetched yet",
- cache.containsKey(key.toString()));
- beginCalled = true;
- }
-
- @Override
- public void dataLoadingEnd() {
- assertTrue("dataLoadingBegin should be called", beginCalled);
-
- assertTrue(cache.containsKey(key.toString()));
-
- cache.fetchDynamicData(key, null, new DataLoadListener() {
- boolean beginCalled2 = false;
-
- @Override
- public void dataLoadingBegin() {
- beginCalled2 = true;
- }
-
- @Override
- public void dataLoadingEnd() {
- assertTrue("dataLoadingBegin should be called", beginCalled2);
-
- assertTrue(cache.containsKey(key.toString()));
- finishTest();
- }
- });
- }
- });
- }
+ public void testFetchAgainRightAfterOneFetchStart() {
+ final LookupKey key = new LookupKey.Builder(US_KEY).build();
- public void testInvalidKey() {
- final LookupKey key = new LookupKey.Builder(RANDOM_COUNTRY_KEY).build();
+ delayTestFinish(10000);
- delayTestFinish(15000);
+ cache.fetchDynamicData(key, null, null);
- cache.fetchDynamicData(key, null, new DataLoadListener() {
- boolean beginCalled = false;
+ cache.fetchDynamicData(key, null, new DataLoadListener() {
+ boolean beginCalled = false;
- @Override
- public void dataLoadingBegin() {
- beginCalled = true;
- }
+ @Override
+ public void dataLoadingBegin() {
+ assertFalse("data for key " + key + " should not be fetched yet",
+ cache.containsKey(key.toString()));
+ beginCalled = true;
+ }
- @Override
- public void dataLoadingEnd() {
- assertTrue("dataLoadingBegin should be called", beginCalled);
- assertFalse(cache.containsKey(key.toString()));
+ @Override
+ public void dataLoadingEnd() {
+ assertTrue("dataLoadingBegin should be called", beginCalled);
- finishTest();
- }
- });
- }
+ assertTrue(cache.containsKey(key.toString()));
- public void testSetUrl() {
- final LookupKey key = new LookupKey.Builder(FRANCE_KEY).build();
- final String originalUrl = cache.getUrl();
+ cache.fetchDynamicData(key, null, new DataLoadListener() {
+ boolean beginCalled2 = false;
- assertFalse(FRANCE_KEY + " should not be in the cache. Do you request it before this test?",
- cache.containsKey(key.toString()));
+ @Override
+ public void dataLoadingBegin() {
+ beginCalled2 = true;
+ }
- delayTestFinish(10000);
- // Something that is not an URL.
- cache.setUrl("FDSSfdfdsfasdfadsf");
+ @Override
+ public void dataLoadingEnd() {
+ assertTrue("dataLoadingBegin should be called", beginCalled2);
- cache.fetchDynamicData(key, null, new DataLoadListener() {
- boolean beginCalled = false;
-
- @Override
- public void dataLoadingBegin() {
- beginCalled = true;
- }
-
- @Override
- public void dataLoadingEnd() {
- assertTrue("dataLoadingBegin should be called", beginCalled);
- assertFalse(cache.containsKey(key.toString()));
- cache.setUrl(originalUrl);
- finishTest();
- }
+ assertTrue(cache.containsKey(key.toString()));
+ finishTest();
+ }
});
- }
+ }
+ });
+ }
+
+ public void testInvalidKey() {
+ final LookupKey key = new LookupKey.Builder(RANDOM_COUNTRY_KEY).build();
+
+ delayTestFinish(15000);
+
+ cache.fetchDynamicData(key, null, new DataLoadListener() {
+ boolean beginCalled = false;
+
+ @Override
+ public void dataLoadingBegin() {
+ beginCalled = true;
+ }
+
+ @Override
+ public void dataLoadingEnd() {
+ assertTrue("dataLoadingBegin should be called", beginCalled);
+ assertFalse(cache.containsKey(key.toString()));
+
+ finishTest();
+ }
+ });
+ }
+
+ public void testSetUrl() {
+ final LookupKey key = new LookupKey.Builder(FRANCE_KEY).build();
+ final String originalUrl = cache.getUrl();
+
+ assertFalse(FRANCE_KEY + " should not be in the cache. Do you request it before this test?",
+ cache.containsKey(key.toString()));
+
+ delayTestFinish(10000);
+ // Something that is not an URL.
+ cache.setUrl("FDSSfdfdsfasdfadsf");
+
+ cache.fetchDynamicData(key, null, new DataLoadListener() {
+ boolean beginCalled = false;
+
+ @Override
+ public void dataLoadingBegin() {
+ beginCalled = true;
+ }
+
+ @Override
+ public void dataLoadingEnd() {
+ assertTrue("dataLoadingBegin should be called", beginCalled);
+ assertFalse(cache.containsKey(key.toString()));
+ cache.setUrl(originalUrl);
+ finishTest();
+ }
+ });
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/ClientDataTest.java b/java/test/com/android/i18n/addressinput/ClientDataTest.java
index b18d726..c665a3b 100644
--- a/java/test/com/android/i18n/addressinput/ClientDataTest.java
+++ b/java/test/com/android/i18n/addressinput/ClientDataTest.java
@@ -23,61 +23,61 @@ import com.android.i18n.addressinput.testing.AsyncTestCase;
* server and recovers if no data is present.
*/
public class ClientDataTest extends AsyncTestCase {
- private ClientData client;
+ private ClientData client;
- @Override
- public void setUp() {
- client = new ClientData(new CacheData());
- }
+ @Override
+ public void setUp() {
+ client = new ClientData(new CacheData());
+ }
- public void testGet() {
- AddressVerificationNodeData data = client.get("data");
- assertNotNull(data);
- }
+ public void testGet() {
+ AddressVerificationNodeData data = client.get("data");
+ assertNotNull(data);
+ }
- public void testGet2() {
- AddressVerificationNodeData data;
+ public void testGet2() {
+ AddressVerificationNodeData data;
- data = client.get("data");
- assertNotNull(data);
+ data = client.get("data");
+ assertNotNull(data);
- data = client.get("data");
- assertNotNull(data);
- }
+ data = client.get("data");
+ assertNotNull(data);
+ }
- public void testPrefetchCountry() {
- delayTestFinish(60000);
+ public void testPrefetchCountry() {
+ delayTestFinish(60000);
- client.prefetchCountry("TW", new DataLoadListener() {
- boolean beginCalled = false;
+ client.prefetchCountry("TW", new DataLoadListener() {
+ boolean beginCalled = false;
- @Override
- public void dataLoadingBegin() {
- beginCalled = true;
- }
+ @Override
+ public void dataLoadingBegin() {
+ beginCalled = true;
+ }
- @Override
- public void dataLoadingEnd() {
- assertTrue("dataLoadingBegin should be called", beginCalled);
- // Currently this test only tests that the execution doesn't crash and eventually
- // terminates. TODO: Write test cases to verify that correct data is loaded.
- finishTest();
- }
- });
- }
+ @Override
+ public void dataLoadingEnd() {
+ assertTrue("dataLoadingBegin should be called", beginCalled);
+ // Currently this test only tests that the execution doesn't crash and eventually
+ // terminates. TODO: Write test cases to verify that correct data is loaded.
+ finishTest();
+ }
+ });
+ }
- public void testFetchDataWithBadServer() {
- CacheData badCache = new CacheData();
- badCache.setUrl("http://www.google.com");
- ClientData badServerClient = new ClientData(badCache);
+ public void testFetchDataWithBadServer() {
+ CacheData badCache = new CacheData();
+ badCache.setUrl("http://www.google.com");
+ ClientData badServerClient = new ClientData(badCache);
- AddressVerificationNodeData data = badServerClient.get("data/US");
+ AddressVerificationNodeData data = badServerClient.get("data/US");
- // No data was available on the server or in the cache - it should check
- // that there is nothing in region data constants, and should return the
- // data from there.
- assertNotNull(data);
- String unitedStatesFormatInfo = data.get(AddressDataKey.FMT);
- assertEquals("%N%n%O%n%A%n%C, %S %Z", unitedStatesFormatInfo);
- }
+ // No data was available on the server or in the cache - it should check
+ // that there is nothing in region data constants, and should return the
+ // data from there.
+ assertNotNull(data);
+ String unitedStatesFormatInfo = data.get(AddressDataKey.FMT);
+ assertEquals("%N%n%O%n%A%n%C, %S %Z", unitedStatesFormatInfo);
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/FieldVerifierTest.java b/java/test/com/android/i18n/addressinput/FieldVerifierTest.java
index 6521a5a..2988691 100644
--- a/java/test/com/android/i18n/addressinput/FieldVerifierTest.java
+++ b/java/test/com/android/i18n/addressinput/FieldVerifierTest.java
@@ -20,252 +20,295 @@ import com.android.i18n.addressinput.testing.AddressDataMapLoader;
import junit.framework.TestCase;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Set;
+
/**
* Spot check the standard data set for various cases of interest. This is not an exhaustive test.
*/
public class FieldVerifierTest extends TestCase {
- private static final StandardAddressVerifier VERIFIER =
- new StandardAddressVerifier(new FieldVerifier(
- new AddressVerificationData(AddressDataMapLoader.DATA)));
-
- private AddressProblems problems = new AddressProblems();
-
- @Override
- protected void setUp() {
- problems.clear();
- }
-
- public void testUnitedStatesOk() {
- AddressData addr = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality("Mountain View")
- .setAddress("1234 Somewhere")
- .setPostalCode("94025").build();
- VERIFIER.verify(addr, problems);
- assertTrue(problems.toString(), problems.isEmpty()); // no mismatch
- }
-
- public void testUnitedStatesZipMismatch() {
- AddressData addr = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality("Mountain View")
- .setPostalCode("12345").build();
- VERIFIER.verify(addr, problems);
-
- assertEquals(AddressProblemType.MISMATCHING_VALUE,
- problems.getProblem(AddressField.POSTAL_CODE));
- }
-
- public void testUnitedStatesNotOk() {
- AddressData addr = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality(null)
- .setDependentLocality("Foo Bar")
- .setPostalCode("12345").build();
- VERIFIER.verify(addr, problems);
-
- assertEquals(AddressProblemType.MISMATCHING_VALUE,
- problems.getProblem(AddressField.POSTAL_CODE));
- assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
- problems.getProblem(AddressField.LOCALITY));
- }
-
- public void testChinaOk() {
- AddressData addr = new AddressData.Builder().setCountry("CN")
- .setAdminArea("Beijing Shi")
- .setLocality("Xicheng Qu")
- .setAddress("Yitiao Lu")
- .setPostalCode("123456").build();
- VERIFIER.verify(addr, problems);
- assertTrue(problems.isEmpty());
- }
-
- public void testGermanAddress() {
- AddressData addr = new AddressData.Builder().setCountry("DE")
- .setLocality("Berlin")
- .setAddress("Huttenstr. 50")
- .setPostalCode("10553")
- .setOrganization("BMW AG Niederkassung Berlin")
- .setRecipient("Herr Diefendorf").build();
-
- VERIFIER.verify(addr, problems);
- assertTrue(problems.isEmpty());
-
- // Clones address but leave city empty.
- addr = new AddressData.Builder().set(addr).setLocality(null).build();
-
- VERIFIER.verify(addr, problems);
- assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
- problems.getProblem(AddressField.LOCALITY));
- }
-
- public void testIrishAddress() {
- AddressData addr = new AddressData.Builder().setCountry("IE")
- .setLocality("Dublin")
- .setAdminArea("Co. Dublin")
- .setAddress("7424 118 Avenue NW")
- .setRecipient("Conan O'Brien").build();
-
- VERIFIER.verify(addr, problems);
- assertTrue(problems.toString(), problems.isEmpty());
-
- // Clones address but leave county empty. This address should be valid
- // since county is not required.
- addr = new AddressData.Builder().set(addr).setAdminArea(null).build();
-
- VERIFIER.verify(addr, problems);
- assertTrue(problems.toString(), problems.isEmpty());
- }
-
- public void testChinaPostalCodeBadFormat() {
- AddressData addr = new AddressData.Builder().setCountry("CN")
- .setAdminArea("Beijing Shi")
- .setLocality("Xicheng Qu")
- .setPostalCode("12345").build();
- VERIFIER.verify(addr, problems);
-
- assertEquals(AddressProblemType.UNRECOGNIZED_FORMAT,
- problems.getProblem(AddressField.POSTAL_CODE));
- }
-
- /**
- * If there is a postal code pattern for a certain country, and the input postal code is empty,
- * it should not be reported as bad postal code format. Whether empty postal code is ok should
- * be determined by checks for required fields.
- */
- public void testEmptyPostalCodeReportedAsGoodFormat() {
- // Chilean address has a postal code format pattern, but does not require
- // postal code. The following address is valid.
- AddressData addr = new AddressData.Builder().setCountry("CL")
- .setAddressLine1("GUSTAVO LE PAIGE ST #159")
- .setAdminArea("Atacama")
- .setLocality("San Pedro")
- .setPostalCode("")
- .build();
- VERIFIER.verify(addr, problems);
- assertTrue(problems.toString(), problems.isEmpty());
-
- problems.clear();
-
- // Now check for US addresses, which require a postal code. The following
- // address's postal code is wrong because it is missing a required field, not
- // because it doesn't match the expected postal code pattern.
- addr = new AddressData.Builder().setCountry("US").setPostalCode("").build();
- problems.clear();
- VERIFIER.verify(addr, problems);
-
- assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
- problems.getProblem(AddressField.POSTAL_CODE));
- }
-
- public void testChinaTaiwanOk() {
- AddressData addr = new AddressData.Builder().setCountry("CN")
- .setAdminArea("Taiwan")
- .setLocality("Taichung City")
- .setDependentLocality("Situn District")
- .setAddress("12345 Yitiao Lu")
- .setPostalCode("407").build();
- VERIFIER.verify(addr, problems);
- assertTrue(problems.isEmpty());
- }
-
- public void testChinaTaiwanUnknownDistrict() {
- AddressData addr = new AddressData.Builder().setCountry("CN")
- .setAdminArea("Taiwan")
- .setLocality("Taichung City")
- .setDependentLocality("Foo Bar")
- .setPostalCode("400").build();
- VERIFIER.verify(addr, problems);
-
- assertEquals(AddressProblemType.UNKNOWN_VALUE,
- problems.getProblem(AddressField.DEPENDENT_LOCALITY));
- }
-
- public void testStreetVerification() {
- // Missing street address
- AddressData addr = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality("Mountain View")
- .setPostalCode("94025").build();
-
- assertNull(addr.getAddressLine1());
- assertNull(addr.getAddressLine2());
-
- VERIFIER.verify(addr, problems);
-
- assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
- problems.getProblem(AddressField.STREET_ADDRESS));
- }
-
- // Tests The Bahamas' address
- public void failingtestBahamas() {
- final AddressData address =
- new AddressData.Builder().setAddress("Abaco Beach Resort & Boat Habour")
- .setLocality("Treasure Cay")
- .setAdminArea("Abaco")
- .setCountry("BS").build();
- VERIFIER.verify(address, problems);
- assertTrue(problems.isEmpty());
- }
-
- public void testJapan() {
- // Added AdminArea since address verification can't infer it from Kyoto City
- // Commented out dependent locality since we don't have the data for this and in fact say
- // that it shouldn't be used for Japan.
- // TODO: support inference of higher levels from lower ones
- final AddressData address = new AddressData.Builder()
- .setRecipient("\u5BAE\u672C \u8302") // SHIGERU_MIYAMOTO
- .setAddress("\u4E0A\u9CE5\u7FBD\u927E\u7ACB\u753A11\u756A\u5730")
- .setAdminArea("\u4eac\u90fd\u5e9c") // Kyoto prefecture, added
- .setLocality("\u4EAC\u90FD\u5E02") // Kyoto city
- // .setDependentLocality("\u5357\u533A")
- .setCountry("JP")
- .setPostalCode("601-8501").build();
- VERIFIER.verify(address, problems);
- assertTrue(problems.toString(), problems.isEmpty());
- }
-
- public void testJapanLatin() {
- // added AdminArea since address verification can't infer it from Kyoto City
- // commented out dependent locality since address verification doesn't use it
- final AddressData address = new AddressData.Builder()
- .setRecipient("Shigeru Miyamoto") // SHIGERU_MIYAMOTO_ENGLISH
- .setAddress("11-1 Kamitoba-hokotate-cho")
- .setAdminArea("KYOTO") // added
- .setLocality("Kyoto")
- // .setDependentLocality("Minami-ku")
- .setLanguageCode("ja_Latn")
- .setCountry("JP")
- .setPostalCode("601-8501").build();
- VERIFIER.verify(address, problems);
- assertTrue(problems.isEmpty());
- }
-
- public void testJapanLatinInvalidAdmin() {
- final AddressData address = new AddressData.Builder()
- .setRecipient("Shigeru Miyamoto") // SHIGERU_MIYAMOTO_ENGLISH
- .setAddress("11-1 Kamitoba-hokotate-cho")
- .setAdminArea("Fake Admin")
- .setLocality("Kyoto")
- .setLanguageCode("ja_Latn")
- .setCountry("JP")
- .setPostalCode("601-8501").build();
- VERIFIER.verify(address, problems);
- assertFalse(problems.isEmpty());
- assertEquals(AddressProblemType.UNKNOWN_VALUE,
- problems.getProblem(AddressField.ADMIN_AREA));
- }
-
- public void testCanadaMixedCasePostcode() {
- final AddressData address = new AddressData.Builder()
- .setRecipient("Joe Bloggs")
- .setAddress("11 East St")
- .setLocality("Montreal")
- .setAdminArea("Quebec")
- .setCountry("CA")
- .setPostalCode("H2b 2y5").build();
- VERIFIER.verify(address, problems);
- assertTrue(problems.isEmpty());
+ private static final StandardAddressVerifier VERIFIER =
+ new StandardAddressVerifier(new FieldVerifier(
+ new AddressVerificationData(AddressDataMapLoader.DATA)));
+
+ private AddressProblems problems = new AddressProblems();
+
+ @Override
+ protected void setUp() {
+ problems.clear();
+ }
+
+ public void testUnitedStatesOk() {
+ AddressData addr = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality("Mountain View")
+ .setAddress("1234 Somewhere")
+ .setPostalCode("94025").build();
+ VERIFIER.verify(addr, problems);
+ assertTrue(problems.toString(), problems.isEmpty()); // no mismatch
+ }
+
+ public void testUnitedStatesZipMismatch() {
+ AddressData addr = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality("Mountain View")
+ .setPostalCode("12345").build();
+ VERIFIER.verify(addr, problems);
+
+ assertEquals(AddressProblemType.MISMATCHING_VALUE,
+ problems.getProblem(AddressField.POSTAL_CODE));
+ }
+
+ public void testUnitedStatesNotOk() {
+ AddressData addr = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality(null)
+ .setDependentLocality("Foo Bar")
+ .setPostalCode("12345").build();
+ VERIFIER.verify(addr, problems);
+
+ assertEquals(AddressProblemType.MISMATCHING_VALUE,
+ problems.getProblem(AddressField.POSTAL_CODE));
+ assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
+ problems.getProblem(AddressField.LOCALITY));
+ }
+
+ public void testChinaOk() {
+ AddressData addr = new AddressData.Builder().setCountry("CN")
+ .setAdminArea("Beijing Shi")
+ .setLocality("Xicheng Qu")
+ .setAddress("Yitiao Lu")
+ .setPostalCode("123456").build();
+ VERIFIER.verify(addr, problems);
+ assertTrue(problems.isEmpty());
+ }
+
+ public void testGermanAddress() {
+ AddressData addr = new AddressData.Builder().setCountry("DE")
+ .setLocality("Berlin")
+ .setAddress("Huttenstr. 50")
+ .setPostalCode("10553")
+ .setOrganization("BMW AG Niederkassung Berlin")
+ .setRecipient("Herr Diefendorf").build();
+
+ VERIFIER.verify(addr, problems);
+ assertTrue(problems.isEmpty());
+
+ // Clones address but leave city empty.
+ addr = new AddressData.Builder().set(addr).setLocality(null).build();
+
+ VERIFIER.verify(addr, problems);
+ assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
+ problems.getProblem(AddressField.LOCALITY));
+ }
+
+ public void testIrishAddress() {
+ AddressData addr = new AddressData.Builder().setCountry("IE")
+ .setLocality("Dublin")
+ .setAdminArea("Co. Dublin")
+ .setAddress("7424 118 Avenue NW")
+ .setRecipient("Conan O'Brien").build();
+
+ VERIFIER.verify(addr, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+
+ // Clones address but leave county empty. This address should be valid
+ // since county is not required.
+ addr = new AddressData.Builder().set(addr).setAdminArea(null).build();
+
+ VERIFIER.verify(addr, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+ }
+
+ public void testChinaPostalCodeBadFormat() {
+ AddressData addr = new AddressData.Builder().setCountry("CN")
+ .setAdminArea("Beijing Shi")
+ .setLocality("Xicheng Qu")
+ .setPostalCode("12345").build();
+ VERIFIER.verify(addr, problems);
+
+ assertEquals(AddressProblemType.UNRECOGNIZED_FORMAT,
+ problems.getProblem(AddressField.POSTAL_CODE));
+ }
+
+ /**
+ * If there is a postal code pattern for a certain country, and the input postal code is empty,
+ * it should not be reported as bad postal code format. Whether empty postal code is ok should
+ * be determined by checks for required fields.
+ */
+ public void testEmptyPostalCodeReportedAsGoodFormat() {
+ // Chilean address has a postal code format pattern, but does not require
+ // postal code. The following address is valid.
+ AddressData addr = new AddressData.Builder().setCountry("CL")
+ .setAddressLine1("GUSTAVO LE PAIGE ST #159")
+ .setAdminArea("Atacama")
+ .setLocality("San Pedro")
+ .setPostalCode("")
+ .build();
+ VERIFIER.verify(addr, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+
+ problems.clear();
+
+ // Now check for US addresses, which require a postal code. The following
+ // address's postal code is wrong because it is missing a required field, not
+ // because it doesn't match the expected postal code pattern.
+ addr = new AddressData.Builder().setCountry("US").setPostalCode("").build();
+ problems.clear();
+ VERIFIER.verify(addr, problems);
+
+ assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
+ problems.getProblem(AddressField.POSTAL_CODE));
+ }
+
+ public void testChinaTaiwanOk() {
+ AddressData addr = new AddressData.Builder().setCountry("CN")
+ .setAdminArea("Taiwan")
+ .setLocality("Taichung City")
+ .setDependentLocality("Situn District")
+ .setAddress("12345 Yitiao Lu")
+ .setPostalCode("407").build();
+ VERIFIER.verify(addr, problems);
+ assertTrue(problems.isEmpty());
+ }
+
+ public void testChinaTaiwanUnknownDistrict() {
+ AddressData addr = new AddressData.Builder().setCountry("CN")
+ .setAdminArea("Taiwan")
+ .setLocality("Taichung City")
+ .setDependentLocality("Foo Bar")
+ .setPostalCode("400").build();
+ VERIFIER.verify(addr, problems);
+
+ assertEquals(AddressProblemType.UNKNOWN_VALUE,
+ problems.getProblem(AddressField.DEPENDENT_LOCALITY));
+ }
+
+ public void testStreetVerification() {
+ // Missing street address
+ AddressData addr = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality("Mountain View")
+ .setPostalCode("94025").build();
+
+ assertNull(addr.getAddressLine1());
+ assertNull(addr.getAddressLine2());
+
+ VERIFIER.verify(addr, problems);
+
+ assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
+ problems.getProblem(AddressField.STREET_ADDRESS));
+ }
+
+ // Tests The Bahamas' address
+ public void failingtestBahamas() {
+ final AddressData address =
+ new AddressData.Builder().setAddress("Abaco Beach Resort & Boat Habour")
+ .setLocality("Treasure Cay")
+ .setAdminArea("Abaco")
+ .setCountry("BS").build();
+ VERIFIER.verify(address, problems);
+ assertTrue(problems.isEmpty());
+ }
+
+ public void testJapan() {
+ // Added AdminArea since address verification can't infer it from Kyoto City
+ // Commented out dependent locality since we don't have the data for this and in fact say
+ // that it shouldn't be used for Japan.
+ // TODO: support inference of higher levels from lower ones
+ final AddressData address = new AddressData.Builder()
+ .setRecipient("\u5BAE\u672C \u8302") // SHIGERU_MIYAMOTO
+ .setAddress("\u4E0A\u9CE5\u7FBD\u927E\u7ACB\u753A11\u756A\u5730")
+ .setAdminArea("\u4eac\u90fd\u5e9c") // Kyoto prefecture, added
+ .setLocality("\u4EAC\u90FD\u5E02") // Kyoto city
+ // .setDependentLocality("\u5357\u533A")
+ .setCountry("JP")
+ .setPostalCode("601-8501").build();
+ VERIFIER.verify(address, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+ }
+
+ public void testJapanLatin() {
+ // added AdminArea since address verification can't infer it from Kyoto City
+ // commented out dependent locality since address verification doesn't use it
+ final AddressData address = new AddressData.Builder()
+ .setRecipient("Shigeru Miyamoto") // SHIGERU_MIYAMOTO_ENGLISH
+ .setAddress("11-1 Kamitoba-hokotate-cho")
+ .setAdminArea("KYOTO") // added
+ .setLocality("Kyoto")
+ // .setDependentLocality("Minami-ku")
+ .setLanguageCode("ja_Latn")
+ .setCountry("JP")
+ .setPostalCode("601-8501").build();
+ VERIFIER.verify(address, problems);
+ assertTrue(problems.isEmpty());
+ }
+
+ public void testJapanLatinInvalidAdmin() {
+ final AddressData address = new AddressData.Builder()
+ .setRecipient("Shigeru Miyamoto") // SHIGERU_MIYAMOTO_ENGLISH
+ .setAddress("11-1 Kamitoba-hokotate-cho")
+ .setAdminArea("Fake Admin")
+ .setLocality("Kyoto")
+ .setLanguageCode("ja_Latn")
+ .setCountry("JP")
+ .setPostalCode("601-8501").build();
+ VERIFIER.verify(address, problems);
+ assertFalse(problems.isEmpty());
+ assertEquals(AddressProblemType.UNKNOWN_VALUE,
+ problems.getProblem(AddressField.ADMIN_AREA));
+ }
+
+ public void testCanadaMixedCasePostcode() {
+ final AddressData address = new AddressData.Builder()
+ .setRecipient("Joe Bloggs")
+ .setAddress("11 East St")
+ .setLocality("Montreal")
+ .setAdminArea("Quebec")
+ .setCountry("CA")
+ .setPostalCode("H2b 2y5").build();
+ VERIFIER.verify(address, problems);
+ assertTrue(problems.isEmpty());
+ }
+
+ public void testMultipleAddressLines() {
+ final AddressData address = new AddressData.Builder()
+ .setCountry("US")
+ .setAdminArea("CA")
+ .setLocality("Mountain View")
+ .setAddressLine1("Somewhere")
+ .setAddressLine2("1234")
+ .setPostalCode("94025").build();
+ VERIFIER.verify(address, problems);
+ assertTrue(problems.isEmpty());
+ }
+
+ public void testFieldVerifierUsesRegionDataConstantsForFmtAndRequire() {
+ Map<AddressDataKey, String> map = new EnumMap<AddressDataKey, String>(AddressDataKey.class);
+ // Values for format and require are deliberately different from RegionDataConstants so that
+ // we can test that the RDC's version is preferred.
+ map.put(AddressDataKey.FMT, "%N%n%O");
+ map.put(AddressDataKey.REQUIRE, "A");
+ map.put(AddressDataKey.SUB_KEYS, "Test");
+ map.put(AddressDataKey.ID, "data/FM");
+ AddressVerificationNodeData testNode = new AddressVerificationNodeData(map);
+ FieldVerifier fieldVerifier = new FieldVerifier(VERIFIER.rootVerifier, testNode);
+
+ // Used and required obtained from RegionDataConstants for FM.
+ Set<AddressField> expectedPossibleFields = EnumSet.of(AddressField.RECIPIENT,
+ AddressField.ORGANIZATION, AddressField.STREET_ADDRESS, AddressField.LOCALITY,
+ AddressField.ADMIN_AREA, AddressField.POSTAL_CODE, AddressField.COUNTRY);
+ Set<AddressField> expectedRequiredField = EnumSet.of(AddressField.STREET_ADDRESS,
+ AddressField.LOCALITY, AddressField.ADMIN_AREA, AddressField.POSTAL_CODE,
+ AddressField.COUNTRY);
+ assertEquals(expectedPossibleFields, fieldVerifier.possiblyUsedFields);
+ assertEquals(expectedRequiredField, fieldVerifier.required);
+ assertEquals("data/FM", fieldVerifier.id);
+ // Keys should be populated from the test node.
+ assertEquals("[Test]", Arrays.toString(fieldVerifier.keys));
}
}
diff --git a/java/test/com/android/i18n/addressinput/FormControllerTest.java b/java/test/com/android/i18n/addressinput/FormControllerTest.java
index 23b798f..c0fa877 100644
--- a/java/test/com/android/i18n/addressinput/FormControllerTest.java
+++ b/java/test/com/android/i18n/addressinput/FormControllerTest.java
@@ -26,126 +26,126 @@ import java.util.List;
*/
public class FormControllerTest extends AsyncTestCase {
- private static final AddressData US_CA_ADDRESS;
- private static final AddressData US_ADDRESS;
- private ClientData clientData;
-
- static {
- US_CA_ADDRESS = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality("Mt View")
- .setAddressLine1("1098 Alta Ave")
- .setPostalCode("94043")
- .build();
- US_ADDRESS = new AddressData.Builder().setCountry("US").build();
- }
-
- @Override
- public void setUp() {
- clientData = new ClientData(new CacheData());
- }
-
- public void testRequestDataForAddress() {
- final FormController controller = new FormController(clientData, "en", "US");
-
- delayTestFinish(15000);
-
- controller.requestDataForAddress(US_CA_ADDRESS, new DataLoadListener() {
- boolean beginCalled = false;
- @Override
- public void dataLoadingBegin() {
- beginCalled = true;
- }
-
- @Override
- public void dataLoadingEnd() {
- assertTrue("dataLoadingBegin should be called before dataLoadingEnd",
- beginCalled);
- LookupKey usCaMtvKey = new LookupKey.Builder(KeyType.DATA)
- .setAddressData(US_CA_ADDRESS).build();
- LookupKey usKey = usCaMtvKey.getKeyForUpperLevelField(
- AddressField.COUNTRY);
- LookupKey usCaKey = usCaMtvKey.getKeyForUpperLevelField(
- AddressField.ADMIN_AREA);
- assertNotNull("key should be data/US/CA", usCaKey);
- assertNotNull("key should be data/US/CA/Mt View", usCaMtvKey);
- assertNotNull(clientData.get(usKey.toString()));
- assertNotNull(clientData.get(usCaKey.toString()));
- assertNull(clientData.get(usCaMtvKey.toString()));
- finishTest();
- }
- });
- }
-
- public void testRequestDataForBadAddress() {
- final AddressData address = new AddressData.Builder(US_CA_ADDRESS)
- .setAdminArea("FOOBAR")
- .setLocality("KarKar")
- .build();
-
- final FormController controller = new FormController(clientData, "en", "US");
-
- delayTestFinish(15000);
-
- controller.requestDataForAddress(address, new DataLoadListener() {
- boolean beginCalled = false;
- @Override
- public void dataLoadingBegin() {
- beginCalled = true;
- }
-
- @Override
- public void dataLoadingEnd() {
- assertTrue("dataLoadingBegin should be called before dataLoadingEnd",
- beginCalled);
- LookupKey badKey = new LookupKey.Builder(KeyType.DATA)
- .setAddressData(address).build();
- LookupKey usKey = badKey.getKeyForUpperLevelField(AddressField.COUNTRY);
-
- List<RegionData> rdata = controller.getRegionData(usKey);
- assertTrue(rdata.size() > 0);
- String subkey = rdata.get(0).getKey();
- assertNotNull("Should be the first US state", subkey);
- LookupKey usFirstStateKey =
- new LookupKey.Builder(usKey.toString() + "/" + subkey).build();
-
- assertNotNull(clientData.get(usKey.toString()));
- assertNotNull(clientData.get(usFirstStateKey.toString()));
- assertNull(clientData.get(badKey.toString()));
- finishTest();
- }
- });
- }
-
- public void testRequestDataForCountry() {
- final FormController controller = new FormController(clientData, "en", "US");
-
- delayTestFinish(15000);
-
- controller.requestDataForAddress(US_ADDRESS, new DataLoadListener() {
- boolean beginCalled = false;
- @Override
- public void dataLoadingBegin() {
- beginCalled = true;
- }
-
- @Override
- public void dataLoadingEnd() {
- assertTrue("dataLoadingBegin should be called before dataLoadingEnd",
- beginCalled);
- LookupKey usKey = new LookupKey.Builder(KeyType.DATA)
- .setAddressData(US_ADDRESS).build();
- assertNotNull("key should be data/US", usKey);
- List<RegionData> rdata = controller.getRegionData(usKey);
- assertTrue(rdata.size() > 0);
- String subkey = rdata.get(0).getKey();
- assertNotNull("Should be the first US state", subkey);
- LookupKey usFirstStateKey =
- new LookupKey.Builder(usKey.toString() + "/" + subkey).build();
- assertNotNull(clientData.get(usKey.toString()));
- assertNotNull(clientData.get(usFirstStateKey.toString()));
- finishTest();
- }
- });
- }
+ private static final AddressData US_CA_ADDRESS;
+ private static final AddressData US_ADDRESS;
+ private ClientData clientData;
+
+ static {
+ US_CA_ADDRESS = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality("Mt View")
+ .setAddressLine1("1098 Alta Ave")
+ .setPostalCode("94043")
+ .build();
+ US_ADDRESS = new AddressData.Builder().setCountry("US").build();
+ }
+
+ @Override
+ public void setUp() {
+ clientData = new ClientData(new CacheData());
+ }
+
+ public void testRequestDataForAddress() {
+ final FormController controller = new FormController(clientData, "en", "US");
+
+ delayTestFinish(15000);
+
+ controller.requestDataForAddress(US_CA_ADDRESS, new DataLoadListener() {
+ boolean beginCalled = false;
+ @Override
+ public void dataLoadingBegin() {
+ beginCalled = true;
+ }
+
+ @Override
+ public void dataLoadingEnd() {
+ assertTrue("dataLoadingBegin should be called before dataLoadingEnd",
+ beginCalled);
+ LookupKey usCaMtvKey = new LookupKey.Builder(KeyType.DATA)
+ .setAddressData(US_CA_ADDRESS).build();
+ LookupKey usKey = usCaMtvKey.getKeyForUpperLevelField(
+ AddressField.COUNTRY);
+ LookupKey usCaKey = usCaMtvKey.getKeyForUpperLevelField(
+ AddressField.ADMIN_AREA);
+ assertNotNull("key should be data/US/CA", usCaKey);
+ assertNotNull("key should be data/US/CA/Mt View", usCaMtvKey);
+ assertNotNull(clientData.get(usKey.toString()));
+ assertNotNull(clientData.get(usCaKey.toString()));
+ assertNull(clientData.get(usCaMtvKey.toString()));
+ finishTest();
+ }
+ });
+ }
+
+ public void testRequestDataForBadAddress() {
+ final AddressData address = new AddressData.Builder(US_CA_ADDRESS)
+ .setAdminArea("FOOBAR")
+ .setLocality("KarKar")
+ .build();
+
+ final FormController controller = new FormController(clientData, "en", "US");
+
+ delayTestFinish(15000);
+
+ controller.requestDataForAddress(address, new DataLoadListener() {
+ boolean beginCalled = false;
+ @Override
+ public void dataLoadingBegin() {
+ beginCalled = true;
+ }
+
+ @Override
+ public void dataLoadingEnd() {
+ assertTrue("dataLoadingBegin should be called before dataLoadingEnd",
+ beginCalled);
+ LookupKey badKey = new LookupKey.Builder(KeyType.DATA)
+ .setAddressData(address).build();
+ LookupKey usKey = badKey.getKeyForUpperLevelField(AddressField.COUNTRY);
+
+ List<RegionData> rdata = controller.getRegionData(usKey);
+ assertTrue(rdata.size() > 0);
+ String subkey = rdata.get(0).getKey();
+ assertNotNull("Should be the first US state", subkey);
+ LookupKey usFirstStateKey =
+ new LookupKey.Builder(usKey.toString() + "/" + subkey).build();
+
+ assertNotNull(clientData.get(usKey.toString()));
+ assertNotNull(clientData.get(usFirstStateKey.toString()));
+ assertNull(clientData.get(badKey.toString()));
+ finishTest();
+ }
+ });
+ }
+
+ public void testRequestDataForCountry() {
+ final FormController controller = new FormController(clientData, "en", "US");
+
+ delayTestFinish(15000);
+
+ controller.requestDataForAddress(US_ADDRESS, new DataLoadListener() {
+ boolean beginCalled = false;
+ @Override
+ public void dataLoadingBegin() {
+ beginCalled = true;
+ }
+
+ @Override
+ public void dataLoadingEnd() {
+ assertTrue("dataLoadingBegin should be called before dataLoadingEnd",
+ beginCalled);
+ LookupKey usKey = new LookupKey.Builder(KeyType.DATA)
+ .setAddressData(US_ADDRESS).build();
+ assertNotNull("key should be data/US", usKey);
+ List<RegionData> rdata = controller.getRegionData(usKey);
+ assertTrue(rdata.size() > 0);
+ String subkey = rdata.get(0).getKey();
+ assertNotNull("Should be the first US state", subkey);
+ LookupKey usFirstStateKey =
+ new LookupKey.Builder(usKey.toString() + "/" + subkey).build();
+ assertNotNull(clientData.get(usKey.toString()));
+ assertNotNull(clientData.get(usFirstStateKey.toString()));
+ finishTest();
+ }
+ });
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/FormOptionsTest.java b/java/test/com/android/i18n/addressinput/FormOptionsTest.java
index 5f8e8c3..5e4fc6e 100644
--- a/java/test/com/android/i18n/addressinput/FormOptionsTest.java
+++ b/java/test/com/android/i18n/addressinput/FormOptionsTest.java
@@ -22,23 +22,23 @@ import junit.framework.TestCase;
* Test for building form options.
*/
public class FormOptionsTest extends TestCase {
- public void testRequiredField() throws Exception {
- FormOptions options = new FormOptions.Builder().required(AddressField.COUNTRY).build();
- assertTrue(options.isRequired(AddressField.COUNTRY));
- assertFalse(options.isRequired(AddressField.LOCALITY));
- assertTrue(options.getRequiredFields().contains(AddressField.COUNTRY));
- assertFalse(options.getRequiredFields().contains(AddressField.LOCALITY));
- }
+ public void testRequiredField() throws Exception {
+ FormOptions options = new FormOptions.Builder().required(AddressField.COUNTRY).build();
+ assertTrue(options.isRequired(AddressField.COUNTRY));
+ assertFalse(options.isRequired(AddressField.LOCALITY));
+ assertTrue(options.getRequiredFields().contains(AddressField.COUNTRY));
+ assertFalse(options.getRequiredFields().contains(AddressField.LOCALITY));
+ }
- public void testReadonlyField() throws Exception {
- FormOptions options = new FormOptions.Builder().readonly(AddressField.COUNTRY).build();
- assertTrue(options.isReadonly(AddressField.COUNTRY));
- assertFalse(options.isReadonly(AddressField.LOCALITY));
- }
+ public void testReadonlyField() throws Exception {
+ FormOptions options = new FormOptions.Builder().readonly(AddressField.COUNTRY).build();
+ assertTrue(options.isReadonly(AddressField.COUNTRY));
+ assertFalse(options.isReadonly(AddressField.LOCALITY));
+ }
- public void testHiddenField() throws Exception {
- FormOptions options = new FormOptions.Builder().hide(AddressField.COUNTRY).build();
- assertTrue(options.isHidden(AddressField.COUNTRY));
- assertFalse(options.isHidden(AddressField.LOCALITY));
- }
+ public void testHiddenField() throws Exception {
+ FormOptions options = new FormOptions.Builder().hide(AddressField.COUNTRY).build();
+ assertTrue(options.isHidden(AddressField.COUNTRY));
+ assertFalse(options.isHidden(AddressField.LOCALITY));
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java b/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java
index f5bac79..3efd37b 100644
--- a/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java
+++ b/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java
@@ -27,206 +27,206 @@ import junit.framework.TestCase;
* Tests for the FormatInterpreter class.
*/
public class FormatInterpreterTest extends TestCase {
- private static final AddressData US_CA_ADDRESS;
- private static final AddressData TW_ADDRESS;
-
- private FormatInterpreter formatInterpreter;
-
- static {
- US_CA_ADDRESS = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality("Mt View")
- .setAddressLine1("1098 Alta Ave")
- .setPostalCode("94043")
- .build();
-
- TW_ADDRESS = new AddressData.Builder().setCountry("TW")
- .setAdminArea("\u53F0\u5317\u5E02") // Taipei city
- .setLocality("\u5927\u5B89\u5340") // Da-an district
- .setAddressLine1("Sec. 3 Hsin-yi Rd.")
- .setPostalCode("106")
- .setOrganization("Giant Bike Store")
- .setRecipient("Mr. Liu")
- .build();
- }
+ private static final AddressData US_CA_ADDRESS;
+ private static final AddressData TW_ADDRESS;
+
+ private FormatInterpreter formatInterpreter;
+
+ static {
+ US_CA_ADDRESS = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality("Mt View")
+ .setAddressLine1("1098 Alta Ave")
+ .setPostalCode("94043")
+ .build();
+
+ TW_ADDRESS = new AddressData.Builder().setCountry("TW")
+ .setAdminArea("\u53F0\u5317\u5E02") // Taipei city
+ .setLocality("\u5927\u5B89\u5340") // Da-an district
+ .setAddressLine1("Sec. 3 Hsin-yi Rd.")
+ .setPostalCode("106")
+ .setOrganization("Giant Bike Store")
+ .setRecipient("Mr. Liu")
+ .build();
+ }
- @Override
- public void setUp() {
- formatInterpreter = new FormatInterpreter(new FormOptions.Builder().build());
- }
+ @Override
+ public void setUp() {
+ formatInterpreter = new FormatInterpreter(new FormOptions.Builder().build());
+ }
- public void testIterateUsAddressFields() {
- AddressField[] format = {
- AddressField.RECIPIENT,
- AddressField.ORGANIZATION,
- AddressField.ADDRESS_LINE_1,
- AddressField.ADDRESS_LINE_2,
- AddressField.LOCALITY,
- AddressField.ADMIN_AREA,
- AddressField.POSTAL_CODE
- };
-
- int currIndex = 0;
- for (AddressField field : formatInterpreter.getAddressFieldOrder(ScriptType.LOCAL, "US")) {
- assertEquals("index " + currIndex + " should have matched",
- format[currIndex].getChar(), field.getChar());
- currIndex++;
- }
+ public void testIterateUsAddressFields() {
+ AddressField[] format = {
+ AddressField.RECIPIENT,
+ AddressField.ORGANIZATION,
+ AddressField.ADDRESS_LINE_1,
+ AddressField.ADDRESS_LINE_2,
+ AddressField.LOCALITY,
+ AddressField.ADMIN_AREA,
+ AddressField.POSTAL_CODE
+ };
+
+ int currIndex = 0;
+ for (AddressField field : formatInterpreter.getAddressFieldOrder(ScriptType.LOCAL, "US")) {
+ assertEquals("index " + currIndex + " should have matched",
+ format[currIndex].getChar(), field.getChar());
+ currIndex++;
}
+ }
- /**
- * Tests that this works for the case of Vanuatu, since we have no country-specific formatting
- * data for that country. Should fall back to the default region.
- */
- public void testIterateVuAddressFields() {
- AddressField[] format = {
- AddressField.RECIPIENT,
- AddressField.ORGANIZATION,
- AddressField.ADDRESS_LINE_1,
- AddressField.ADDRESS_LINE_2,
- AddressField.LOCALITY,
- };
-
- int currIndex = 0;
- for (AddressField field : formatInterpreter.getAddressFieldOrder(ScriptType.LOCAL, "VU")) {
- assertEquals("index " + currIndex + " should have matched",
- format[currIndex].getChar(), field.getChar());
- currIndex++;
- }
+ /**
+ * Tests that this works for the case of Vanuatu, since we have no country-specific formatting
+ * data for that country. Should fall back to the default region.
+ */
+ public void testIterateVuAddressFields() {
+ AddressField[] format = {
+ AddressField.RECIPIENT,
+ AddressField.ORGANIZATION,
+ AddressField.ADDRESS_LINE_1,
+ AddressField.ADDRESS_LINE_2,
+ AddressField.LOCALITY,
+ };
+
+ int currIndex = 0;
+ for (AddressField field : formatInterpreter.getAddressFieldOrder(ScriptType.LOCAL, "VU")) {
+ assertEquals("index " + currIndex + " should have matched",
+ format[currIndex].getChar(), field.getChar());
+ currIndex++;
}
+ }
- public void testOverrideFieldOrder() {
- AddressField[] expectedOrder = {
- AddressField.ADMIN_AREA,
- AddressField.ORGANIZATION,
- AddressField.ADDRESS_LINE_1,
- AddressField.ADDRESS_LINE_2,
- AddressField.LOCALITY,
- AddressField.RECIPIENT,
- AddressField.POSTAL_CODE
- };
-
- FormatInterpreter myInterpreter = new FormatInterpreter(
- new FormOptions.Builder().customizeFieldOrder("US",
- AddressField.ADMIN_AREA,
- AddressField.RECIPIENT,
- AddressField.SORTING_CODE,
- AddressField.POSTAL_CODE).build());
-
- int currIndex = 0;
- for (AddressField field : myInterpreter.getAddressFieldOrder(ScriptType.LOCAL, "US")) {
- assertEquals("Wrong field order for US on index " + currIndex + " of address fields.",
- expectedOrder[currIndex], field);
-
- // Sorting code (CEDEX) is not in US address format and should be
- // neglected even if it is specified in customizeFieldOrder().
- assertNotSame(AddressField.SORTING_CODE, field);
- currIndex++;
- }
+ public void testOverrideFieldOrder() {
+ AddressField[] expectedOrder = {
+ AddressField.ADMIN_AREA,
+ AddressField.ORGANIZATION,
+ AddressField.ADDRESS_LINE_1,
+ AddressField.ADDRESS_LINE_2,
+ AddressField.LOCALITY,
+ AddressField.RECIPIENT,
+ AddressField.POSTAL_CODE
+ };
+
+ FormatInterpreter myInterpreter = new FormatInterpreter(
+ new FormOptions.Builder().customizeFieldOrder("US",
+ AddressField.ADMIN_AREA,
+ AddressField.RECIPIENT,
+ AddressField.SORTING_CODE,
+ AddressField.POSTAL_CODE).build());
+
+ int currIndex = 0;
+ for (AddressField field : myInterpreter.getAddressFieldOrder(ScriptType.LOCAL, "US")) {
+ assertEquals("Wrong field order for US on index " + currIndex + " of address fields.",
+ expectedOrder[currIndex], field);
+
+ // Sorting code (CEDEX) is not in US address format and should be
+ // neglected even if it is specified in customizeFieldOrder().
+ assertNotSame(AddressField.SORTING_CODE, field);
+ currIndex++;
}
+ }
- public void testIterateTwLatinAddressFields() {
- AddressField[] format = {
- AddressField.RECIPIENT,
- AddressField.ORGANIZATION,
- AddressField.ADDRESS_LINE_1,
- AddressField.ADDRESS_LINE_2,
- AddressField.LOCALITY,
- AddressField.ADMIN_AREA,
- AddressField.POSTAL_CODE
- };
-
- int currIndex = 0;
- for (AddressField field : formatInterpreter.getAddressFieldOrder(ScriptType.LATIN, "TW")) {
- assertEquals("Unexpected field order -- mismatched on index " + currIndex,
- format[currIndex].getChar(), field.getChar());
- currIndex++;
- }
+ public void testIterateTwLatinAddressFields() {
+ AddressField[] format = {
+ AddressField.RECIPIENT,
+ AddressField.ORGANIZATION,
+ AddressField.ADDRESS_LINE_1,
+ AddressField.ADDRESS_LINE_2,
+ AddressField.LOCALITY,
+ AddressField.ADMIN_AREA,
+ AddressField.POSTAL_CODE
+ };
+
+ int currIndex = 0;
+ for (AddressField field : formatInterpreter.getAddressFieldOrder(ScriptType.LATIN, "TW")) {
+ assertEquals("Unexpected field order -- mismatched on index " + currIndex,
+ format[currIndex].getChar(), field.getChar());
+ currIndex++;
}
+ }
- public void testUsEnvelopeAddress() {
- List<String> expected = new ArrayList<String>();
- expected.add("1098 Alta Ave");
- expected.add("Mt View, CA 94043");
+ public void testUsEnvelopeAddress() {
+ List<String> expected = new ArrayList<String>();
+ expected.add("1098 Alta Ave");
+ expected.add("Mt View, CA 94043");
- List<String> real = formatInterpreter.getEnvelopeAddress(US_CA_ADDRESS);
+ List<String> real = formatInterpreter.getEnvelopeAddress(US_CA_ADDRESS);
- assertEquals(expected, real);
- }
+ assertEquals(expected, real);
+ }
- public void testTwEnvelopeAddress() {
- // To be in this order, the whole address should really be in Traditional Chinese - for
- // readability, only the neighbourhood and city are.
- List<String> expected = new ArrayList<String>();
- expected.add("106");
- expected.add("\u53F0\u5317\u5E02\u5927\u5B89\u5340"); // Taipei city, Da-an district
- expected.add("Sec. 3 Hsin-yi Rd.");
- expected.add("Giant Bike Store");
- expected.add("Mr. Liu");
+ public void testTwEnvelopeAddress() {
+ // To be in this order, the whole address should really be in Traditional Chinese - for
+ // readability, only the neighbourhood and city are.
+ List<String> expected = new ArrayList<String>();
+ expected.add("106");
+ expected.add("\u53F0\u5317\u5E02\u5927\u5B89\u5340"); // Taipei city, Da-an district
+ expected.add("Sec. 3 Hsin-yi Rd.");
+ expected.add("Giant Bike Store");
+ expected.add("Mr. Liu");
- List<String> real = formatInterpreter.getEnvelopeAddress(TW_ADDRESS);
+ List<String> real = formatInterpreter.getEnvelopeAddress(TW_ADDRESS);
- assertEquals(expected, real);
- }
+ assertEquals(expected, real);
+ }
- public void testEnvelopeAddressIncompleteAddress() {
- List<String> expected = new ArrayList<String>();
- expected.add("1098 Alta Ave");
- expected.add("CA 94043");
+ public void testEnvelopeAddressIncompleteAddress() {
+ List<String> expected = new ArrayList<String>();
+ expected.add("1098 Alta Ave");
+ expected.add("CA 94043");
- AddressData address = new AddressData.Builder().set(US_CA_ADDRESS)
- .set(AddressField.LOCALITY, null).build();
+ AddressData address = new AddressData.Builder().set(US_CA_ADDRESS)
+ .set(AddressField.LOCALITY, null).build();
- List<String> real = formatInterpreter.getEnvelopeAddress(address);
+ List<String> real = formatInterpreter.getEnvelopeAddress(address);
- assertEquals(expected, real);
- }
+ assertEquals(expected, real);
+ }
- public void testEnvelopeAddressEmptyAddress() {
- List<String> expected = new ArrayList<String>();
- AddressData address = new AddressData.Builder().setCountry("US").build();
+ public void testEnvelopeAddressEmptyAddress() {
+ List<String> expected = new ArrayList<String>();
+ AddressData address = new AddressData.Builder().setCountry("US").build();
- List<String> real = formatInterpreter.getEnvelopeAddress(address);
- assertEquals(expected, real);
- }
+ List<String> real = formatInterpreter.getEnvelopeAddress(address);
+ assertEquals(expected, real);
+ }
public void testEnvelopeAddressLeadingPostPrefix() {
- List<String> expected = new ArrayList<String>();
- expected.add("CH-8047 Herrliberg");
- AddressData address = new AddressData.Builder().setCountry("CH")
- .setPostalCode("8047")
- .setLocality("Herrliberg")
- .build();
-
- List<String> real = formatInterpreter.getEnvelopeAddress(address);
- assertEquals(expected, real);
+ List<String> expected = new ArrayList<String>();
+ expected.add("CH-8047 Herrliberg");
+ AddressData address = new AddressData.Builder().setCountry("CH")
+ .setPostalCode("8047")
+ .setLocality("Herrliberg")
+ .build();
+
+ List<String> real = formatInterpreter.getEnvelopeAddress(address);
+ assertEquals(expected, real);
}
public void testSvAddress() {
- final AddressData svAddress = new AddressData.Builder().setCountry("SV")
- .setAdminArea("Ahuachapán")
- .setLocality("Ahuachapán")
- .setAddressLine1("Some Street 12")
- .build();
-
- List<String> expected = new ArrayList<String>();
- expected.add("Some Street 12");
- expected.add("Ahuachapán");
- expected.add("Ahuachapán");
-
- List<String> real = formatInterpreter.getEnvelopeAddress(svAddress);
- assertEquals(expected, real);
-
- final AddressData svAddressWithPostCode = new AddressData.Builder(svAddress)
- .setPostalCode("CP 2101")
- .build();
-
- expected = new ArrayList<String>();
- expected.add("Some Street 12");
- expected.add("CP 2101-Ahuachapán");
- expected.add("Ahuachapán");
-
- real = formatInterpreter.getEnvelopeAddress(svAddressWithPostCode);
- assertEquals(expected, real);
+ final AddressData svAddress = new AddressData.Builder().setCountry("SV")
+ .setAdminArea("Ahuachapán")
+ .setLocality("Ahuachapán")
+ .setAddressLine1("Some Street 12")
+ .build();
+
+ List<String> expected = new ArrayList<String>();
+ expected.add("Some Street 12");
+ expected.add("Ahuachapán");
+ expected.add("Ahuachapán");
+
+ List<String> real = formatInterpreter.getEnvelopeAddress(svAddress);
+ assertEquals(expected, real);
+
+ final AddressData svAddressWithPostCode = new AddressData.Builder(svAddress)
+ .setPostalCode("CP 2101")
+ .build();
+
+ expected = new ArrayList<String>();
+ expected.add("Some Street 12");
+ expected.add("CP 2101-Ahuachapán");
+ expected.add("Ahuachapán");
+
+ real = formatInterpreter.getEnvelopeAddress(svAddressWithPostCode);
+ assertEquals(expected, real);
}
}
diff --git a/java/test/com/android/i18n/addressinput/JsoMapTest.java b/java/test/com/android/i18n/addressinput/JsoMapTest.java
index 76bcbed..56e4d1e 100644
--- a/java/test/com/android/i18n/addressinput/JsoMapTest.java
+++ b/java/test/com/android/i18n/addressinput/JsoMapTest.java
@@ -30,218 +30,218 @@ import java.util.Set;
*/
public class JsoMapTest extends TestCase {
- private static final String VALID_JSON = "{\"a\":\"b\",\"c\":1,\"d\":{\"e\":\"f\"}}";
- private static final String INVALID_JSON = "!";
-
- public void testBuildJsoMap() throws Exception {
- assertNotNull(JsoMap.buildJsoMap(VALID_JSON));
-
- try {
- JsoMap.buildJsoMap(INVALID_JSON);
- fail("Expected JSONException.");
- } catch (JSONException e) {
- // Expected.
- }
- }
-
- public void testCreateEmptyJsoMap() throws Exception {
- assertNotNull(JsoMap.createEmptyJsoMap());
- }
+ private static final String VALID_JSON = "{\"a\":\"b\",\"c\":1,\"d\":{\"e\":\"f\"}}";
+ private static final String INVALID_JSON = "!";
- public void testDelKey() throws Exception {
- JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+ public void testBuildJsoMap() throws Exception {
+ assertNotNull(JsoMap.buildJsoMap(VALID_JSON));
- assertEquals("b", map.get("a"));
- map.delKey("a");
- assertNull(map.get("a"));
-
- map.delKey("b");
- map.delKey("c");
- map.delKey("d");
+ try {
+ JsoMap.buildJsoMap(INVALID_JSON);
+ fail("Expected JSONException.");
+ } catch (JSONException e) {
+ // Expected.
}
-
- public void testGet() throws Exception {
- JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
- assertEquals("b", map.get("a"));
- assertNull(map.get("b"));
-
- try {
- map.get("c");
- fail("Expected IllegalArgumentException.");
- } catch (IllegalArgumentException e) {
- // Expected.
- }
-
- try {
- map.get("d");
- fail("Expected ClassCastException.");
- } catch (ClassCastException e) {
- // Expected.
- }
+ }
+
+ public void testCreateEmptyJsoMap() throws Exception {
+ assertNotNull(JsoMap.createEmptyJsoMap());
+ }
+
+ public void testDelKey() throws Exception {
+ JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+
+ assertEquals("b", map.get("a"));
+ map.delKey("a");
+ assertNull(map.get("a"));
+
+ map.delKey("b");
+ map.delKey("c");
+ map.delKey("d");
+ }
+
+ public void testGet() throws Exception {
+ JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+ assertEquals("b", map.get("a"));
+ assertNull(map.get("b"));
+
+ try {
+ map.get("c");
+ fail("Expected IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
}
- public void testGetInt() throws Exception {
- JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
-
- try {
- map.getInt("a");
- fail("Expected RuntimeException.");
- } catch (RuntimeException e) {
- // Expected.
- }
-
- assertEquals(-1, map.getInt("b"));
- assertEquals(1, map.getInt("c"));
-
- try {
- map.getInt("d");
- fail("Expected RuntimeException.");
- } catch (RuntimeException e) {
- // Expected.
- }
+ try {
+ map.get("d");
+ fail("Expected ClassCastException.");
+ } catch (ClassCastException e) {
+ // Expected.
}
+ }
- public void testGetKeys() throws Exception {
- JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
- JSONArray keys = map.getKeys();
- assertNotNull(keys);
- assertEquals(3, keys.length());
- Set<String> keySet = new HashSet<String>(keys.length());
- for (int i = 0; i < keys.length(); i++) {
- keySet.add(keys.getString(i));
- }
- assertEquals(new HashSet<String>(Arrays.asList("a", "c", "d")), keySet);
- }
-
- public void testGetObj() throws Exception {
- JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+ public void testGetInt() throws Exception {
+ JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
- try {
- map.getObj("a");
- fail("Expected ClassCastException.");
- } catch (ClassCastException e) {
- // Expected.
- }
-
- assertNull(map.getObj("b"));
+ try {
+ map.getInt("a");
+ fail("Expected RuntimeException.");
+ } catch (RuntimeException e) {
+ // Expected.
+ }
- try {
- map.getObj("c");
- fail("Expected IllegalArgumentException.");
- } catch (IllegalArgumentException e) {
- // Expected.
- }
+ assertEquals(-1, map.getInt("b"));
+ assertEquals(1, map.getInt("c"));
- JsoMap obj = map.getObj("d");
- assertNotNull(obj);
- assertEquals("f", obj.get("e"));
+ try {
+ map.getInt("d");
+ fail("Expected RuntimeException.");
+ } catch (RuntimeException e) {
+ // Expected.
}
-
- public void testContainsKey() throws Exception {
- JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
- assertTrue(map.containsKey("a"));
- assertFalse(map.containsKey("b"));
- assertTrue(map.containsKey("c"));
- assertTrue(map.containsKey("d"));
+ }
+
+ public void testGetKeys() throws Exception {
+ JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+ JSONArray keys = map.getKeys();
+ assertNotNull(keys);
+ assertEquals(3, keys.length());
+ Set<String> keySet = new HashSet<String>(keys.length());
+ for (int i = 0; i < keys.length(); i++) {
+ keySet.add(keys.getString(i));
}
+ assertEquals(new HashSet<String>(Arrays.asList("a", "c", "d")), keySet);
+ }
- public void testMergeData() throws Exception {
- JsoMap mapA = JsoMap.createEmptyJsoMap();
- JsoMap mapB = JsoMap.createEmptyJsoMap();
-
- mapA.putInt("a", 1);
- mapA.putInt("b", 2);
-
- mapB.putInt("b", 3);
- mapB.putInt("c", 4);
+ public void testGetObj() throws Exception {
+ JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
- mapA.mergeData(mapB);
- assertEquals(1, mapA.getInt("a"));
- assertEquals(2, mapA.getInt("b"));
- assertEquals(4, mapA.getInt("c"));
+ try {
+ map.getObj("a");
+ fail("Expected ClassCastException.");
+ } catch (ClassCastException e) {
+ // Expected.
}
- public void testPut() throws Exception {
- JsoMap map = JsoMap.createEmptyJsoMap();
+ assertNull(map.getObj("b"));
- map.put("a", "b");
- assertEquals("b", map.get("a"));
-
- map.put("a", "c");
- assertEquals("c", map.get("a"));
+ try {
+ map.getObj("c");
+ fail("Expected IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
}
- public void testPutInt() throws Exception {
- JsoMap map = JsoMap.createEmptyJsoMap();
-
- map.putInt("a", 1);
- assertEquals(1, map.getInt("a"));
-
- map.putInt("a", 2);
- assertEquals(2, map.getInt("a"));
+ JsoMap obj = map.getObj("d");
+ assertNotNull(obj);
+ assertEquals("f", obj.get("e"));
+ }
+
+ public void testContainsKey() throws Exception {
+ JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+ assertTrue(map.containsKey("a"));
+ assertFalse(map.containsKey("b"));
+ assertTrue(map.containsKey("c"));
+ assertTrue(map.containsKey("d"));
+ }
+
+ public void testMergeData() throws Exception {
+ JsoMap mapA = JsoMap.createEmptyJsoMap();
+ JsoMap mapB = JsoMap.createEmptyJsoMap();
+
+ mapA.putInt("a", 1);
+ mapA.putInt("b", 2);
+
+ mapB.putInt("b", 3);
+ mapB.putInt("c", 4);
+
+ mapA.mergeData(mapB);
+ assertEquals(1, mapA.getInt("a"));
+ assertEquals(2, mapA.getInt("b"));
+ assertEquals(4, mapA.getInt("c"));
+ }
+
+ public void testPut() throws Exception {
+ JsoMap map = JsoMap.createEmptyJsoMap();
+
+ map.put("a", "b");
+ assertEquals("b", map.get("a"));
+
+ map.put("a", "c");
+ assertEquals("c", map.get("a"));
+ }
+
+ public void testPutInt() throws Exception {
+ JsoMap map = JsoMap.createEmptyJsoMap();
+
+ map.putInt("a", 1);
+ assertEquals(1, map.getInt("a"));
+
+ map.putInt("a", 2);
+ assertEquals(2, map.getInt("a"));
+ }
+
+ public void testPutObj() throws Exception {
+ JsoMap map = JsoMap.createEmptyJsoMap();
+ JsoMap obj = JsoMap.createEmptyJsoMap();
+
+ obj.putInt("a", 1);
+ map.putObj("b", obj);
+ assertEquals(obj.toString(), map.getObj("b").toString());
+
+ obj.putInt("a", 2);
+ map.putObj("b", obj);
+ assertEquals(obj.toString(), map.getObj("b").toString());
+ }
+
+ public void testString() throws Exception {
+ JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+
+ try {
+ // This should fail on the integer "c" or the map "d".
+ map.string();
+ fail("Expected IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ } catch (ClassCastException e) {
+ // Expected.
}
- public void testPutObj() throws Exception {
- JsoMap map = JsoMap.createEmptyJsoMap();
- JsoMap obj = JsoMap.createEmptyJsoMap();
-
- obj.putInt("a", 1);
- map.putObj("b", obj);
- assertEquals(obj.toString(), map.getObj("b").toString());
-
- obj.putInt("a", 2);
- map.putObj("b", obj);
- assertEquals(obj.toString(), map.getObj("b").toString());
+ map.delKey("c");
+ try {
+ // This should fail on the object "d".
+ map.string();
+ fail("Expected ClassCastException.");
+ } catch (ClassCastException e) {
+ // Expected.
}
- public void testString() throws Exception {
- JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
-
- try {
- // This should fail on the integer "c" or the map "d".
- map.string();
- fail("Expected IllegalArgumentException.");
- } catch (IllegalArgumentException e) {
- // Expected.
- } catch (ClassCastException e) {
- // Expected.
- }
-
- map.delKey("c");
- try {
- // This should fail on the object "d".
- map.string();
- fail("Expected ClassCastException.");
- } catch (ClassCastException e) {
- // Expected.
- }
-
- map.delKey("d");
- assertEquals("JsoMap[\n(a:b)\n]", map.string());
+ map.delKey("d");
+ assertEquals("JsoMap[\n(a:b)\n]", map.string());
+ }
+
+ public void testMap() throws Exception {
+ JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+ try {
+ // This should fail on the string "a" or the integer "c".
+ map.map();
+ fail("Expected ClassCastException.");
+ } catch (ClassCastException e) {
+ // Expected.
+ } catch (IllegalArgumentException e) {
+ // Expected.
}
- public void testMap() throws Exception {
- JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
- try {
- // This should fail on the string "a" or the integer "c".
- map.map();
- fail("Expected ClassCastException.");
- } catch (ClassCastException e) {
- // Expected.
- } catch (IllegalArgumentException e) {
- // Expected.
- }
-
- map.delKey("a");
- try {
- // This should fail on the integer "c".
- map.map();
- fail("Expected IllegalArgumentException.");
- } catch (IllegalArgumentException e) {
- // Expected.
- }
-
- map.delKey("c");
- assertEquals("JsoMap[\n(d:JsoMap[\n(e:f)\n])\n]", map.map());
+ map.delKey("a");
+ try {
+ // This should fail on the integer "c".
+ map.map();
+ fail("Expected IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
}
+
+ map.delKey("c");
+ assertEquals("JsoMap[\n(d:JsoMap[\n(e:f)\n])\n]", map.map());
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/JsonpRequestBuilderTest.java b/java/test/com/android/i18n/addressinput/JsonpRequestBuilderTest.java
index 392a68e..9a40d1a 100644
--- a/java/test/com/android/i18n/addressinput/JsonpRequestBuilderTest.java
+++ b/java/test/com/android/i18n/addressinput/JsonpRequestBuilderTest.java
@@ -27,131 +27,131 @@ import java.net.Socket;
import java.net.SocketTimeoutException;
public class JsonpRequestBuilderTest extends AsyncTestCase {
- private JsonpRequestBuilder builder;
-
- @Override
- public void setUp() {
- builder = new JsonpRequestBuilder();
- }
-
- public void testRequestObject() throws Exception {
- delayTestFinish(4000);
- builder.setTimeout(2000);
-
- String url = HttpServer.execute(1000, "{\"id\": \"data\"}");
-
- builder.requestObject(url, new AsyncCallback<JsoMap>() {
- @Override
- public void onFailure(Throwable caught) {
- fail(caught.toString());
- }
-
- @Override
- public void onSuccess(JsoMap result) {
- assertNotNull(result);
- assertEquals("data", result.get("id"));
- finishTest();
- }
- });
- }
-
- public void testSetTimeout() throws Exception {
- delayTestFinish(4000);
- builder.setTimeout(1000);
-
- String url = HttpServer.execute(2000, "Fubar");
-
- builder.requestObject(url, new AsyncCallback<JsoMap>() {
- @Override
- public void onFailure(Throwable caught) {
- assertNotNull(caught);
- assertTrue(caught instanceof SocketTimeoutException);
- finishTest();
- }
-
- @Override
- public void onSuccess(JsoMap result) {
- fail("The request should have timed out.");
- }
- });
- }
-
- public void testUrlEncoding() throws Exception {
- delayTestFinish(4000);
- builder.setTimeout(2000);
-
- String urlBase = HttpServer.execute(1000, "{\"id\": \"data\"}");
- String url = urlBase + "address/data/VN/B\u1EAFc K\u1EA1n";
-
- builder.requestObject(url, new AsyncCallback<JsoMap>() {
- @Override
- public void onFailure(Throwable caught) {
- fail(caught.toString());
- }
-
- @Override
- public void onSuccess(JsoMap result) {
- assertNotNull(result);
- assertEquals("data", result.get("id"));
- finishTest();
- }
- });
- }
-
+ private JsonpRequestBuilder builder;
+
+ @Override
+ public void setUp() {
+ builder = new JsonpRequestBuilder();
+ }
+
+ public void testRequestObject() throws Exception {
+ delayTestFinish(4000);
+ builder.setTimeout(2000);
+
+ String url = HttpServer.execute(1000, "{\"id\": \"data\"}");
+
+ builder.requestObject(url, new AsyncCallback<JsoMap>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ fail(caught.toString());
+ }
+
+ @Override
+ public void onSuccess(JsoMap result) {
+ assertNotNull(result);
+ assertEquals("data", result.get("id"));
+ finishTest();
+ }
+ });
+ }
+
+ public void testSetTimeout() throws Exception {
+ delayTestFinish(4000);
+ builder.setTimeout(1000);
+
+ String url = HttpServer.execute(2000, "Fubar");
+
+ builder.requestObject(url, new AsyncCallback<JsoMap>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ assertNotNull(caught);
+ assertTrue(caught instanceof SocketTimeoutException);
+ finishTest();
+ }
+
+ @Override
+ public void onSuccess(JsoMap result) {
+ fail("The request should have timed out.");
+ }
+ });
+ }
+
+ public void testUrlEncoding() throws Exception {
+ delayTestFinish(4000);
+ builder.setTimeout(2000);
+
+ String urlBase = HttpServer.execute(1000, "{\"id\": \"data\"}");
+ String url = urlBase + "address/data/VN/B\u1EAFc K\u1EA1n";
+
+ builder.requestObject(url, new AsyncCallback<JsoMap>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ fail(caught.toString());
+ }
+
+ @Override
+ public void onSuccess(JsoMap result) {
+ assertNotNull(result);
+ assertEquals("data", result.get("id"));
+ finishTest();
+ }
+ });
+ }
+
+ /**
+ * Simple implementation of an HTTP server.
+ */
+ private static class HttpServer extends Thread {
/**
- * Simple implementation of an HTTP server.
+ * Start an HTTP server that will serve one request and then terminate.
+ *
+ * @param timeoutMillis
+ * Wait this long before answering a request.
+ * @param response
+ * Reply to any request with this response.
+ * @return The URL to the server.
+ * @throws IOException
*/
- private static class HttpServer extends Thread {
- /**
- * Start an HTTP server that will serve one request and then terminate.
- *
- * @param timeoutMillis
- * Wait this long before answering a request.
- * @param response
- * Reply to any request with this response.
- * @return The URL to the server.
- * @throws IOException
- */
- public static String execute(long timeoutMillis, String response) throws IOException {
- HttpServer server = new HttpServer(timeoutMillis, response);
- server.start();
- return "http://localhost:" + server.serverSocket.getLocalPort() + "/";
- }
+ public static String execute(long timeoutMillis, String response) throws IOException {
+ HttpServer server = new HttpServer(timeoutMillis, response);
+ server.start();
+ return "http://localhost:" + server.serverSocket.getLocalPort() + "/";
+ }
- @Override
- public void run() {
- try {
- Socket clientSocket = serverSocket.accept();
- try {
- synchronized (this) {
- wait(waitMillis);
- }
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- InputStream inputStream = clientSocket.getInputStream();
- inputStream.read(new byte[1024]); // Discard input.
- OutputStream outputStream = clientSocket.getOutputStream();
- outputStream.write(response);
- outputStream.close();
- inputStream.close();
- clientSocket.close();
- serverSocket.close();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ @Override
+ public void run() {
+ try {
+ Socket clientSocket = serverSocket.accept();
+ try {
+ synchronized (this) {
+ wait(waitMillis);
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
}
+ InputStream inputStream = clientSocket.getInputStream();
+ inputStream.read(new byte[1024]); // Discard input.
+ OutputStream outputStream = clientSocket.getOutputStream();
+ outputStream.write(response);
+ outputStream.close();
+ inputStream.close();
+ clientSocket.close();
+ serverSocket.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
- private HttpServer(long waitMillis, String response) throws IOException {
- this.waitMillis = waitMillis;
- this.response = (header + response).getBytes();
- serverSocket = new ServerSocket(0);
- }
+ private HttpServer(long waitMillis, String response) throws IOException {
+ this.waitMillis = waitMillis;
+ this.response = (header + response).getBytes();
+ serverSocket = new ServerSocket(0);
+ }
- private long waitMillis;
- private byte[] response;
- private ServerSocket serverSocket;
+ private long waitMillis;
+ private byte[] response;
+ private ServerSocket serverSocket;
- private static final String header = "HTTP/1.0 200 OK\nContent-Type: text/plain\n\n";
- }
+ private static final String header = "HTTP/1.0 200 OK\nContent-Type: text/plain\n\n";
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/LookupKeyTest.java b/java/test/com/android/i18n/addressinput/LookupKeyTest.java
index 608e076..fa07618 100644
--- a/java/test/com/android/i18n/addressinput/LookupKeyTest.java
+++ b/java/test/com/android/i18n/addressinput/LookupKeyTest.java
@@ -27,211 +27,211 @@ import junit.framework.TestCase;
* Unit tests for the LookupKey class.
*/
public class LookupKeyTest extends TestCase {
- private static final String ROOT_KEY = "data";
- private static final String ROOT_EXAMPLE_KEY = "examples";
- private static final String US_KEY = "data/US";
- private static final String CALIFORNIA_KEY = "data/US/CA";
- private static final String EXAMPLE_LOCAL_US_KEY = "examples/US/local/_default";
-
- // Data key for Da-an District, Taipei Taiwan
- private static final String TW_KEY = "data/TW/\u53F0\u5317\u5E02/\u5927\u5B89\u5340";
-
- // Example key for TW's address (local script)
- private static final String TW_EXAMPLE_LOCAL_KEY = "examples/TW/local/_default";
-
- // Example key for TW's address (latin script)
- private static final String TW_EXAMPLE_LATIN_KEY = "examples/TW/latin/_default";
-
- private static final String RANDOM_KEY = "sdfIisooIFOOBAR";
- private static final String RANDOM_COUNTRY_KEY = "data/asIOSDxcowW";
-
- public void testRootKey() {
- LookupKey key = new LookupKey.Builder(KeyType.DATA).build();
- assertEquals(ROOT_KEY, key.toString());
-
- LookupKey key2 = new LookupKey.Builder(key.toString()).build();
- assertEquals(ROOT_KEY, key2.toString());
+ private static final String ROOT_KEY = "data";
+ private static final String ROOT_EXAMPLE_KEY = "examples";
+ private static final String US_KEY = "data/US";
+ private static final String CALIFORNIA_KEY = "data/US/CA";
+ private static final String EXAMPLE_LOCAL_US_KEY = "examples/US/local/_default";
+
+ // Data key for Da-an District, Taipei Taiwan
+ private static final String TW_KEY = "data/TW/\u53F0\u5317\u5E02/\u5927\u5B89\u5340";
+
+ // Example key for TW's address (local script)
+ private static final String TW_EXAMPLE_LOCAL_KEY = "examples/TW/local/_default";
+
+ // Example key for TW's address (latin script)
+ private static final String TW_EXAMPLE_LATIN_KEY = "examples/TW/latin/_default";
+
+ private static final String RANDOM_KEY = "sdfIisooIFOOBAR";
+ private static final String RANDOM_COUNTRY_KEY = "data/asIOSDxcowW";
+
+ public void testRootKey() {
+ LookupKey key = new LookupKey.Builder(KeyType.DATA).build();
+ assertEquals(ROOT_KEY, key.toString());
+
+ LookupKey key2 = new LookupKey.Builder(key.toString()).build();
+ assertEquals(ROOT_KEY, key2.toString());
+ }
+
+ public void testDataKeys() {
+ LookupKey key = new LookupKey.Builder(US_KEY).build();
+ assertEquals(US_KEY, key.toString());
+
+ LookupKey key2 = new LookupKey.Builder(CALIFORNIA_KEY).build();
+ assertEquals(CALIFORNIA_KEY, key2.toString());
+ }
+
+ public void testExampleRootKeys() {
+ LookupKey key = new LookupKey.Builder(KeyType.EXAMPLES).build();
+ assertEquals(ROOT_EXAMPLE_KEY, key.toString());
+ }
+
+ public void testExampleKeys() {
+ AddressData address = new AddressData.Builder().setCountry("US")
+ .setLanguageCode("en")
+ .build();
+
+ LookupKey key = new LookupKey.Builder(KeyType.EXAMPLES).setAddressData(address).build();
+ assertEquals(EXAMPLE_LOCAL_US_KEY, key.toString());
+
+ key = new LookupKey.Builder(EXAMPLE_LOCAL_US_KEY).build();
+ assertEquals(EXAMPLE_LOCAL_US_KEY, key.toString());
+ }
+
+ public void testKeyWithWrongScriptType() {
+ String wrongScript = "examples/US/asdfasdfasdf/_default";
+ try {
+ new LookupKey.Builder(wrongScript).build();
+ fail("should fail since the script type is wrong");
+ } catch (RuntimeException e) {
+ // Expected.
}
-
- public void testDataKeys() {
- LookupKey key = new LookupKey.Builder(US_KEY).build();
- assertEquals(US_KEY, key.toString());
-
- LookupKey key2 = new LookupKey.Builder(CALIFORNIA_KEY).build();
- assertEquals(CALIFORNIA_KEY, key2.toString());
- }
-
- public void testExampleRootKeys() {
- LookupKey key = new LookupKey.Builder(KeyType.EXAMPLES).build();
- assertEquals(ROOT_EXAMPLE_KEY, key.toString());
+ }
+
+ public void testFallbackToCountry() {
+ // Admin Area is missing.
+ AddressData address = new AddressData.Builder().setCountry("US")
+ .setLocality("Mt View")
+ .build();
+
+ LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
+
+ assertEquals("locality should be omitted since admin area is not specified", US_KEY,
+ key.toString());
+
+ // Tries key string with the same problem (missing Admin Area).
+ key = new LookupKey.Builder("data/US//Mt View").build();
+
+ assertEquals("locality should be omitted since admin area is not specified", US_KEY,
+ key.toString());
+ }
+
+ public void testNonUsAddress() {
+ AddressData address = new AddressData.Builder().setCountry("TW")
+ // Taipei City
+ .setAdminArea("\u53F0\u5317\u5E02")
+ // Da-an District
+ .setLocality("\u5927\u5B89\u5340")
+ .build();
+
+ LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
+ assertEquals(TW_KEY, key.toString());
+
+ key = new LookupKey.Builder(KeyType.EXAMPLES).setAddressData(address).build();
+ assertEquals(TW_EXAMPLE_LOCAL_KEY, key.toString());
+
+ address = new AddressData.Builder(address).setLanguageCode("zh-latn").build();
+ key = new LookupKey.Builder(KeyType.EXAMPLES).setAddressData(address).build();
+ assertEquals(TW_EXAMPLE_LATIN_KEY, key.toString());
+ }
+
+ public void testGetKeyForUpperLevelFieldWithDataKey() {
+ AddressData address = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality("Mt View")
+ .build();
+
+ LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
+ LookupKey newKey = key.getKeyForUpperLevelField(AddressField.COUNTRY);
+ assertNotNull("failed to get key for " + AddressField.COUNTRY, newKey);
+ assertEquals("data/US", newKey.toString());
+
+ newKey = key.getKeyForUpperLevelField(AddressField.ADMIN_AREA);
+ assertNotNull("failed to get key for " + AddressField.ADMIN_AREA, newKey);
+ assertEquals("data/US/CA", newKey.toString());
+ assertEquals("original key should not be changed", "data/US/CA/Mt View", key.toString());
+
+ newKey = key.getKeyForUpperLevelField(AddressField.LOCALITY);
+ assertNotNull("failed to get key for " + AddressField.LOCALITY, newKey);
+ assertEquals("data/US/CA/Mt View", newKey.toString());
+
+ newKey = key.getKeyForUpperLevelField(AddressField.DEPENDENT_LOCALITY);
+ assertNull("should return null for field not contained in current key", newKey);
+
+ newKey = key.getKeyForUpperLevelField(AddressField.RECIPIENT);
+ assertNull("should return null since field '" + AddressField.RECIPIENT +
+ "' is not in address hierarchy", newKey);
+ }
+
+ public void testGetKeyForUpperLevelFieldWithExampleKey() {
+ LookupKey key = new LookupKey.Builder("examples/US/latin/_default").build();
+
+ try {
+ key.getKeyForUpperLevelField(AddressField.COUNTRY);
+ fail("should fail if you try to get parent key for an example key.");
+ } catch (RuntimeException e) {
+ // Expected.
}
+ }
- public void testExampleKeys() {
- AddressData address = new AddressData.Builder().setCountry("US")
- .setLanguageCode("en")
- .build();
+ public void testGetParentKey() {
+ AddressData address = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality("Mt View")
+ .setDependentLocality("El Camino")
+ .build();
- LookupKey key = new LookupKey.Builder(KeyType.EXAMPLES).setAddressData(address).build();
- assertEquals(EXAMPLE_LOCAL_US_KEY, key.toString());
+ LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
+ assertEquals("data/US/CA/Mt View/El Camino", key.toString());
- key = new LookupKey.Builder(EXAMPLE_LOCAL_US_KEY).build();
- assertEquals(EXAMPLE_LOCAL_US_KEY, key.toString());
- }
+ key = key.getParentKey();
+ assertEquals("data/US/CA/Mt View", key.toString());
- public void testKeyWithWrongScriptType() {
- String wrongScript = "examples/US/asdfasdfasdf/_default";
- try {
- new LookupKey.Builder(wrongScript).build();
- fail("should fail since the script type is wrong");
- } catch (RuntimeException e) {
- // Expected.
- }
- }
+ key = key.getParentKey();
+ assertEquals("data/US/CA", key.toString());
- public void testFallbackToCountry() {
- // Admin Area is missing.
- AddressData address = new AddressData.Builder().setCountry("US")
- .setLocality("Mt View")
- .build();
+ key = key.getParentKey();
+ assertEquals("data/US", key.toString());
- LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
+ key = key.getParentKey();
+ assertEquals("data", key.toString());
- assertEquals("locality should be omitted since admin area is not specified", US_KEY,
- key.toString());
+ key = key.getParentKey();
+ assertNull("root key's parent should be null", key);
+ }
- // Tries key string with the same problem (missing Admin Area).
- key = new LookupKey.Builder("data/US//Mt View").build();
-
- assertEquals("locality should be omitted since admin area is not specified", US_KEY,
- key.toString());
- }
-
- public void testNonUsAddress() {
- AddressData address = new AddressData.Builder().setCountry("TW")
- // Taipei City
- .setAdminArea("\u53F0\u5317\u5E02")
- // Da-an District
- .setLocality("\u5927\u5B89\u5340")
- .build();
-
- LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
- assertEquals(TW_KEY, key.toString());
-
- key = new LookupKey.Builder(KeyType.EXAMPLES).setAddressData(address).build();
- assertEquals(TW_EXAMPLE_LOCAL_KEY, key.toString());
-
- address = new AddressData.Builder(address).setLanguageCode("zh-latn").build();
- key = new LookupKey.Builder(KeyType.EXAMPLES).setAddressData(address).build();
- assertEquals(TW_EXAMPLE_LATIN_KEY, key.toString());
+ public void testInvalidKeyTypeWillFail() {
+ try {
+ new LookupKey.Builder(RANDOM_KEY).build();
+ fail("Should fail if key string does not start with a valid key type");
+ } catch (RuntimeException e) {
+ // Expected.
}
-
- public void testGetKeyForUpperLevelFieldWithDataKey() {
- AddressData address = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality("Mt View")
- .build();
-
- LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
- LookupKey newKey = key.getKeyForUpperLevelField(AddressField.COUNTRY);
- assertNotNull("failed to get key for " + AddressField.COUNTRY, newKey);
- assertEquals("data/US", newKey.toString());
-
- newKey = key.getKeyForUpperLevelField(AddressField.ADMIN_AREA);
- assertNotNull("failed to get key for " + AddressField.ADMIN_AREA, newKey);
- assertEquals("data/US/CA", newKey.toString());
- assertEquals("original key should not be changed", "data/US/CA/Mt View", key.toString());
-
- newKey = key.getKeyForUpperLevelField(AddressField.LOCALITY);
- assertNotNull("failed to get key for " + AddressField.LOCALITY, newKey);
- assertEquals("data/US/CA/Mt View", newKey.toString());
-
- newKey = key.getKeyForUpperLevelField(AddressField.DEPENDENT_LOCALITY);
- assertNull("should return null for field not contained in current key", newKey);
-
- newKey = key.getKeyForUpperLevelField(AddressField.RECIPIENT);
- assertNull("should return null since field '" + AddressField.RECIPIENT +
- "' is not in address hierarchy", newKey);
- }
-
- public void testGetKeyForUpperLevelFieldWithExampleKey() {
- LookupKey key = new LookupKey.Builder("examples/US/latin/_default").build();
-
- try {
- key.getKeyForUpperLevelField(AddressField.COUNTRY);
- fail("should fail if you try to get parent key for an example key.");
- } catch (RuntimeException e) {
- // Expected.
- }
- }
-
- public void testGetParentKey() {
- AddressData address = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality("Mt View")
- .setDependentLocality("El Camino")
- .build();
-
- LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
- assertEquals("data/US/CA/Mt View/El Camino", key.toString());
-
- key = key.getParentKey();
- assertEquals("data/US/CA/Mt View", key.toString());
-
- key = key.getParentKey();
- assertEquals("data/US/CA", key.toString());
-
- key = key.getParentKey();
- assertEquals("data/US", key.toString());
-
- key = key.getParentKey();
- assertEquals("data", key.toString());
-
- key = key.getParentKey();
- assertNull("root key's parent should be null", key);
- }
-
- public void testInvalidKeyTypeWillFail() {
- try {
- new LookupKey.Builder(RANDOM_KEY).build();
- fail("Should fail if key string does not start with a valid key type");
- } catch (RuntimeException e) {
- // Expected.
- }
- }
-
- /**
- * Ensures that even when the input key string is random, we still create a key. (We do not
- * verify if the key maps to an real world entity like a city or country).
- */
- public void testWeDontVerifyKeyName() {
- LookupKey key = new LookupKey.Builder(RANDOM_COUNTRY_KEY).build();
- assertEquals(RANDOM_COUNTRY_KEY, key.toString());
- }
-
- public void testHash() {
- String keys[] = { ROOT_KEY, ROOT_EXAMPLE_KEY, US_KEY, CALIFORNIA_KEY };
- Map<LookupKey, String> map = new HashMap<LookupKey, String>();
-
- for (String key : keys) {
- map.put(new LookupKey.Builder(key).build(), key);
- }
-
- for (String key : keys) {
- assertTrue(map.containsKey(new LookupKey.Builder(key).build()));
- assertEquals(key, map.get(new LookupKey.Builder(key).build()));
- }
- assertFalse(map.containsKey(new LookupKey.Builder(RANDOM_COUNTRY_KEY).build()));
- }
-
- public void testGetValueForUpperLevelField() {
- LookupKey key = new LookupKey.Builder("data/US/CA").build();
- assertEquals("US", key.getValueForUpperLevelField(AddressField.COUNTRY));
+ }
+
+ /**
+ * Ensures that even when the input key string is random, we still create a key. (We do not
+ * verify if the key maps to an real world entity like a city or country).
+ */
+ public void testWeDontVerifyKeyName() {
+ LookupKey key = new LookupKey.Builder(RANDOM_COUNTRY_KEY).build();
+ assertEquals(RANDOM_COUNTRY_KEY, key.toString());
+ }
+
+ public void testHash() {
+ String keys[] = { ROOT_KEY, ROOT_EXAMPLE_KEY, US_KEY, CALIFORNIA_KEY };
+ Map<LookupKey, String> map = new HashMap<LookupKey, String>();
+
+ for (String key : keys) {
+ map.put(new LookupKey.Builder(key).build(), key);
}
- public void testGetValueForUpperLevelFieldInvalid() {
- LookupKey key = new LookupKey.Builder("data").build();
- assertEquals("", key.getValueForUpperLevelField(AddressField.COUNTRY));
- LookupKey key2 = new LookupKey.Builder("data/").build();
- assertEquals("", key2.getValueForUpperLevelField(AddressField.COUNTRY));
+ for (String key : keys) {
+ assertTrue(map.containsKey(new LookupKey.Builder(key).build()));
+ assertEquals(key, map.get(new LookupKey.Builder(key).build()));
}
+ assertFalse(map.containsKey(new LookupKey.Builder(RANDOM_COUNTRY_KEY).build()));
+ }
+
+ public void testGetValueForUpperLevelField() {
+ LookupKey key = new LookupKey.Builder("data/US/CA").build();
+ assertEquals("US", key.getValueForUpperLevelField(AddressField.COUNTRY));
+ }
+
+ public void testGetValueForUpperLevelFieldInvalid() {
+ LookupKey key = new LookupKey.Builder("data").build();
+ assertEquals("", key.getValueForUpperLevelField(AddressField.COUNTRY));
+ LookupKey key2 = new LookupKey.Builder("data/").build();
+ assertEquals("", key2.getValueForUpperLevelField(AddressField.COUNTRY));
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/RegionDataConstantsTest.java b/java/test/com/android/i18n/addressinput/RegionDataConstantsTest.java
index f623146..d268c5f 100644
--- a/java/test/com/android/i18n/addressinput/RegionDataConstantsTest.java
+++ b/java/test/com/android/i18n/addressinput/RegionDataConstantsTest.java
@@ -23,22 +23,22 @@ import junit.framework.TestCase;
* and converted into the appropriate format.
*/
public class RegionDataConstantsTest extends TestCase {
- public void testDataLoad() throws Exception {
- assertFalse("The list of countries should not be empty",
- RegionDataConstants.getCountryFormatMap().isEmpty());
- }
+ public void testDataLoad() throws Exception {
+ assertFalse("The list of countries should not be empty",
+ RegionDataConstants.getCountryFormatMap().isEmpty());
+ }
- public void testZZRegion() throws Exception {
- assertNotNull("Data for 'ZZ' is missing (needed for default region info.)",
- RegionDataConstants.getCountryFormatMap().get("ZZ"));
- }
+ public void testZZRegion() throws Exception {
+ assertNotNull("Data for 'ZZ' is missing (needed for default region info.)",
+ RegionDataConstants.getCountryFormatMap().get("ZZ"));
+ }
- public void testStringsAreConvertedIntoJson() throws Exception {
- String[] input = { "key", "value", "key2", "value2" };
- // Input order is not maintained, since we build this using JSON objects. This is
- // unimportant, so long as the key-value mappings are maintained.
- String expectedOutput = "{\"key2\":\"value2\",\"key\":\"value\"}";
- String actualOutput = RegionDataConstants.convertArrayToJsonString(input);
- assertEquals(expectedOutput, actualOutput);
- }
+ public void testStringsAreConvertedIntoJson() throws Exception {
+ String[] input = { "key", "value", "key2", "value2" };
+ // Input order is not maintained, since we build this using JSON objects. This is
+ // unimportant, so long as the key-value mappings are maintained.
+ String expectedOutput = "{\"key2\":\"value2\",\"key\":\"value\"}";
+ String actualOutput = RegionDataConstants.convertArrayToJsonString(input);
+ assertEquals(expectedOutput, actualOutput);
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/RegionDataTest.java b/java/test/com/android/i18n/addressinput/RegionDataTest.java
index 547f934..4731e4d 100644
--- a/java/test/com/android/i18n/addressinput/RegionDataTest.java
+++ b/java/test/com/android/i18n/addressinput/RegionDataTest.java
@@ -22,28 +22,28 @@ import junit.framework.TestCase;
* Small unit tests for the RegionData class.
*/
public class RegionDataTest extends TestCase {
- public void testBuilder() throws Exception {
- RegionData data = new RegionData.Builder().setKey("CA").setName("California").build();
- assertEquals("CA", data.getKey());
- assertEquals("California", data.getName());
- assertTrue(data.isValidName("CA"));
- // Should match either the key or the name.
- assertTrue(data.isValidName("California"));
- // Matching should be case-insensitive.
- assertTrue(data.isValidName("ca"));
- assertFalse(data.isValidName("Cat"));
- }
+ public void testBuilder() throws Exception {
+ RegionData data = new RegionData.Builder().setKey("CA").setName("California").build();
+ assertEquals("CA", data.getKey());
+ assertEquals("California", data.getName());
+ assertTrue(data.isValidName("CA"));
+ // Should match either the key or the name.
+ assertTrue(data.isValidName("California"));
+ // Matching should be case-insensitive.
+ assertTrue(data.isValidName("ca"));
+ assertFalse(data.isValidName("Cat"));
+ }
- public void testBuilderNoName() throws Exception {
- RegionData data = new RegionData.Builder().setKey("CA").build();
- assertEquals("CA", data.getKey());
- assertEquals(null, data.getName());
- }
+ public void testBuilderNoName() throws Exception {
+ RegionData data = new RegionData.Builder().setKey("CA").build();
+ assertEquals("CA", data.getKey());
+ assertEquals(null, data.getName());
+ }
- public void testBuilderWhitespaceName() throws Exception {
- RegionData data = new RegionData.Builder().setKey("CA").setName(" ").build();
- assertEquals("CA", data.getKey());
- assertEquals(null, data.getName());
- assertEquals("CA", data.getDisplayName());
- }
+ public void testBuilderWhitespaceName() throws Exception {
+ RegionData data = new RegionData.Builder().setKey("CA").setName(" ").build();
+ assertEquals("CA", data.getKey());
+ assertEquals(null, data.getName());
+ assertEquals("CA", data.getDisplayName());
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/StandardAddressVerifierTest.java b/java/test/com/android/i18n/addressinput/StandardAddressVerifierTest.java
index f2c86f6..f47e64f 100644
--- a/java/test/com/android/i18n/addressinput/StandardAddressVerifierTest.java
+++ b/java/test/com/android/i18n/addressinput/StandardAddressVerifierTest.java
@@ -23,235 +23,235 @@ import junit.framework.TestCase;
*/
public class StandardAddressVerifierTest extends TestCase {
- private AddressProblems problems = new AddressProblems();
- private StandardAddressVerifier verifier;
-
- @Override
- protected void setUp() {
- problems.clear();
- verifier = new StandardAddressVerifier(new FieldVerifier(new ClientData(new CacheData())),
- StandardChecks.PROBLEM_MAP);
- }
-
- public void testUnitedStatesOk() {
- AddressData addr = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality("Mountain View")
- .setAddress("1234 Somewhere")
- .setPostalCode("94025")
- .build();
- verifier.verify(addr, problems);
- assertTrue(problems.toString(), problems.isEmpty()); // no mismatch
- }
-
- public void testUnitedStatesZipMismatch() {
- AddressData addr = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality("Mountain View")
- .setPostalCode("12345")
- .build();
- verifier.verify(addr, problems);
-
- assertEquals(AddressProblemType.MISMATCHING_VALUE,
- problems.getProblem(AddressField.POSTAL_CODE));
- }
-
- public void testUnitedStatesNotOk() {
- AddressData addr = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality(null)
- .setDependentLocality("Foo Bar")
- .setPostalCode("12345")
- .build();
- verifier.verify(addr, problems);
-
- assertEquals(AddressProblemType.MISMATCHING_VALUE,
- problems.getProblem(AddressField.POSTAL_CODE));
- assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
- problems.getProblem(AddressField.LOCALITY));
- }
-
- public void testChinaOk() {
- AddressData addr = new AddressData.Builder().setCountry("CN")
- .setAdminArea("Beijing Shi")
- .setLocality("Xicheng Qu")
- .setAddress("Yitiao Lu")
- .setPostalCode("123456")
- .build();
- verifier.verify(addr, problems);
- assertTrue(problems.toString(), problems.isEmpty());
- }
-
- public void testGermanAddress() {
- AddressData addr = new AddressData.Builder().setCountry("DE")
- .setLocality("Berlin")
- .setAddress("Huttenstr. 50")
- .setPostalCode("10553")
- .setOrganization("BMW AG Niederkassung Berlin")
- .setRecipient("Herr Diefendorf")
- .build();
-
- verifier.verify(addr, problems);
- assertTrue(problems.toString(), problems.isEmpty());
-
- // Clones address but leave city empty.
- addr = new AddressData.Builder().set(addr).setLocality(null).build();
-
- verifier.verify(addr, problems);
- assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
- problems.getProblem(AddressField.LOCALITY));
- }
-
- public void testIrishAddress() {
- AddressData addr = new AddressData.Builder().setCountry("IE")
- .setLocality("Dublin")
- .setAdminArea("Co. Dublin")
- .setAddress("7424 118 Avenue NW")
- .setRecipient("Conan O'Brien")
- .build();
-
- verifier.verify(addr, problems);
- assertTrue(problems.toString(), problems.isEmpty());
-
- // Clones address but leave county empty. This address should be valid
- // since county is not required.
- addr = new AddressData.Builder().set(addr).setAdminArea(null).build();
-
- verifier.verify(addr, problems);
- assertTrue(problems.toString(), problems.isEmpty());
- }
-
- public void testChinaPostalCodeBadFormat() {
- AddressData addr = new AddressData.Builder().setCountry("CN")
- .setAdminArea("Beijing Shi")
- .setLocality("Xicheng Qu")
- .setPostalCode("12345")
- .build();
- verifier.verify(addr, problems);
-
- // ensure problem is unrecognized format and problem is in POSTAL_CODE
- assertEquals(AddressProblemType.UNRECOGNIZED_FORMAT,
- problems.getProblem(AddressField.POSTAL_CODE));
- }
-
- /**
- * If there is a postal code pattern for a certain country, and the input postal code is empty,
- * it should not be reported as bad postal code format. Whether empty postal code is ok should
- * be determined by checks for required fields.
- */
- public void testEmptyPostalCodeReportedAsGoodFormat() {
- // Chilean address has a postal code format pattern, but does not require
- // postal code. The following address is valid.
- AddressData addr = new AddressData.Builder().setCountry("CL")
- .setAddressLine1("GUSTAVO LE PAIGE ST #159")
- .setAdminArea("Atacama")
- .setLocality("San Pedro")
- .setPostalCode("")
- .build();
- verifier.verify(addr, problems);
- assertTrue(problems.toString(), problems.isEmpty());
-
- problems.clear();
-
- // Now checks for US addresses, which requires postal code. The following
- // address's postal code is wrong because it misses required field, not
- // because it mismatches expected postal code pattern.
- addr = new AddressData.Builder().setCountry("US").setPostalCode("").build();
- problems.clear();
- verifier.verify(addr, problems);
-
- assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
- problems.getProblem(AddressField.POSTAL_CODE));
- }
-
- public void testChinaTaiwanOk() {
- AddressData addr = new AddressData.Builder().setCountry("CN")
- .setAdminArea("Taiwan")
- .setLocality("Taichung City")
- .setDependentLocality("Situn District")
- .setAddress("12345 Yitiao Lu")
- .setPostalCode("407")
- .build();
- verifier.verify(addr, problems);
- assertTrue(problems.toString(), problems.isEmpty());
- }
-
- public void testChinaTaiwanUnknownDistrict() {
- AddressData addr = new AddressData.Builder().setCountry("CN")
- .setAdminArea("Taiwan")
- .setLocality("Taichung City")
- .setDependentLocality("Foo Bar")
- .setPostalCode("400")
- .build();
- verifier.verify(addr, problems);
-
- assertEquals(AddressProblemType.UNKNOWN_VALUE,
- problems.getProblem(AddressField.DEPENDENT_LOCALITY));
- }
-
- public void testStreetVerification() {
- // missing street address
- AddressData addr = new AddressData.Builder().setCountry("US")
- .setAdminArea("CA")
- .setLocality("Mountain View")
- .setPostalCode("94025")
- .build();
-
- assertNull(addr.getAddressLine1());
- assertNull(addr.getAddressLine2());
-
- verifier.verify(addr, problems);
-
- assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
- problems.getProblem(AddressField.STREET_ADDRESS));
- }
-
- // Tests The Bahamas' address
- public void failingtestBahamas() {
- final AddressData address =
- new AddressData.Builder().setAddress("Abaco Beach Resort & Boat Habour")
- .setLocality("Treasure Cay")
- .setAdminArea("Abaco")
- .setCountry("BS")
- .build();
- verifier.verify(address, problems);
- assertTrue(problems.toString(), problems.isEmpty());
- }
-
- public void testJapan() {
- // added AdminArea since address verification can't infer it from Kyoto City
- // commented out dependent locality since address verification doesn't use it
- // TODO: support inference of higher levels from lower ones
- // TODO: add dependent locality support for japan addresses
- final AddressData address =
- new AddressData.Builder()
- .setRecipient("\u5BAE\u672C \u8302") // SHIGERU_MIYAMOTO
- .setAddress("\u4E0A\u9CE5\u7FBD\u927E\u7ACB\u753A11\u756A\u5730")
- .setAdminArea("\u4eac\u90fd\u5e9c") // Kyoto prefecture, added
- .setLocality("\u4EAC\u90FD\u5E02") // Kyoto city
- // .setDependentLocality("\u5357\u533A")
- .setCountry("JP")
- .setPostalCode("601-8501")
- .build();
- verifier.verify(address, problems);
- assertTrue(problems.toString(), problems.isEmpty());
- }
-
- public void testJapanLatin() {
- // added AdminArea since address verification can't infer it from Kyoto City
- // commented out dependent locality since address verification doesn't use it
- final AddressData address =
- new AddressData.Builder()
- .setRecipient("Shigeru Miyamoto") // SHIGERU_MIYAMOTO_ENGLISH
- .setAddress("11-1 Kamitoba-hokotate-cho")
- .setAdminArea("KYOTO") // Kyoto prefecture, added
- .setLocality("Kyoto") // Kyoto city
- // .setDependentLocality("Minami-ku")
- .setLanguageCode("ja_Latn")
- .setCountry("JP")
- .setPostalCode("601-8501")
- .build();
- verifier.verify(address, problems);
- assertTrue(problems.toString(), problems.isEmpty());
- }
+ private AddressProblems problems = new AddressProblems();
+ private StandardAddressVerifier verifier;
+
+ @Override
+ protected void setUp() {
+ problems.clear();
+ verifier = new StandardAddressVerifier(new FieldVerifier(new ClientData(new CacheData())),
+ StandardChecks.PROBLEM_MAP);
+ }
+
+ public void testUnitedStatesOk() {
+ AddressData addr = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality("Mountain View")
+ .setAddress("1234 Somewhere")
+ .setPostalCode("94025")
+ .build();
+ verifier.verify(addr, problems);
+ assertTrue(problems.toString(), problems.isEmpty()); // no mismatch
+ }
+
+ public void testUnitedStatesZipMismatch() {
+ AddressData addr = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality("Mountain View")
+ .setPostalCode("12345")
+ .build();
+ verifier.verify(addr, problems);
+
+ assertEquals(AddressProblemType.MISMATCHING_VALUE,
+ problems.getProblem(AddressField.POSTAL_CODE));
+ }
+
+ public void testUnitedStatesNotOk() {
+ AddressData addr = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality(null)
+ .setDependentLocality("Foo Bar")
+ .setPostalCode("12345")
+ .build();
+ verifier.verify(addr, problems);
+
+ assertEquals(AddressProblemType.MISMATCHING_VALUE,
+ problems.getProblem(AddressField.POSTAL_CODE));
+ assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
+ problems.getProblem(AddressField.LOCALITY));
+ }
+
+ public void testChinaOk() {
+ AddressData addr = new AddressData.Builder().setCountry("CN")
+ .setAdminArea("Beijing Shi")
+ .setLocality("Xicheng Qu")
+ .setAddress("Yitiao Lu")
+ .setPostalCode("123456")
+ .build();
+ verifier.verify(addr, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+ }
+
+ public void testGermanAddress() {
+ AddressData addr = new AddressData.Builder().setCountry("DE")
+ .setLocality("Berlin")
+ .setAddress("Huttenstr. 50")
+ .setPostalCode("10553")
+ .setOrganization("BMW AG Niederkassung Berlin")
+ .setRecipient("Herr Diefendorf")
+ .build();
+
+ verifier.verify(addr, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+
+ // Clones address but leave city empty.
+ addr = new AddressData.Builder().set(addr).setLocality(null).build();
+
+ verifier.verify(addr, problems);
+ assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
+ problems.getProblem(AddressField.LOCALITY));
+ }
+
+ public void testIrishAddress() {
+ AddressData addr = new AddressData.Builder().setCountry("IE")
+ .setLocality("Dublin")
+ .setAdminArea("Co. Dublin")
+ .setAddress("7424 118 Avenue NW")
+ .setRecipient("Conan O'Brien")
+ .build();
+
+ verifier.verify(addr, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+
+ // Clones address but leave county empty. This address should be valid
+ // since county is not required.
+ addr = new AddressData.Builder().set(addr).setAdminArea(null).build();
+
+ verifier.verify(addr, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+ }
+
+ public void testChinaPostalCodeBadFormat() {
+ AddressData addr = new AddressData.Builder().setCountry("CN")
+ .setAdminArea("Beijing Shi")
+ .setLocality("Xicheng Qu")
+ .setPostalCode("12345")
+ .build();
+ verifier.verify(addr, problems);
+
+ // ensure problem is unrecognized format and problem is in POSTAL_CODE
+ assertEquals(AddressProblemType.UNRECOGNIZED_FORMAT,
+ problems.getProblem(AddressField.POSTAL_CODE));
+ }
+
+ /**
+ * If there is a postal code pattern for a certain country, and the input postal code is empty,
+ * it should not be reported as bad postal code format. Whether an empty postal code is ok
+ * should be determined by checks for required fields.
+ */
+ public void testEmptyPostalCodeReportedAsGoodFormat() {
+ // Chilean address has a postal code format pattern, but does not require
+ // postal code. The following address is valid.
+ AddressData addr = new AddressData.Builder().setCountry("CL")
+ .setAddressLine1("GUSTAVO LE PAIGE ST #159")
+ .setAdminArea("Atacama")
+ .setLocality("Alto del Carmen")
+ .setPostalCode("")
+ .build();
+ verifier.verify(addr, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+
+ problems.clear();
+
+ // Now checks for US addresses, which requires postal code. The following
+ // address's postal code is wrong because it misses required field, not
+ // because it mismatches expected postal code pattern.
+ addr = new AddressData.Builder().setCountry("US").setPostalCode("").build();
+ problems.clear();
+ verifier.verify(addr, problems);
+
+ assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
+ problems.getProblem(AddressField.POSTAL_CODE));
+ }
+
+ public void testChinaTaiwanOk() {
+ AddressData addr = new AddressData.Builder().setCountry("CN")
+ .setAdminArea("Taiwan")
+ .setLocality("Taichung City")
+ .setDependentLocality("Situn District")
+ .setAddress("12345 Yitiao Lu")
+ .setPostalCode("407")
+ .build();
+ verifier.verify(addr, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+ }
+
+ public void testChinaTaiwanUnknownDistrict() {
+ AddressData addr = new AddressData.Builder().setCountry("CN")
+ .setAdminArea("Taiwan")
+ .setLocality("Taichung City")
+ .setDependentLocality("Foo Bar")
+ .setPostalCode("400")
+ .build();
+ verifier.verify(addr, problems);
+
+ assertEquals(AddressProblemType.UNKNOWN_VALUE,
+ problems.getProblem(AddressField.DEPENDENT_LOCALITY));
+ }
+
+ public void testStreetVerification() {
+ // missing street address
+ AddressData addr = new AddressData.Builder().setCountry("US")
+ .setAdminArea("CA")
+ .setLocality("Mountain View")
+ .setPostalCode("94025")
+ .build();
+
+ assertNull(addr.getAddressLine1());
+ assertNull(addr.getAddressLine2());
+
+ verifier.verify(addr, problems);
+
+ assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
+ problems.getProblem(AddressField.STREET_ADDRESS));
+ }
+
+ // Tests The Bahamas' address
+ public void failingtestBahamas() {
+ final AddressData address =
+ new AddressData.Builder().setAddress("Abaco Beach Resort & Boat Habour")
+ .setLocality("Treasure Cay")
+ .setAdminArea("Abaco")
+ .setCountry("BS")
+ .build();
+ verifier.verify(address, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+ }
+
+ public void testJapan() {
+ // added AdminArea since address verification can't infer it from Kyoto City
+ // commented out dependent locality since address verification doesn't use it
+ // TODO: support inference of higher levels from lower ones
+ // TODO: add dependent locality support for japan addresses
+ final AddressData address =
+ new AddressData.Builder()
+ .setRecipient("\u5BAE\u672C \u8302") // SHIGERU_MIYAMOTO
+ .setAddress("\u4E0A\u9CE5\u7FBD\u927E\u7ACB\u753A11\u756A\u5730")
+ .setAdminArea("\u4eac\u90fd\u5e9c") // Kyoto prefecture, added
+ .setLocality("\u4EAC\u90FD\u5E02") // Kyoto city
+ // .setDependentLocality("\u5357\u533A")
+ .setCountry("JP")
+ .setPostalCode("601-8501")
+ .build();
+ verifier.verify(address, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+ }
+
+ public void testJapanLatin() {
+ // added AdminArea since address verification can't infer it from Kyoto City
+ // commented out dependent locality since address verification doesn't use it
+ final AddressData address =
+ new AddressData.Builder()
+ .setRecipient("Shigeru Miyamoto") // SHIGERU_MIYAMOTO_ENGLISH
+ .setAddress("11-1 Kamitoba-hokotate-cho")
+ .setAdminArea("KYOTO") // Kyoto prefecture, added
+ .setLocality("Kyoto") // Kyoto city
+ // .setDependentLocality("Minami-ku")
+ .setLanguageCode("ja_Latn")
+ .setCountry("JP")
+ .setPostalCode("601-8501")
+ .build();
+ verifier.verify(address, problems);
+ assertTrue(problems.toString(), problems.isEmpty());
+ }
}
diff --git a/java/test/com/android/i18n/addressinput/UtilTest.java b/java/test/com/android/i18n/addressinput/UtilTest.java
index d552062..73a7956 100644
--- a/java/test/com/android/i18n/addressinput/UtilTest.java
+++ b/java/test/com/android/i18n/addressinput/UtilTest.java
@@ -26,129 +26,129 @@ import java.util.Map;
*/
public class UtilTest extends TestCase {
- public void testIsExplicitLatinScript() throws Exception {
- // Should recognise Latin script in a variety of forms.
- assertTrue(Util.isExplicitLatinScript("zh-Latn"));
- assertTrue(Util.isExplicitLatinScript("ja_LATN"));
- assertTrue(Util.isExplicitLatinScript("und_LATN"));
- assertTrue(Util.isExplicitLatinScript("ja_LATN-JP"));
- assertTrue(Util.isExplicitLatinScript("ko-latn_JP"));
- }
+ public void testIsExplicitLatinScript() throws Exception {
+ // Should recognise Latin script in a variety of forms.
+ assertTrue(Util.isExplicitLatinScript("zh-Latn"));
+ assertTrue(Util.isExplicitLatinScript("ja_LATN"));
+ assertTrue(Util.isExplicitLatinScript("und_LATN"));
+ assertTrue(Util.isExplicitLatinScript("ja_LATN-JP"));
+ assertTrue(Util.isExplicitLatinScript("ko-latn_JP"));
+ }
- public void testIsExplicitLatinScriptNonLatin() throws Exception {
- assertFalse(Util.isExplicitLatinScript("ko"));
- assertFalse(Util.isExplicitLatinScript("KO"));
- assertFalse(Util.isExplicitLatinScript("ja"));
- assertFalse(Util.isExplicitLatinScript("ja-JP"));
- assertFalse(Util.isExplicitLatinScript("zh-Hans"));
- assertFalse(Util.isExplicitLatinScript("zh-Hans-CN"));
- assertFalse(Util.isExplicitLatinScript("zh-Hant"));
- assertFalse(Util.isExplicitLatinScript("zh-TW"));
- assertFalse(Util.isExplicitLatinScript("zh_TW"));
- assertFalse(Util.isExplicitLatinScript("ko"));
- assertFalse(Util.isExplicitLatinScript("ko_KR"));
- assertFalse(Util.isExplicitLatinScript("en"));
- assertFalse(Util.isExplicitLatinScript("EN"));
- assertFalse(Util.isExplicitLatinScript("ru"));
- }
+ public void testIsExplicitLatinScriptNonLatin() throws Exception {
+ assertFalse(Util.isExplicitLatinScript("ko"));
+ assertFalse(Util.isExplicitLatinScript("KO"));
+ assertFalse(Util.isExplicitLatinScript("ja"));
+ assertFalse(Util.isExplicitLatinScript("ja-JP"));
+ assertFalse(Util.isExplicitLatinScript("zh-Hans"));
+ assertFalse(Util.isExplicitLatinScript("zh-Hans-CN"));
+ assertFalse(Util.isExplicitLatinScript("zh-Hant"));
+ assertFalse(Util.isExplicitLatinScript("zh-TW"));
+ assertFalse(Util.isExplicitLatinScript("zh_TW"));
+ assertFalse(Util.isExplicitLatinScript("ko"));
+ assertFalse(Util.isExplicitLatinScript("ko_KR"));
+ assertFalse(Util.isExplicitLatinScript("en"));
+ assertFalse(Util.isExplicitLatinScript("EN"));
+ assertFalse(Util.isExplicitLatinScript("ru"));
+ }
- public void testGetLanguageSubtag() throws Exception {
- assertEquals("zh", Util.getLanguageSubtag("zh-Latn"));
- assertEquals("ja", Util.getLanguageSubtag("ja_LATN"));
- assertEquals("und", Util.getLanguageSubtag("und_LATN"));
- assertEquals("ja", Util.getLanguageSubtag("ja_LATN-JP"));
- assertEquals("ko", Util.getLanguageSubtag("ko"));
- assertEquals("ko", Util.getLanguageSubtag("KO"));
- assertEquals("ko", Util.getLanguageSubtag("ko-KR"));
- assertEquals("ko", Util.getLanguageSubtag("ko_kr"));
- assertEquals("und", Util.getLanguageSubtag("Not a language"));
- }
+ public void testGetLanguageSubtag() throws Exception {
+ assertEquals("zh", Util.getLanguageSubtag("zh-Latn"));
+ assertEquals("ja", Util.getLanguageSubtag("ja_LATN"));
+ assertEquals("und", Util.getLanguageSubtag("und_LATN"));
+ assertEquals("ja", Util.getLanguageSubtag("ja_LATN-JP"));
+ assertEquals("ko", Util.getLanguageSubtag("ko"));
+ assertEquals("ko", Util.getLanguageSubtag("KO"));
+ assertEquals("ko", Util.getLanguageSubtag("ko-KR"));
+ assertEquals("ko", Util.getLanguageSubtag("ko_kr"));
+ assertEquals("und", Util.getLanguageSubtag("Not a language"));
+ }
- public void testTrimToNull() throws Exception {
- assertEquals("Trimmed String", Util.trimToNull(" Trimmed String "));
- assertEquals("Trimmed String", Util.trimToNull(" Trimmed String"));
- assertEquals("Trimmed String", Util.trimToNull("Trimmed String"));
- assertEquals(null, Util.trimToNull(" "));
- assertEquals(null, Util.trimToNull(null));
- }
+ public void testTrimToNull() throws Exception {
+ assertEquals("Trimmed String", Util.trimToNull(" Trimmed String "));
+ assertEquals("Trimmed String", Util.trimToNull(" Trimmed String"));
+ assertEquals("Trimmed String", Util.trimToNull("Trimmed String"));
+ assertEquals(null, Util.trimToNull(" "));
+ assertEquals(null, Util.trimToNull(null));
+ }
- public void testJoinAndSkipNulls() throws Exception {
- String first = "String 1";
- String second = "String 2";
- String expectedString = "String 1-String 2";
- String nullString = null;
- assertEquals(expectedString, Util.joinAndSkipNulls("-", first, second));
- assertEquals(expectedString, Util.joinAndSkipNulls("-", first, second, nullString));
- assertEquals(expectedString, Util.joinAndSkipNulls("-", first, nullString, second));
- assertEquals(expectedString, Util.joinAndSkipNulls("-", first, nullString, " ", second));
- assertEquals(first, Util.joinAndSkipNulls("-", first, nullString));
- assertEquals(first, Util.joinAndSkipNulls("-", nullString, first));
+ public void testJoinAndSkipNulls() throws Exception {
+ String first = "String 1";
+ String second = "String 2";
+ String expectedString = "String 1-String 2";
+ String nullString = null;
+ assertEquals(expectedString, Util.joinAndSkipNulls("-", first, second));
+ assertEquals(expectedString, Util.joinAndSkipNulls("-", first, second, nullString));
+ assertEquals(expectedString, Util.joinAndSkipNulls("-", first, nullString, second));
+ assertEquals(expectedString, Util.joinAndSkipNulls("-", first, nullString, " ", second));
+ assertEquals(first, Util.joinAndSkipNulls("-", first, nullString));
+ assertEquals(first, Util.joinAndSkipNulls("-", nullString, first));
- assertEquals(null, Util.joinAndSkipNulls("-", nullString));
- assertEquals(null, Util.joinAndSkipNulls("-", nullString, nullString));
- assertEquals(null, Util.joinAndSkipNulls("-", nullString, "", nullString));
- }
+ assertEquals(null, Util.joinAndSkipNulls("-", nullString));
+ assertEquals(null, Util.joinAndSkipNulls("-", nullString, nullString));
+ assertEquals(null, Util.joinAndSkipNulls("-", nullString, "", nullString));
+ }
- public void testGetWidgetCompatibleLanguageCodeCjkCountry() throws Exception {
- Locale canadianFrench = new Locale("fr", "CA");
- // Latin language, CJK country. Need explicit Latin tag, and country should be retained.
- assertEquals("fr_latn_CA", Util.getWidgetCompatibleLanguageCode(canadianFrench, "CN"));
- Locale canadianFrenchUpper = new Locale("FR", "CA");
- // Test that the locale returns the same language code, regardless of the case of the
- // initial input.
- assertEquals("fr_latn_CA", Util.getWidgetCompatibleLanguageCode(canadianFrenchUpper, "CN"));
- // No country in the Locale language.
- assertEquals("fr_latn", Util.getWidgetCompatibleLanguageCode(Locale.FRENCH, "CN"));
- // CJK language - but wrong country.
- assertEquals("ko_latn",
- Util.getWidgetCompatibleLanguageCode(Locale.KOREAN, "CN"));
- Locale chineseChina = new Locale("zh", "CN");
- assertEquals("zh_CN", Util.getWidgetCompatibleLanguageCode(chineseChina, "CN"));
- }
+ public void testGetWidgetCompatibleLanguageCodeCjkCountry() throws Exception {
+ Locale canadianFrench = new Locale("fr", "CA");
+ // Latin language, CJK country. Need explicit Latin tag, and country should be retained.
+ assertEquals("fr_latn_CA", Util.getWidgetCompatibleLanguageCode(canadianFrench, "CN"));
+ Locale canadianFrenchUpper = new Locale("FR", "CA");
+ // Test that the locale returns the same language code, regardless of the case of the
+ // initial input.
+ assertEquals("fr_latn_CA", Util.getWidgetCompatibleLanguageCode(canadianFrenchUpper, "CN"));
+ // No country in the Locale language.
+ assertEquals("fr_latn", Util.getWidgetCompatibleLanguageCode(Locale.FRENCH, "CN"));
+ // CJK language - but wrong country.
+ assertEquals("ko_latn",
+ Util.getWidgetCompatibleLanguageCode(Locale.KOREAN, "CN"));
+ Locale chineseChina = new Locale("zh", "CN");
+ assertEquals("zh_CN", Util.getWidgetCompatibleLanguageCode(chineseChina, "CN"));
+ }
- public void testGetWidgetCompatibleLanguageCodeThailand() throws Exception {
- Locale thai = new Locale("th", "TH");
- assertEquals("th_TH", Util.getWidgetCompatibleLanguageCode(thai, "TH"));
- // However, we assume Thai users prefer Latin names for China.
- assertEquals("th_latn_TH", Util.getWidgetCompatibleLanguageCode(thai, "CN"));
- }
+ public void testGetWidgetCompatibleLanguageCodeThailand() throws Exception {
+ Locale thai = new Locale("th", "TH");
+ assertEquals("th_TH", Util.getWidgetCompatibleLanguageCode(thai, "TH"));
+ // However, we assume Thai users prefer Latin names for China.
+ assertEquals("th_latn_TH", Util.getWidgetCompatibleLanguageCode(thai, "CN"));
+ }
- public void testGetWidgetCompatibleLanguageCodeNonCjkCountry() throws Exception {
- // Nothing should be changed for non-CJK countries, since their form layout is the same
- // regardless of language.
- Locale canadianFrench = new Locale("fr", "CA");
- assertEquals("fr_CA", Util.getWidgetCompatibleLanguageCode(canadianFrench, "US"));
- // No country in the Locale language.
- assertEquals(Locale.FRENCH.toString(),
- Util.getWidgetCompatibleLanguageCode(Locale.FRENCH, "US"));
- // CJK language - should be unaltered too.
- assertEquals(Locale.KOREAN.toString(),
- Util.getWidgetCompatibleLanguageCode(Locale.KOREAN, "US"));
- }
+ public void testGetWidgetCompatibleLanguageCodeNonCjkCountry() throws Exception {
+ // Nothing should be changed for non-CJK countries, since their form layout is the same
+ // regardless of language.
+ Locale canadianFrench = new Locale("fr", "CA");
+ assertEquals("fr_CA", Util.getWidgetCompatibleLanguageCode(canadianFrench, "US"));
+ // No country in the Locale language.
+ assertEquals(Locale.FRENCH.toString(),
+ Util.getWidgetCompatibleLanguageCode(Locale.FRENCH, "US"));
+ // CJK language - should be unaltered too.
+ assertEquals(Locale.KOREAN.toString(),
+ Util.getWidgetCompatibleLanguageCode(Locale.KOREAN, "US"));
+ }
- public void testBuildNameToKeyMap() throws Exception {
- String names[] = {"", "", "", "", "NEW PROVIDENCE" };
- // We have one more key than name here.
- String keys[] = {"AB", "AC", "AD", "AE", "NP", "XX"};
- Map<String, String> result = Util.buildNameToKeyMap(keys, names, null);
- // We should have the six keys, and the one name, in the end result. No empty-string names
- // should be present.
- assertEquals(keys.length + 1, result.size());
- // The empty string should not be present.
- assertFalse(result.containsKey(""));
+ public void testBuildNameToKeyMap() throws Exception {
+ String names[] = {"", "", "", "", "NEW PROVIDENCE" };
+ // We have one more key than name here.
+ String keys[] = {"AB", "AC", "AD", "AE", "NP", "XX"};
+ Map<String, String> result = Util.buildNameToKeyMap(keys, names, null);
+ // We should have the six keys, and the one name, in the end result. No empty-string names
+ // should be present.
+ assertEquals(keys.length + 1, result.size());
+ // The empty string should not be present.
+ assertFalse(result.containsKey(""));
- // Try with Latin names instead.
- Map<String, String> resultWithLatin = Util.buildNameToKeyMap(keys, null, names);
- // We should have the six keys and the one Latin-script name in the end result.
- assertEquals(keys.length + 1, resultWithLatin.size());
- String lnames[] = { "Other name" };
- resultWithLatin = Util.buildNameToKeyMap(keys, names, lnames);
- // We should have the keys, plus the names in lnames and names.
- assertEquals(keys.length + 2, resultWithLatin.size());
- assertTrue(resultWithLatin.containsKey("other name"));
- assertTrue(resultWithLatin.containsKey("new providence"));
- assertTrue(resultWithLatin.containsKey("xx"));
- // The empty string should not be present.
- assertFalse(resultWithLatin.containsKey(""));
- }
+ // Try with Latin names instead.
+ Map<String, String> resultWithLatin = Util.buildNameToKeyMap(keys, null, names);
+ // We should have the six keys and the one Latin-script name in the end result.
+ assertEquals(keys.length + 1, resultWithLatin.size());
+ String lnames[] = { "Other name" };
+ resultWithLatin = Util.buildNameToKeyMap(keys, names, lnames);
+ // We should have the keys, plus the names in lnames and names.
+ assertEquals(keys.length + 2, resultWithLatin.size());
+ assertTrue(resultWithLatin.containsKey("other name"));
+ assertTrue(resultWithLatin.containsKey("new providence"));
+ assertTrue(resultWithLatin.containsKey("xx"));
+ // The empty string should not be present.
+ assertFalse(resultWithLatin.containsKey(""));
+ }
}