Merge from Chromium at DEPS revision db3f05efe0f9

This commit was generated by merge_to_master.py.

Change-Id: I07ba5e568405463b1b643a6e88d60d6d35bba2b7
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 @@
 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 @@
     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 @@
     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 @@
 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 @@
       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 @@
     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 @@
       "\"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 @@
       "\"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 @@
       "}"));
   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 @@
       "}"));
   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 @@
       "\"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 @@
       "\"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 @@
       "}"));
   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 @@
       "}"));
   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 @@
       "\"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 @@
       "\"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 @@
       "\"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 @@
   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 @@
       "\"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 @@
       "\"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 @@
       "\"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 @@
       "}"));
   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 @@
       "\"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 @@
       "\"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 @@
       "\"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 @@
   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 @@
       "\"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 @@
       "\"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 @@
       "\"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 @@
       "\"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 @@
       "\"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 @@
       "}"));
   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 @@
       "\"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 @@
   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 @@
       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 @@
   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 @@
         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 @@
     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 @@
   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 @@
     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 @@
 
 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 @@
 
 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 @@
             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 @@
             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 @@
         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 @@
   }
 }
 
+// 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
index 0000000..77abf65
--- /dev/null
+++ b/externals/grit
@@ -0,0 +1 @@
+Subproject commit 77abf65c1d72af6fb7f9ef6f50cdf29fcf42d0a1
diff --git a/externals/rapidjson b/externals/rapidjson
new file mode 160000
index 0000000..d0f98d2
--- /dev/null
+++ b/externals/rapidjson
@@ -0,0 +1 @@
+Subproject commit d0f98d2da1e2e6345831dc1ab2c30950417e6490
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 United Arab Emirates (e.g., Abu Dhabi) [CHAR LIMIT=30] -->
+    <!-- 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] -->
     <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>
+    <!-- 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 a required field is empty [CHAR LIMIT=30] -->
-    <string name="i18n_missing_required_field">Required</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 value entered by the user in a given field is invalid
+    <!-- Label for a neighborhood, shown as part of an address input form. [CHAR LIMIT=30] -->
+    <string name="i18n_neighborhood">Neighborhood</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="invalid_entry">Invalid entry</string>
+    <string name="i18n_organization_label">Organization</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>
+    <!-- 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 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>
+    <!-- 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 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>
+    <!-- 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 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>
+    <!-- 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 for Hong Kong (e.g., Kowloon)
-         is entered incorrectly by the user [CHAR LIMIT=30] -->
-    <string name="invalid_area">Invalid area</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 (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>
-
-    <!-- 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>
-
-    <!-- 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>
-
-    <!-- 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>
-
-    <!-- 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>
-
-    <!-- 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>
-
-    <!-- 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>
-
-    <!-- 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>
-
-    <!-- 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 @@
  * 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;
+  // 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 mAddressLine1;
+  // street street, line 1
+  private final String addressLine1;
 
-    // street street, line 2
-    private final String mAddressLine2;
+  // 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 mAdministrativeArea;
+  // 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 mLocality;
+  // 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 mDependentLocality;
+  // 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 mPostalCode;
+  // 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 mSortingCode;
+  // 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 mOrganization;
+  // 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 mRecipient;
+  // 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 mLanguageCode;
+  // 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) {
-        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;
+  /**
+   * 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);
+    }
+  }
+
+  /**
+   * 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.
+     * 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) {
+      values = 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.
      *
-     * <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".
+     * @param languageCode the language to use, or {@code null} for no specified language.
      */
-    public String getPostalCountry() {
-        return mPostalCountry;
-    }
-
-    public String getAddressLine1() {
-        return mAddressLine1;
-    }
-
-    public String getAddressLine2() {
-        return mAddressLine2;
+    public Builder setLanguageCode(String languageCode) {
+      this.language = languageCode;
+      return this;
     }
 
     /**
-     * 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;
-    }
-
-    /**
-     * 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 mLocality;
-    }
-
-    /**
-     * 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;
+    }
+
+    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);
     }
 
     /**
-     * Returns the recipient. Examples: "Jesse Wilson" or "Jesse Wilson c/o Apurva Mathad".
+     * 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 getRecipient() {
-        return mRecipient;
+    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);
     }
 
     /**
-     * Returns the country-specific postal code. Examples: "94043", "94043-1351", "SW1W",
-     * "SW1W 9TQ".
+     * 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 String getPostalCode() {
-        return mPostalCode;
+    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);
     }
-
-    /**
-     * 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 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);
-        }
-    }
-
-    /**
-     * 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 mLanguageCode;
-    }
-
-    /**
-     * Builder for AddressData
-     */
-    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);
-        }
-    }
+  }
 }
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 @@
      */
     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 @@
  * 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>();
+
+  static {
+    for (AddressField value : values()) {
+      FIELD_MAPPING.put(value.getChar(), value);
     }
+  }
 
-    private static final Map<Character, AddressField> FIELD_MAPPING
-            = new HashMap<Character, AddressField>();
+  private final char field;
 
-    static {
-        for (AddressField value : values()) {
-            FIELD_MAPPING.put(value.getChar(), value);
-        }
-    }
+  private AddressField(char field) {
+    this.field = field;
+  }
 
-    private final char mField;
+  /**
+   * 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);
+  }
 
-    private AddressField(char field) {
-        mField = field;
-    }
+  /**
+   * Gets the field's identification character, as used in the metadata.
+   *
+   * @return identification char.
+   */
+  char getChar() {
+    return 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;
-    }
-
-    /** 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 @@
  */
 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 @@
  */
 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 @@
  * candidate) or a spinner.
  */
 class AddressUiComponent {
-    // The label for the UI component
-    private String mFieldName;
+  // The label for the UI component
+  private String fieldName;
 
-    // The type of the UI component
-    private UiComponent mUiType;
+  // The type of the UI component
+  private UiComponent uiType;
 
-    // The list of elements in the UI component
-    private List<RegionData> mCandidatesList = new ArrayList<RegionData>();
+  // The list of elements in the UI component
+  private List<RegionData> candidatesList = new ArrayList<RegionData>();
 
-    // The id of this UI component
-    private AddressField mId;
+  // 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 mParentId;
+  // 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 mView;
+  // 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,
+  /**
+   * 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.
+      }
     }
+  }
 
-    AddressUiComponent(AddressField id) {
-        mId = id;
-        // By default, an AddressUiComponent doesn't depend on anything else.
-        mParentId = null;
-        mUiType = UiComponent.EDIT;
+  /**
+   * Gets the value entered in the UI component.
+   */
+  String getValue() {
+    if (view == null) {
+      return (candidatesList.size() == 0) ? "" : candidatesList.get(0).getDisplayName();
     }
-
-    /**
-     * 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.
-            }
+    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 "";
     }
+  }
 
-    /**
-     * 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 "";
-        }
-    }
+  String getFieldName() {
+    return fieldName;
+  }
 
-    String getFieldName() {
-        return mFieldName;
-    }
+  void setFieldName(String fieldName) {
+    this.fieldName = fieldName;
+  }
 
-    void setFieldName(String fieldName) {
-        mFieldName = fieldName;
-    }
+  UiComponent getUiType() {
+    return uiType;
+  }
 
-    UiComponent getUiType() {
-        return mUiType;
-    }
+  void setUiType(UiComponent uiType) {
+    this.uiType = uiType;
+  }
 
-    void setUiType(UiComponent uiType) {
-        mUiType = uiType;
-    }
+  List<RegionData> getCandidatesList() {
+    return candidatesList;
+  }
 
-    List<RegionData> getCandidatesList() {
-        return mCandidatesList;
-    }
+  void setCandidatesList(List<RegionData> candidatesList) {
+    this.candidatesList = candidatesList;
+  }
 
-    void setCandidatesList(List<RegionData> candidatesList) {
-        mCandidatesList = candidatesList;
-    }
+  AddressField getId() {
+    return id;
+  }
 
-    AddressField getId() {
-        return mId;
-    }
+  void setId(AddressField id) {
+    this.id = id;
+  }
 
-    void setId(AddressField id) {
-        mId = id;
-    }
+  AddressField getParentId() {
+    return parentId;
+  }
 
-    AddressField getParentId() {
-        return mParentId;
-    }
+  void setParentId(AddressField parentId) {
+    this.parentId = parentId;
+  }
 
-    void setParentId(AddressField parentId) {
-        mParentId = parentId;
-    }
+  void setView(View view) {
+    this.view = view;
+  }
 
-    void setView(View view) {
-        mView = 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 @@
  */
 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 = propertiesMap.get(key);
+    if (json != null && isValidKey(key)) {
+      return createNodeData(json);
     }
+    return null;
+  }
 
-    @Override
-    public AddressVerificationNodeData get(String key) {
-        String json = mPropertiesMap.get(key);
-        if (json != null && isValidKey(key)) {
-            return createNodeData(json);
-        }
-        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);
+  }
 
-    /**
-     * 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);
+  /**
+   * 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;
             }
-        }
-        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);
-                }
-
-                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 + "'");
-            }
+            linechars[w++] = c;
+          }
+          value = new String(linechars, 0, w);
         }
 
-        return new AddressVerificationNodeData(map);
+        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 + "'");
+      }
     }
 
-    @Override
-    public AddressVerificationNodeData getDefaultData(String key) {
-        // gets country key
-        if (key.split("/").length > 1) {
-            String[] parts = key.split("/");
-            key = parts[0] + "/" + parts[1];
-        }
+    return new AddressVerificationNodeData(map);
+  }
 
-        AddressVerificationNodeData data = get(key);
-        if (data == null) {
-            throw new RuntimeException("failed to get default data with key " + key);
-        }
-        return data;
+  @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;
+  }
 }
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 @@
  */
 public class AddressVerificationNodeData {
 
-    private final Map<AddressDataKey, String> mMap;
+  private final Map<AddressDataKey, String> map;
 
-    public AddressVerificationNodeData(Map<AddressDataKey, String> map) {
-        Util.checkNotNull("Cannot construct StandardNodeData with null map");
-        mMap = 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 mMap.keySet().iterator();
-    }
+  /**
+   * Iterates through the map.
+   */
+  public Iterator<AddressDataKey> iterator() {
+    return map.keySet().iterator();
+  }
 
-    public boolean containsKey(AddressDataKey key) {
-        return mMap.containsKey(key);
-    }
+  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 mMap.get(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 @@
  * 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);
+
+    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);
+
+    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);
+  }
+
+  // Need handler for callbacks to the UI thread
+  final Handler handler = new Handler();
+
+  final Runnable updateMultipleFields = new Runnable() {
+    @Override
+    public void run() {
+      updateFields();
+    }
+  };
+
+  private class UpdateRunnable implements Runnable {
+    private AddressField myId;
+
+    public UpdateRunnable(AddressField id) {
+      myId = id;
     }
 
-    private ZipLabel mZipLabel;
+    @Override
+    public void run() {
+      updateInputWidget(myId);
+    }
+  }
 
-    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);
+  private static class AddressSpinnerInfo {
+    private Spinner view;
 
-        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);
+    private AddressField id;
 
-        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);
+    private AddressField parentId;
+
+    private ArrayAdapter<String> adapter;
+
+    private List<RegionData> currentRegions;
+
+    @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();
     }
 
-    // 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;
-
-        public UpdateRunnable(AddressField id) {
-            myId = id;
-        }
-
-        @Override
-        public void run() {
-            updateInputWidget(myId);
-        }
-    }
-
-    private static class AddressSpinnerInfo {
-        private Spinner mView;
-
-        private AddressField mId;
-
-        private AddressField mParentId;
-
-        private ArrayAdapter<String> mAdapter;
-
-        private List<RegionData> mCurrentRegions;
-
-        @SuppressWarnings("unchecked")
-        public AddressSpinnerInfo(Spinner view, AddressField id, AddressField parentId) {
-            mView = view;
-            mId = id;
-            mParentId = parentId;
-            mAdapter = (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);
-            }
-        }
-
-        // 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 for the region value.
-        public String getRegionDataKeyForValue(String value) {
-            for (RegionData data : mCurrentRegions) {
-                if (data.getDisplayName().endsWith(value)) {
-                    return data.getKey();
-                }
-            }
-            return "";
-        }
-    }
-
-    private final ArrayList<AddressSpinnerInfo> mSpinners = new ArrayList<AddressSpinnerInfo>();
-
-    private AddressWidgetUiComponentProvider mComponentProvider;
-
-    /** 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.
-        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);
-    }
-
-    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 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 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);
-        }
-    }
-
-    private void layoutAddressFields() {
-        for (AddressField field : mFormatInterpreter.getAddressFieldOrder(mScript,
-                mCurrentRegion)) {
-            if (!mFormOptions.isHidden(field)) {
-              createView(mRootView, mInputWidgets.get(field), "", mFormOptions.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);
-            }
-        });
-    }
-
-    public void updateWidgetOnCountryChange(String regionCode) {
-        if (mCurrentRegion.equalsIgnoreCase(regionCode)) {
-            return;
-        }
-        mCurrentRegion = regionCode;
-        mFormController.setCurrentCountry(mCurrentRegion);
-        renderForm();
-    }
-
-    private void updateInputWidget(AddressField myId) {
-        for (AddressSpinnerInfo child : mSpinners) {
-            if (child.mParentId == myId) {
-                List<RegionData> candidates = getRegionData(child.mParentId);
-                child.setSpinnerList(candidates, "");
-            }
-        }
-    }
-
-    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();
-        }
-
-        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);
-            }
-        }
-    }
-
-    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));
-        }
-    }
-
-    /**
-     * 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;
-        }
-    }
-
-    /**
-     * 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);
-                }
-            }
-        }
-    }
-
-    public View getViewForField(AddressField field) {
-      AddressUiComponent component = mInputWidgets.get(field);
-      if (component == null) {
-        return null;
+    public void setSpinnerList(List<RegionData> list, String defaultKey) {
+      currentRegions = list;
+      adapter.clear();
+      for (RegionData item : list) {
+        adapter.add(item.getDisplayName());
       }
-      return component.getView();
+      adapter.sort(Collator.getInstance(Locale.getDefault()));
+      if (defaultKey.length() == 0) {
+        view.setSelection(0);
+      } else {
+        int position = adapter.getPosition(defaultKey);
+        view.setSelection(position);
+      }
     }
 
-    @Override
-    public void onNothingSelected(AdapterView<?> arg0) {
+    // 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);
     }
 
-    @Override
-    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-        updateChildNodes(parent, position);
+    // 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> spinners = new ArrayList<AddressSpinnerInfo>();
+
+  private AddressWidgetUiComponentProvider componentProvider;
+
+  /** 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.
+        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 = 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 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 void updateFields() {
+    removePreviousViews();
+    buildFieldWidgets();
+    initializeDropDowns();
+    layoutAddressFields();
+  }
+
+  private void removePreviousViews() {
+    if (rootView == null) {
+      return;
+    }
+    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 : 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.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;
+    }
+
+    String regionCode = spinnerInfo.getRegionCode(position);
+    if (myId == AddressField.COUNTRY) {
+      updateWidgetOnCountryChange(regionCode);
+      return;
+    }
+
+    formController.requestDataForAddress(getAddressData(), new DataLoadListener() {
+      @Override
+      public void dataLoadingBegin(){
+      }
+
+      @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, "");
+      }
+    }
+  }
+
+  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);
+      }
+    }
+  }
+
+  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);
+      }
+    }
+    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 = inputWidgets.get(field);
+    if (component == null) {
+      return null;
+    }
+    return component.getView();
+  }
+
+  @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 @@
  * 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 @@
  */
 public final class CacheData {
 
-    /**
-     * Used to identify the source of a log message.
-     */
-    private static final String TAG = "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 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;
+    }
+  }
+
+  /**
+   * 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 {
 
     /**
-     * Time out value for the server to respond in millisecond.
+     * 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.
      */
-    private static final int TIMEOUT = 5000;
+    void onAdd(String key);
+  }
+
+  /**
+   * Class to handle JSON response.
+   */
+  private class JsonHandler {
 
     /**
-     * URL to get address data. You can also reset it by calling {@link #setUrl(String)}.
+     * Key for the requested data.
      */
-    private String mServiceUrl;
+    private final String key;
 
     /**
-     * Storage for all dynamically retrieved data.
+     * Pre-existing data for the requested key. Null is allowed.
      */
-    private final JsoMap mCache;
+    private final JSONObject existingJso;
+
+    private final DataLoadListener listener;
 
     /**
-     * CacheManager that handles caching that is needed by the client of the Address Widget.
+     * Constructs a JsonHandler instance.
+     *
+     * @param key    The key for requested data.
+     * @param oldJso Pre-existing data for this key or null.
      */
-    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());
+    private JsonHandler(String key, JSONObject oldJso, DataLoadListener listener) {
+      checkNotNull(key);
+      this.key = key;
+      this.existingJso = oldJso;
+      this.listener = listener;
     }
 
     /**
-     * Creates an instance of CacheData with an empty cache, and uses additional caching (external
-     * to the AddressWidget) specified by clientCacheManager.
+     * 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.
      */
-    public CacheData(ClientCacheManager clientCacheManager) {
-        mClientCacheManager = clientCacheManager;
-        setUrl(mClientCacheManager.getAddressServerUrl());
-        mCache = JsoMap.createEmptyJsoMap();
+    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);
+    }
+  }
+
+  /**
+   * 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();
+    }
+  }
+
+  /**
+   * 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();
     }
 
-    /**
-     * 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) {
-        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;
+    // Key is valid and cached.
+    if (cache.containsKey(key.toString())) {
+      triggerDataLoadingEndIfNotNull(listener);
+      return;
+    }
+
+    // Key is invalid and cached.
+    if (badKeys.contains(key.toString())) {
+      triggerDataLoadingEndIfNotNull(listener);
+      return;
+    }
+
+    // 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);
         }
+      });
+      return;
     }
 
-    /**
-     * 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);
+    // 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);
+      }
     }
 
-    /**
-     * Class to handle JSON response.
-     */
-    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);
-        }
-    }
-
-    /**
-     * 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.");
-        mServiceUrl = url;
-    }
-
-    /**
-     * Gets address data server URL.
-     */
-    public String getUrl() {
-        return mServiceUrl;
-    }
-
-    /**
-     * 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 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();
-        }
-    }
-
-    /**
-     * 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();
-        }
-
-        // Key is valid and cached.
-        if (mCache.containsKey(key.toString())) {
+    // 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);
-            return;
-        }
+          }
 
-        // Key is invalid and cached.
-        if (mBadKeys.contains(key.toString())) {
-            triggerDataLoadingEndIfNotNull(listener);
-            return;
-        }
+          @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);
+          }
+        });
+  }
 
-        // 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);
-                    }
-                });
+  /**
+   * 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");
+      }
     }
+  }
 
-    /**
-     * 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");
-            }
-        }
-    }
+  /**
+   * 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 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);
-    }
+  /**
+   * 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);
+  }
 
-    /**
-     * 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);
+  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 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();
-        }
+  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);
+  }
 
-    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);
-        }
-        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.
-     * 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);
-    }
-
-    /**
-     * 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;
-    }
+  /**
+   * 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 @@
  *  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 @@
  */
 public class ClientData implements DataSource {
 
-    private static final String TAG = "ClientData";
+  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"
+  /**
+   * 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);
+    }
+    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);
+    }
+
+    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);
+  }
+
+  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("/");
+
+    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;
+  }
+
+
+  /**
+   * 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.
+      }
+    }
+
+    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);
+
+    // 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 final Map<String, JsoMap> mBootstrapMap = new HashMap<String, JsoMap>();
-
-    private CacheData mCacheData;
-
-    public ClientData(CacheData cacheData) {
-        this.mCacheData = cacheData;
-        buildRegionalData();
+    String str = "{\"id\":\"data\",\"" +
+        AddressDataKey.COUNTRIES.toString().toLowerCase() +
+        "\": \"" + countries.toString() + "\"}";
+    JsoMap jsoData = null;
+    try {
+      jsoData = JsoMap.buildJsoMap(str);
+    } catch (JSONException e) {
+      // Ignore.
     }
+    bootstrapMap.put("data", jsoData);
+  }
 
-    @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;
-    }
-
-    @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 = 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;
-        }
-
-        String[] parts = hierarchyKey.split("/");
-
-        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;
-    }
-
-
-    /**
-     * 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.
-            }
-        }
-
-        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();
-            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;
+  /**
+   * 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 {
-            jsoData = JsoMap.buildJsoMap(str);
-        } catch (JSONException e) {
-            // Ignore.
+          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);
         }
-        mBootstrapMap.put("data", jsoData);
+      }
+    }
+  }
+
+  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 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);
-                }
-            }
+    @Override
+    public void dataLoadingBegin() {
+    }
+
+    @Override
+    public void dataLoadingEnd() {
+      final String subKeys = AddressDataKey.SUB_KEYS.name().toLowerCase();
+      final String subMores = AddressDataKey.SUB_MORES.name().toLowerCase();
+
+      JsoMap map = cacheData.getObj(key);
+
+      if (map.containsKey(subMores)) {
+        // This key could have sub keys.
+        String[] mores = map.get(subMores).split("~");
+        String[] keys = {};
+
+        if (map.containsKey(subKeys)) {
+          keys = map.get(subKeys).split("~");
         }
-    }
 
-    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);
-    }
+        if (mores.length != keys.length) {  // This should never happen.
+          throw new IndexOutOfBoundsException("mores.length != keys.length");
+        }
 
-    /**
-     * 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(),
+        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(key, loaders, listener));
+                new RecursiveLoader(subKey, loaders, listener));
+          }
+        }
+      }
+
+      synchronized (loaders) {
+        loaders.remove(this);
+        if (loaders.isEmpty()) {
+          listener.dataLoadingEnd();
+        }
+      }
     }
-
-    /**
-     * 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);
-            }
-        }
-
-        @Override
-        public void dataLoadingBegin() {
-        }
-
-        @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();
-                }
-            }
-        }
-    }
+  }
 }
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 @@
  * 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 @@
 // 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 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 @@
  * 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);
+  }
+
+  /**
+   * 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);
+
+    // 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");
+  }
+
+  /**
+   * 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;
     }
 
-    /**
-     * 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);
+    // 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]);
     }
+  }
 
-    /**
-     * 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);
+  private void populatePossibleAndRequired(String regionCode) {
+    List<AddressField> possible = FORMAT_INTERPRETER.getAddressFieldOrder(regionCode);
+    possiblyUsedFields = convertAddressFieldsToPossiblyUsedSet(possible);
+    required = FormatInterpreter.getRequiredFields(regionCode);
+  }
 
-        // 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));
-        }
+  FieldVerifier refineVerifier(String sublevel) {
+    if (Util.trimToNull(sublevel) == null) {
+      return new FieldVerifier(this, null);
     }
-
-    /**
-     * 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;
-        }
+    // 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);
     }
-
-    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);
+    // 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);
+      }
+    }
+    // No sub-verifiers were found.
+    return new FieldVerifier(this, null);
+  }
+
+  /**
+   * 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;
+
+    String trimmedValue = Util.trimToNull(value);
+    switch (problem) {
+      case USING_UNUSED_FIELD:
+        if (trimmedValue != null && !possiblyUsedFields.contains(field)) {
+          problemFound = true;
         }
-        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);
-                }
-            }
+        break;
+      case MISSING_REQUIRED_FIELD:
+        if (required.contains(field) && trimmedValue == null) {
+          problemFound = true;
         }
-        // No sub-verifiers were found.
-        return new FieldVerifier(this, null);
+        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 && format != null &&
+            !format.matcher(trimmedValue).matches()) {
+          problemFound = true;
+        }
+        break;
+      case MISMATCHING_VALUE:
+        if (trimmedValue != null && match != null &&
+            !match.matcher(trimmedValue).lookingAt()) {
+          problemFound = true;
+        }
+        break;
+      default:
+        throw new RuntimeException("Unknown problem: " + problem);
+    }
+    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 (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());
+      }
     }
 
-    /**
-     * Returns the ID of this verifier.
-     */
-    @Override
-    public String toString() {
-        return mId;
+    if (candidates.size() == 0 || trimmedValue == null) {
+      return true;
     }
 
-    /**
-     * 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;
+    return candidates.contains(value.toLowerCase());
+  }
 
-        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);
-        }
-        if (problemFound) {
-            problems.add(field, problem);
-        }
-        return !problemFound;
+  /**
+   * 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;
+  }
 
-    /**
-     * 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()));
-        }
-        // 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());
-            }
-        }
-        if (mKeys != null) {
-            for (String name : mKeys) {
-                candidates.add(name.toLowerCase());
-            }
-        }
-
-        if (candidates.size() == 0 || trimmedValue == null) {
-            return true;
-        }
-
-        return candidates.contains(value.toLowerCase());
-    }
-
-    /**
-     * 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;
-    }
-
-    /**
-     * 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);
-
-        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 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 @@
  * 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
-    };
+  // 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;
+  // 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");
-        mLanguageCode = languageCode;
-        this.mCurrentCountry = 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);
+    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;
+    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;
+    }
+    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);
+    }
+    if (subkeys.size() == 0) {
+      throw new RuntimeException("Need at least country level info");
     }
 
-    void setLanguageCode(String languageCode) {
-        mLanguageCode = languageCode;
+    if (listener != null) {
+      listener.dataLoadingBegin();
     }
+    requestDataRecursively(ROOT_KEY, subkeys, listener);
+  }
 
-    void setCurrentCountry(String currentCountry) {
-        mCurrentCountry = currentCountry;
-    }
+  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");
 
-    private ScriptType getScriptType() {
-        if (mLanguageCode != null && Util.isExplicitLatinScript(mLanguageCode)) {
-            return ScriptType.LATIN;
-        }
-        return ScriptType.LOCAL;
-    }
+    integratedData.requestData(key, new DataLoadListener() {
+      @Override
+      public void dataLoadingBegin() {
+      }
 
-    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;
+      @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();
+    }
+    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;
+    }
+    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;
+    }
+    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");
+    }
+    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;
     }
 
-    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");
+    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));
 
-        mIntegratedData.requestData(key, new DataLoadListener() {
-            @Override
-            public void dataLoadingBegin() {
-            }
+      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;
+  }
 
-            @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;
-                        }
-                    }
-                }
+  /**
+   * 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);
+  }
 
-                // 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 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");
     }
 
-    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;
+    String subStr[] = key.toString().split(SLASH_DELIM);
 
-        // Country level key
-        if (subKeys.length == 1 &&
-                languageCodeSubTag != null && !isDefaultLanguage(languageCodeSubTag)) {
-            key += DASH_DELIM + languageCodeSubTag.toString();
-        }
-        return new LookupKey.Builder(key).build();
+    // Root key does not need to be normalized.
+    if (subStr.length < 2) {
+      return key;
     }
 
-    /**
-     * 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);
+    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];
+      }
 
-        // Current language is not the default language for the country.
-        if (Util.trimToNull(defaultLanguage) != null &&
-            !Util.getLanguageSubtag(languageCode).equals(Util.getLanguageSubtag(languageCode))) {
-            return false;
+      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 true;
+        break;
+      }
+      sb.append(SLASH_DELIM).append(normalizedSubKey);
+      if (languageCode != null) {
+        sb.append(DASH_DELIM).append(languageCode);
+      }
     }
-
-    /**
-     * 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;
-    }
-
-    /**
-     * 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");
-        }
-
-        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 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]);
-                }
-                break;
-            }
-            sb.append(SLASH_DELIM).append(normalizedSubKey);
-            if (languageCode != null) {
-                sb.append(DASH_DELIM).append(languageCode);
-            }
-        }
-        return new LookupKey.Builder(sb.toString()).build();
-    }
+    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 @@
  */
 public class FormOptions {
 
-    private final String mBaseId;
+  private final String baseId;
 
-    private final EnumSet<AddressField> mHiddenFields;
+  private final EnumSet<AddressField> hiddenFields;
 
-    private final EnumSet<AddressField> mReadonlyFields;
+  private final EnumSet<AddressField> readonlyFields;
 
-    private final EnumSet<AddressField> mRequiredFields;
+  private final EnumSet<AddressField> requiredFields;
 
-    private final EnumMap<AddressField, String> mCustomLabels =
-            new EnumMap<AddressField, String>(AddressField.class);
+  private final EnumMap<AddressField, String> customLabels =
+      new EnumMap<AddressField, String>(AddressField.class);
 
-    private final Map<String, AddressField[]> mOverrideFieldOrder =
-            new HashMap<String, AddressField[]>();
+  private final Map<String, AddressField[]> overrideFieldOrder =
+      new HashMap<String, AddressField[]>();
 
-    private final EnumMap<AddressField, Integer> mMaxLengths =
-            new EnumMap<AddressField, Integer>(AddressField.class);
+  private final EnumMap<AddressField, Integer> maxLengths =
+      new EnumMap<AddressField, Integer>(AddressField.class);
 
-    private final String mServerUrl;
+  private final String serverUrl;
 
-    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 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);
+  }
+
+  /**
+   * Gets the customized max length for the {@code field}, or null if none.
+   */
+  Integer getCustomMaxLength(AddressField field) {
+    return maxLengths.get(field);
+  }
+
+  /**
+   * Class to build the form, specifying the attributes for each field.
+   */
+  public static class Builder {
+
+    private String baseId = "addressform";
+
+    private final EnumSet<AddressField> requiredFields =
+        EnumSet.noneOf(AddressField.class);
+
+    private final EnumSet<AddressField> hiddenFields =
+        EnumSet.noneOf(AddressField.class);
+
+    private final EnumSet<AddressField> readonlyFields =
+        EnumSet.noneOf(AddressField.class);
+
+    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);
+
+    /**
+     * Uses the default server URL from CacheData.
+     */
+    private String serverUrl = 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.");
+      }
+      this.baseId = baseId;
+      return this;
+    }
+
+    public Builder hide(AddressField field) {
+      if (field == null) {
+        throw new RuntimeException("AddressField field cannot be null.");
+      }
+      hiddenFields.add(field);
+      return this;
     }
 
     /**
-     * Gets base ID of the address form. Default is "addressform".
+     * Make a field read-only.
      */
-    String getBaseId() {
-        return mBaseId;
-    }
-
-    boolean isHidden(AddressField field) {
-        return mHiddenFields.contains(field);
-    }
-
-    boolean isReadonly(AddressField field) {
-        return mReadonlyFields.contains(field);
-    }
-
-    boolean isRequired(AddressField field) {
-        return mRequiredFields.contains(field);
-    }
-
-    EnumSet<AddressField> getRequiredFields() {
-        return mRequiredFields;
+    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 FormOptions build() {
-            return new FormOptions(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);
+    }
+  }
 }
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 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;
-            }
+    overrideFieldOrder(regionCode, fieldOrder);
 
-            AddressField field = AddressField.of(substring.charAt(1));
-            fieldOrder.add(field);
-        }
+    // 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;
+  }
 
-        overrideFieldOrder(regionCode, fieldOrder);
+  /**
+   * 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);
+  }
 
-        // 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;
+  private void overrideFieldOrder(String regionCode, List<AddressField> fieldOrder) {
+    if (formOptions.getCustomFieldOrder(regionCode) == null) {
+      return;
     }
 
-    /**
-     * 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);
+    // 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++;
     }
 
-    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 : 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++;
-        }
-
-        // 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));
-        }
+    // 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++;
     }
 
-    /**
-     * 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();
+    // 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);
+      }
+    });
 
-        String lc = address.getLanguageCode();
-        ScriptType scriptType = ScriptType.LOCAL;
-        if (lc != null) {
-            scriptType = Util.isExplicitLatinScript(lc) ? ScriptType.LATIN : ScriptType.LOCAL;
-        }
+    // Puts reordered fields in slots.
+    for (int j = 0; j < union.size(); ++j) {
+      fieldOrder.set(slots.get(j), union.get(j));
+    }
+  }
 
-        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);
+  /**
+   * 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);
 
-                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;
-                }
+    EnumSet<AddressField> required = EnumSet.of(AddressField.COUNTRY);
+    for (char c : requireString.toCharArray()) {
+      required.add(AddressField.of(c));
+    }
+    return required;
+  }
 
-                if (value != null) {
-                    currentLine.append(value);
-                }
-            } else {
-                currentLine.append(formatSymbol);
-            }
-        }
-        String normalizedStr = removeRedundantSpacesAndLeadingPunctuation(currentLine.toString());
+  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);
+          lines.add(normalizedStr);
+          currentLine.setLength(0);
         }
-        return lines;
-    }
+      } else if (formatSymbol.startsWith("%")) {
+        char c = formatSymbol.charAt(1);
+        AddressField field = AddressField.of(c);
+        Util.checkNotNull(field, "null address field for character " + 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);
-                }
-            } else if (c == '%') {
-                escaped = true;
-            } else {
-                parts.add(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;
         }
-        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 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);
+        if (value != null) {
+          currentLine.append(value);
         }
-        return format;
+      } else {
+        currentLine.append(formatSymbol);
+      }
     }
+    String normalizedStr = removeRedundantSpacesAndLeadingPunctuation(currentLine.toString());
+    if (normalizedStr.length() > 0) {
+      lines.add(normalizedStr);
+    }
+    return lines;
+  }
 
-    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);
+  /**
+   * 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>();
 
-        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);
+    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 + "");
+      }
     }
+    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 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);
+    }
+  }
 }
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 @@
  */
 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
+  /**
+   * 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);
+  }
+
+  /**
+   * 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();
+  }
+
+  /**
+   * 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 String) {
-                return (String) o;
-            } 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;
     }
 
-    /**
-     * 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);
+    JSONArray names = obj.names();
+    if (names == null) {
+      return;
     }
 
-    /**
-     * Retrieves the integer value for specified key.
-     *
-     * @return integer value or -1 if value is undefined.
-     */
-    @Override
-    public int getInt(String key) {
+    for (int i = 0; i < names.length(); i++) {
+      try {
+        String name = names.getString(i);
         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");
-            }
+          if (!super.has(name)) {
+            super.put(name, obj.getObject(name));
+          }
         } catch (JSONException e) {
-            return -1;
+          throw new RuntimeException(e);
         }
+      } catch (JSONException e) {
+        // Ignored.
+      }
     }
+  }
 
-    /**
-     * Collect all the keys and return as a JSONArray.
-     *
-     * @return A JSONArray that contains all the keys.
-     */
-    JSONArray getKeys() {
-        return super.names();
+  /**
+   * 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);
     }
+  }
 
-    /**
-     * 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();
-            }
-        } catch (JSONException e) {
-            return null;
-        }
+  /**
+   * 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);
     }
+  }
 
-    /**
-     * 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);
+  /**
+   * 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);
     }
+  }
 
-    /**
-     * 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;
-        }
-
-        JSONArray names = obj.names();
-        if (names == 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.
-            }
-        }
+  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 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);
-        }
+  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');
     }
-
-    /**
-     * 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 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 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();
-    }
+    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 @@
  */
 class JsonpRequestBuilder {
 
-    /**
-     * Re-implementation of the com.google.gwt.user.client.rpc.AsyncCallback interface.
-     */
-    interface AsyncCallback<T> {
+  /**
+   * Re-implementation of the com.google.gwt.user.client.rpc.AsyncCallback interface.
+   */
+  interface AsyncCallback<T> {
 
-        public void onFailure(Throwable caught);
+    public void onFailure(Throwable caught);
 
-        public void onSuccess(T result);
+    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;
     }
 
-    /**
-     * @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 mRequest;
-
-        private AsyncCallback<JsoMap> mCallback;
-
-        protected AsyncHttp(HttpUriRequest request, AsyncCallback<JsoMap> callback) {
-            mRequest = request;
-            mCallback = callback;
+    @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);
+      }
+    }
+  }
 
-        @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);
-            }
+  /**
+   * 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.
     }
 
-    /**
-     * 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 @@
  */
 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 {
+    DATA,
+    /**
+     * Key type for getting examples.
+     */
+    EXAMPLES
+  }
 
-        /**
-         * 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
-    }
+  /**
+   * 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 {
 
     /**
-     * The universal address hierarchy. Notice that sub-administrative area is neglected here since
-     * it is not required to fill out address form.
+     * The script that uses Roman characters like ABC (as opposed to scripts like Cyrillic or
+     * Arabic).
      */
-    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();
-    }
+    LATIN,
 
     /**
-     * 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.
+     * 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.
      */
-    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.");
+    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.");
+    }
+    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);
         }
-        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 (hierarchyField == field) {
+        if (!newKeyBuilder.nodes.containsKey(hierarchyField)) {
+          return null;
         }
-
-        if (!fieldInHierarchy) {
-            return null;
-        }
-
-        newKeyBuilder.languageCode = mLanguageCode;
-        newKeyBuilder.script = mScriptType;
-
-        return newKeyBuilder.build();
+        removeNode = true;
+        fieldInHierarchy = true;
+      }
     }
 
-    /**
-     * 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 "";
+    if (!fieldInHierarchy) {
+      return null;
     }
 
-    /**
-     * 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.");
-        }
-        // Root key's parent should be null.
-        if (!mNodes.containsKey(AddressField.COUNTRY)) {
-            return null;
-        }
+    newKeyBuilder.languageCode = languageCode;
+    newKeyBuilder.script = scriptType;
 
-        Builder parentKeyBuilder = new Builder(this);
-        AddressField mostGranularField = AddressField.COUNTRY;
+    return newKeyBuilder.build();
+  }
 
-        for (AddressField hierarchyField : HIERARCHY) {
-            if (!mNodes.containsKey(hierarchyField)) {
-                break;
-            }
-            mostGranularField = hierarchyField;
-        }
-        parentKeyBuilder.nodes.remove(mostGranularField);
-        return parentKeyBuilder.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;
     }
 
-    KeyType getKeyType() {
-        return mKeyType;
+    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();
+  }
 
-    /**
-     * Gets a key in string format. E.g., "data/US/CA".
-     */
-    private String getKeyString() {
-        StringBuilder keyBuilder = new StringBuilder(mKeyType.name().toLowerCase());
+  KeyType getKeyType() {
+    return keyType;
+  }
 
-        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));
-                }
-            }
+  /**
+   * 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));
         }
+      }
+    } 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);
+      }
+    }
 
-        return keyBuilder.toString();
+    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;
+    }
+
+    return ((LookupKey) obj).toString().equals(keyString);
+  }
+
+  @Override
+  public int hashCode() {
+    return keyString.hashCode();
+  }
+
+  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 {
+
+    private KeyType keyType;
+
+    // Default to LOCAL script.
+
+    private ScriptType script = ScriptType.LOCAL;
+
+    private Map<AddressField, String> nodes = new EnumMap<AddressField, String>(
+        AddressField.class);
+
+    private String languageCode;
+
+    /**
+     * Creates a new builder for the specified key type. keyType cannot be null.
+     */
+    Builder(KeyType keyType) {
+      this.keyType = keyType;
     }
 
     /**
-     * Gets a lookup key as a plain text string., e.g., "data/US/CA".
+     * Creates a new builder for the specified key. oldKey cannot be null.
      */
-    @Override
-    public String toString() {
-        return mKeyString;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
+    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;
         }
-        if ((obj == null) || (obj.getClass() != this.getClass())) {
-            return false;
-        }
-
-        return ((LookupKey) obj).toString().equals(mKeyString);
-    }
-
-    @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;
+        this.nodes.put(field, oldKey.nodes.get(field));
+      }
     }
 
     /**
-     * Builds lookup keys.
+     * 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"
      */
-    static class Builder {
+    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;
 
-        private KeyType keyType;
-
-        // Default to LOCAL script.
-
-        private ScriptType script = ScriptType.LOCAL;
-
-        private Map<AddressField, String> nodes = new EnumMap<AddressField, String>(
-                AddressField.class);
-
-        private String languageCode;
-
-        /**
-         * Creates a new builder for the specified key type. keyType cannot be null.
-         */
-        Builder(KeyType keyType) {
-            this.keyType = keyType;
+        // 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);
         }
 
-        /**
-         * 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));
+        // 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]);
         }
 
-        /**
-         * 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 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.");
+          }
         }
 
-        Builder setLanguageCode(String languageCode) {
-            this.languageCode = languageCode;
-            return this;
+        // Parses language code. Example: "zh_Hant" in
+        // "examples/TW/local/zH_Hant".
+        if (parts.length > 3 && !parts[3].equals(DEFAULT_LANGUAGE)) {
+          languageCode = parts[3];
         }
-
-        /**
-         * 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);
-        }
+      }
     }
+
+    Builder setLanguageCode(String languageCode) {
+      this.languageCode = languageCode;
+      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);
+    }
+  }
 }
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 @@
  * 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 @@
  */
 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);
+    key = data.key;
+    name = data.name;
+  }
+
+  /**
+   * 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 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;
+  }
+
+  /**
+   * A builder class to facilitate the creation of RegionData objects.
+   */
+  static class Builder {
+    RegionData data = new RegionData();
+
+    RegionData build() {
+      return new RegionData(data);
+    }
+
+    Builder setKey(String key) {
+      Util.checkNotNull(key, "Key should not be null.");
+      data.key = key;
+      return this;
     }
 
     /**
-     * Copy constructor. data should not be null.
-     *
-     * @param data A populated instance of RegionData
+     * Sets name of the region. For example, "California". If the name is an empty string, sets
+     * it to null.
      */
-    private RegionData(RegionData data) {
-        Util.checkNotNull(data);
-        mKey = data.mKey;
-        mName = data.mName;
+    Builder setName(String name) {
+      data.name = Util.trimToNull(name);
+      return this;
     }
-
-    /**
-     * Gets the key of the region. For example, California's key is "CA".
-     */
-    String getKey() {
-        return mKey;
-    }
-
-    /**
-     * Gets the name. Returns null if not specified.
-     */
-    String getName() {
-        return mName;
-    }
-
-    /**
-     * Gets the best display name. Returns the name if this is not null, otherwise the key.
-     */
-    public String getDisplayName() {
-        return (mName != null) ? mName : mKey;
-    }
-
-    /**
-     * 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;
-    }
-
-    /**
-     * A builder class to facilitate the creation of RegionData objects.
-     */
-    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;
-        }
-    }
+  }
 }
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 @@
  */
 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());
     }
+  }
 
-    /**
-     * 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();
+  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();
+  }
 }
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 @@
  * 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 @@
  */
 public class StandardAddressVerifier {
 
-    protected final FieldVerifier mRootVerifier;
+  protected final FieldVerifier rootVerifier;
 
-    protected final VerifierRefiner mRefiner;
+  protected final VerifierRefiner refiner;
 
-    protected final Map<AddressField, List<AddressProblemType>> mProblemMap;
+  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 {@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);
+    }
+  }
+
+  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;
     }
 
-    /**
-     * 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);
-    }
+    @Override
+    public void run() {
+      listener.dataLoadingBegin();
 
-    /**
-     * 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);
-    }
+      FieldVerifier v = rootVerifier;
 
-    /**
-     * 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 verify(AddressData address, AddressProblems problems) {
-        NotifyingListener listener = new NotifyingListener(this);
-        verifyAsync(address, problems, listener);
-        try {
-            listener.waitLoadingEnd();
-        } catch (InterruptedException e) {
-            throw new RuntimeException(e);
+      ScriptType script = null;
+      if (address.getLanguageCode() != null) {
+        if (Util.isExplicitLatinScript(address.getLanguageCode())) {
+          script = ScriptType.LATIN;
+        } else {
+          script = ScriptType.LOCAL;
         }
-    }
+      }
 
-    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 mAddress;
-        private AddressProblems mProblems;
-        private DataLoadListener mListener;
-
-        Verifier(AddressData address, AddressProblems problems, DataLoadListener listener) {
-            mAddress = address;
-            mProblems = problems;
-            mListener = listener;
-        }
-
-        @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, 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());
             }
-
-            // 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());
-                        }
-                    }
-                }
-            }
-
-            String street = Util.joinAndSkipNulls("\n", mAddress.getAddressLine1(),
-                    mAddress.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);
-
-            postVerify(v, mAddress, mProblems);
-
-            mListener.dataLoadingEnd();
+          }
         }
+      }
+
+      String street = Util.joinAndSkipNulls("\n", address.getAddressLine1(),
+          address.getAddressLine2());
+
+      // 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, address, problems);
+
+      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 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 = 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 {
+
+    /**
+     * 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);
     }
 
     /**
-     * Hook to perform any final processing using the final verifier.  Default does no additional
-     * verification.
+     * Returns a clean version of the refiner.  Since this implementation is stateless, returns
+     * this.
      */
-    protected void postVerify(FieldVerifier verifier, AddressData address,
-            AddressProblems problems) {
+    public VerifierRefiner newInstance() {
+      return this;
     }
+  }
 
-    /**
-     * 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();
-    }
-
-    /**
-     * 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 {
-
-        /**
-         * 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;
-        }
-    }
-
-    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 @@
  */
 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 @@
  * 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 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;
+  }
+
+  /**
+   * 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);
+    }
+  }
+
+  /**
+   * 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();
+  }
+
+  /**
+   * 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;
     }
 
-    /**
-     * 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;
+    Map<String, String> nameToKeyMap = new HashMap<String, String>();
+
+    int keyLength = keys.length;
+    for (String k : keys) {
+      nameToKeyMap.put(k.toLowerCase(), k);
     }
-
-    /**
-     * 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();
+    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]);
         }
-        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;
+    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]);
         }
-        String trimmedString = originalStr.trim();
-        return (trimmedString.length() == 0) ? null : trimmedString;
+      }
     }
+    return nameToKeyMap;
+  }
 
-    /**
-     * 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.");
+  /**
+   * 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();
+      }
     }
-
-    /**
-     * 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);
-                    }
-                }
-            }
-        }
-        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;
-        }
-
-        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]);
-                }
-            }
-        }
-        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;
-    }
-
-    /**
-     * 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();
-            }
-        }
-        return language.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 @@
  */
 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 @@
  * 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() {
+    testIsFinished = true;
+    synchronized (this) {
+      notify();
     }
+  }
 
-    /**
-     * Causes this test to succeed during asynchronous mode.
-     */
-    protected void finishTest() {
-        mTestIsFinished = true;
+  @Override
+  protected void runTest() throws Throwable {
+    testIsFinished = false;
+    testTimeoutMillis = 0;
+    super.runTest();
+
+    if (testTimeoutMillis > 0) {
+      long timeoutMillis = testTimeoutMillis - System.currentTimeMillis();
+      if (timeoutMillis > 0) {
         synchronized (this) {
-            notify();
+          wait(timeoutMillis);
         }
+      }
+      if (!testIsFinished) {
+        throw new TimeoutException("Waited " + timeoutMillis + " ms!");
+      }
     }
-
-    @Override
-    protected void runTest() throws Throwable {
-        mTestIsFinished = false;
-        mTestTimeoutMillis = 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!");
-            }
-        }
-    }
+  }
 }
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 @@
  * 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 @@
  */
 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 @@
  * 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 @@
  */
 public class AddressVerificationDataTest extends TestCase {
 
-    private static final AddressVerificationData ADDRESS_DATA =
-            new AddressVerificationData(AddressDataMapLoader.DATA);
+  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 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));
+  }
+
+  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);
-    }
+    // Spot check.
+    assertEquals("Kazhakstan's postal code pattern mismatched", "\\d{6}",
+        ADDRESS_DATA.get("data/KZ").get(AddressDataKey.ZIP));
+  }
 
-    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"));
-    }
+  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 @@
 /**
  * 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);
-    }
-    
-    @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);
-            }
-        }
-        
-        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 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);
+      }
     }
 
-    private class CustomSpinner extends Spinner {
-        CustomSpinner(Context context) {
-            super(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);
     }
-    
-    private class CustomArrayAdapter<String> extends ArrayAdapter {
-        CustomArrayAdapter(Context context, int id) {
-            super(context, id);
-        }
+  }
+
+  private class CustomSpinner extends Spinner {
+    CustomSpinner(Context context) {
+      super(context);
     }
-    
-    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();
-        }
+  }
+
+  private class CustomArrayAdapter<String> extends ArrayAdapter {
+    CustomArrayAdapter(Context context, int id) {
+      super(context, id);
     }
+  }
+
+  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>(
+          context, 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();
+    }
+  }
 }
- 
\ 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 @@
 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 @@
    * 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();
-      }
-
-      @Override
-      public void run() {
-          try {
-              synchronized (this) {
-              wait(mWaitMillis);
-          }
-      } catch (InterruptedException e) {
-          throw new RuntimeException(e);
-      }
-      mCallback.run();
-    }
+    private long waitMillis;
+    private Runnable callback;
 
     private AsyncCallback(long waitMillis, Runnable callback) {
-        this.mWaitMillis = waitMillis;
-        this.mCallback = callback;
+      this.waitMillis = waitMillis;
+      this.callback = callback;
     }
 
-    private long mWaitMillis;
-    private Runnable mCallback;
+    public static void execute(long waitMillis, Runnable callback) {
+      (new AsyncCallback(waitMillis, callback)).start();
+    }
+
+    @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.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();
+  @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();
 
-    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");
+    // 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()));
+
+        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;
         }
-        cache.addToJsoMap(id, jsonObject);
-        String toBackup = cache.getJsonString();
+        assertTrue("CounterListener's dataLoadingBegin should not be invoked for more " +
+            "than " + maxCount + " times",
+            listenerInvokeCount <= maxCount);
+      }
 
-        // 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");
+      @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();
         }
+      }
     }
 
-    public void testSimpleFetching() {
-        final LookupKey key = new LookupKey.Builder(CANADA_KEY).build();
+    delayTestFinish(10000);
 
-        delayTestFinish(10000);
+    for (int i = 0; i < maxCount; ++i) {
+      cache.fetchDynamicData(key, null, new CounterListener());
+    }
+
+    // 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);
+
+    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 beginCalled = false;
+          boolean beginCalled2 = false;
 
-            @Override
-            public void dataLoadingBegin() {
-                beginCalled = true;
-            }
+          @Override
+          public void dataLoadingBegin() {
+            beginCalled2 = true;
+          }
 
-            @Override
-            public void dataLoadingEnd() {
-                assertTrue("dataLoadingBegin should be called", beginCalled);
-                JsoMap map = cache.getObj(CANADA_KEY);
+          @Override
+          public void dataLoadingEnd() {
+            assertTrue("dataLoadingBegin should be called", beginCalled2);
 
-                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();
-            }
+            assertTrue(cache.containsKey(key.toString()));
+            finishTest();
+          }
         });
-    }
+      }
+    });
+  }
 
-    public void testFetchingTaiwanData() {
-        final LookupKey key = new LookupKey.Builder(TW_KEY).build();
+  public void testInvalidKey() {
+    final LookupKey key = new LookupKey.Builder(RANDOM_COUNTRY_KEY).build();
 
-        delayTestFinish(10000);
+    delayTestFinish(15000);
 
-        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() {
+        beginCalled = true;
+      }
 
-            @Override
-            public void dataLoadingEnd() {
-                assertTrue("dataLoadingBegin should be called", beginCalled);
+      @Override
+      public void dataLoadingEnd() {
+        assertTrue("dataLoadingBegin should be called", beginCalled);
+        assertFalse(cache.containsKey(key.toString()));
 
-                JsoMap map = cache.getObj(TW_KEY);
+        finishTest();
+      }
+    });
+  }
 
-                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()));
+  public void testSetUrl() {
+    final LookupKey key = new LookupKey.Builder(FRANCE_KEY).build();
+    final String originalUrl = cache.getUrl();
 
-                // Da-an district.
-                assertEquals("\u5927\u5B89\u5340",
-                             map.get(AddressDataKey.KEY.name().toLowerCase()));
+    assertFalse(FRANCE_KEY + " should not be in the cache. Do you request it before this test?",
+        cache.containsKey(key.toString()));
 
-                assertEquals("zh-hant", map.get(AddressDataKey.LANG.name().toLowerCase()));
+    delayTestFinish(10000);
+    // Something that is not an URL.
+    cache.setUrl("FDSSfdfdsfasdfadsf");
 
-                finishTest();
-            }
-        });
-    }
+    cache.fetchDynamicData(key, null, new DataLoadListener() {
+      boolean beginCalled = false;
 
-    public void testFetchingExamples() {
-        final LookupKey key = new LookupKey.Builder(EXAMPLE_LOCAL_US_KEY).build();
+      @Override
+      public void dataLoadingBegin() {
+        beginCalled = true;
+      }
 
-        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;
-                }
-                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();
-                }
-            }
-        }
-
-        delayTestFinish(10000);
-
-        for (int i = 0; i < maxCount; ++i) {
-            cache.fetchDynamicData(key, null, new CounterListener());
-        }
-
-        // 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);
-
-        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 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();
-            }
-        });
-    }
+      @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 @@
  * 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 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 static final StandardAddressVerifier VERIFIER =
+      new StandardAddressVerifier(new FieldVerifier(
+          new AddressVerificationData(AddressDataMapLoader.DATA)));
 
-    private AddressProblems problems = new AddressProblems();
+  private AddressProblems problems = new AddressProblems();
 
-    @Override
-    protected void setUp() {
-        problems.clear();
-    }
+  @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 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);
+  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));
-    }
+    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);
+  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));
-    }
+    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 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();
+  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());
+    VERIFIER.verify(addr, problems);
+    assertTrue(problems.isEmpty());
 
-        // Clones address but leave city empty.
-        addr = new AddressData.Builder().set(addr).setLocality(null).build();
+    // 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));
-    }
+    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();
+  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());
+    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();
+    // 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());
-    }
+    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);
+  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));
-    }
+    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());
+  /**
+   * 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();
+    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);
+    // 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));
-    }
+    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 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);
+  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));
-    }
+    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();
+  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());
+    assertNull(addr.getAddressLine1());
+    assertNull(addr.getAddressLine2());
 
-        VERIFIER.verify(addr, problems);
+    VERIFIER.verify(addr, problems);
 
-        assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
-                     problems.getProblem(AddressField.STREET_ADDRESS));
-    }
+    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());
-    }
+  // 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 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 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 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 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 @@
  */
 public class FormControllerTest extends AsyncTestCase {
 
-    private static final AddressData US_CA_ADDRESS;
-    private static final AddressData US_ADDRESS;
-    private ClientData clientData;
+  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();
-    }
+  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());
-    }
+  @Override
+  public void setUp() {
+    clientData = new ClientData(new CacheData());
+  }
 
-    public void testRequestDataForAddress() {
-        final FormController controller = new FormController(clientData, "en", "US");
+  public void testRequestDataForAddress() {
+    final FormController controller = new FormController(clientData, "en", "US");
 
-        delayTestFinish(15000);
+    delayTestFinish(15000);
 
-        controller.requestDataForAddress(US_CA_ADDRESS, new DataLoadListener() {
-            boolean beginCalled = false;
-            @Override
-            public void dataLoadingBegin() {
-                beginCalled = true;
-            }
+    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();
-            }
-        });
-    }
+      @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();
+  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");
+    final FormController controller = new FormController(clientData, "en", "US");
 
-        delayTestFinish(15000);
+    delayTestFinish(15000);
 
-        controller.requestDataForAddress(address, new DataLoadListener() {
-            boolean beginCalled = false;
-            @Override
-            public void dataLoadingBegin() {
-                beginCalled = true;
-            }
+    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);
+      @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();
+        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();
-            }
-        });
-    }
+        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");
+  public void testRequestDataForCountry() {
+    final FormController controller = new FormController(clientData, "en", "US");
 
-        delayTestFinish(15000);
+    delayTestFinish(15000);
 
-        controller.requestDataForAddress(US_ADDRESS, new DataLoadListener() {
-            boolean beginCalled = false;
-            @Override
-            public void dataLoadingBegin() {
-                beginCalled = true;
-            }
+    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();
-            }
-        });
-    }
+      @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 @@
  * 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 @@
  * Tests for the FormatInterpreter class.
  */
 public class FormatInterpreterTest extends TestCase {
-    private static final AddressData US_CA_ADDRESS;
-    private static final AddressData TW_ADDRESS;
+  private static final AddressData US_CA_ADDRESS;
+  private static final AddressData TW_ADDRESS;
 
-    private FormatInterpreter formatInterpreter;
+  private FormatInterpreter formatInterpreter;
 
-    static {
-        US_CA_ADDRESS = new AddressData.Builder().setCountry("US")
-                                                 .setAdminArea("CA")
-                                                 .setLocality("Mt View")
-                                                 .setAddressLine1("1098 Alta Ave")
-                                                 .setPostalCode("94043")
-                                                 .build();
+  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();
+    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());
+  }
+
+  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++;
     }
+  }
 
-    @Override
-    public void setUp() {
-        formatInterpreter = new FormatInterpreter(new FormOptions.Builder().build());
+  /**
+   * 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 testIterateUsAddressFields() {
-        AddressField[] format = {
-            AddressField.RECIPIENT,
-            AddressField.ORGANIZATION,
-            AddressField.ADDRESS_LINE_1,
-            AddressField.ADDRESS_LINE_2,
-            AddressField.LOCALITY,
-            AddressField.ADMIN_AREA,
-            AddressField.POSTAL_CODE
-        };
+  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
+    };
 
-        int currIndex = 0;
-        for (AddressField field : formatInterpreter.getAddressFieldOrder(ScriptType.LOCAL, "US")) {
-            assertEquals("index " + currIndex + " should have matched",
-                         format[currIndex].getChar(), field.getChar());
-            currIndex++;
-        }
+    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++;
     }
+  }
 
-    /**
-     * 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,
-        };
+  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.LOCAL, "VU")) {
-            assertEquals("index " + currIndex + " should have matched",
-                         format[currIndex].getChar(), field.getChar());
-            currIndex++;
-        }
+    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 testOverrideFieldOrder() {
-        AddressField[] expectedOrder = {
-            AddressField.ADMIN_AREA,
-            AddressField.ORGANIZATION,
-            AddressField.ADDRESS_LINE_1,
-            AddressField.ADDRESS_LINE_2,
-            AddressField.LOCALITY,
-            AddressField.RECIPIENT,
-            AddressField.POSTAL_CODE
-        };
+  public void testUsEnvelopeAddress() {
+    List<String> expected = new ArrayList<String>();
+    expected.add("1098 Alta Ave");
+    expected.add("Mt View, CA 94043");
 
-        FormatInterpreter myInterpreter = new FormatInterpreter(
-                new FormOptions.Builder().customizeFieldOrder("US",
-                                                              AddressField.ADMIN_AREA,
-                                                              AddressField.RECIPIENT,
-                                                              AddressField.SORTING_CODE,
-                                                              AddressField.POSTAL_CODE).build());
+    List<String> real = formatInterpreter.getEnvelopeAddress(US_CA_ADDRESS);
 
-        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);
+    assertEquals(expected, real);
+  }
 
-            // 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 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 testIterateTwLatinAddressFields() {
-        AddressField[] format = {
-            AddressField.RECIPIENT,
-            AddressField.ORGANIZATION,
-            AddressField.ADDRESS_LINE_1,
-            AddressField.ADDRESS_LINE_2,
-            AddressField.LOCALITY,
-            AddressField.ADMIN_AREA,
-            AddressField.POSTAL_CODE
-        };
+    List<String> real = formatInterpreter.getEnvelopeAddress(TW_ADDRESS);
 
-        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++;
-        }
-    }
+    assertEquals(expected, real);
+  }
 
-    public void testUsEnvelopeAddress() {
-        List<String> expected = new ArrayList<String>();
-        expected.add("1098 Alta Ave");
-        expected.add("Mt View, CA 94043");
+  public void testEnvelopeAddressIncompleteAddress() {
+    List<String> expected = new ArrayList<String>();
+    expected.add("1098 Alta Ave");
+    expected.add("CA 94043");
 
-        List<String> real = formatInterpreter.getEnvelopeAddress(US_CA_ADDRESS);
+    AddressData address = new AddressData.Builder().set(US_CA_ADDRESS)
+        .set(AddressField.LOCALITY, null).build();
 
-        assertEquals(expected, real);
-    }
+    List<String> real = formatInterpreter.getEnvelopeAddress(address);
 
-    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");
+    assertEquals(expected, real);
+  }
 
-        List<String> real = formatInterpreter.getEnvelopeAddress(TW_ADDRESS);
+  public void testEnvelopeAddressEmptyAddress() {
+    List<String> expected = new ArrayList<String>();
+    AddressData address = new AddressData.Builder().setCountry("US").build();
 
-        assertEquals(expected, real);
-    }
-
-    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();
-
-        List<String> real = formatInterpreter.getEnvelopeAddress(address);
-
-        assertEquals(expected, real);
-    }
-
-    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> 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> 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();
+    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> 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);
+    List<String> real = formatInterpreter.getEnvelopeAddress(svAddress);
+    assertEquals(expected, real);
 
-      final AddressData svAddressWithPostCode = new AddressData.Builder(svAddress)
-              .setPostalCode("CP 2101")
-              .build();
+    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");
+    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);
+    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 @@
  */
 public class JsoMapTest extends TestCase {
 
-    private static final String VALID_JSON = "{\"a\":\"b\",\"c\":1,\"d\":{\"e\":\"f\"}}";
-    private static final String INVALID_JSON = "!";
+  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));
+  public void testBuildJsoMap() throws Exception {
+    assertNotNull(JsoMap.buildJsoMap(VALID_JSON));
 
-        try {
-            JsoMap.buildJsoMap(INVALID_JSON);
-            fail("Expected JSONException.");
-        } catch (JSONException e) {
-            // Expected.
-        }
+    try {
+      JsoMap.buildJsoMap(INVALID_JSON);
+      fail("Expected JSONException.");
+    } catch (JSONException 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 testCreateEmptyJsoMap() throws Exception {
-        assertNotNull(JsoMap.createEmptyJsoMap());
+    try {
+      map.get("d");
+      fail("Expected ClassCastException.");
+    } catch (ClassCastException e) {
+      // Expected.
+    }
+  }
+
+  public void testGetInt() throws Exception {
+    JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+
+    try {
+      map.getInt("a");
+      fail("Expected RuntimeException.");
+    } catch (RuntimeException e) {
+      // Expected.
     }
 
-    public void testDelKey() throws Exception {
-        JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+    assertEquals(-1, map.getInt("b"));
+    assertEquals(1, map.getInt("c"));
 
-        assertEquals("b", map.get("a"));
-        map.delKey("a");
-        assertNull(map.get("a"));
+    try {
+      map.getInt("d");
+      fail("Expected RuntimeException.");
+    } catch (RuntimeException e) {
+      // Expected.
+    }
+  }
 
-        map.delKey("b");
-        map.delKey("c");
-        map.delKey("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 testGetObj() throws Exception {
+    JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+
+    try {
+      map.getObj("a");
+      fail("Expected ClassCastException.");
+    } catch (ClassCastException e) {
+      // Expected.
     }
 
-    public void testGet() throws Exception {
-        JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
-        assertEquals("b", map.get("a"));
-        assertNull(map.get("b"));
+    assertNull(map.getObj("b"));
 
-        try {
-            map.get("c");
-            fail("Expected IllegalArgumentException.");
-        } catch (IllegalArgumentException e) {
-            // Expected.
-        }
-
-        try {
-            map.get("d");
-            fail("Expected ClassCastException.");
-        } catch (ClassCastException e) {
-            // Expected.
-        }
+    try {
+      map.getObj("c");
+      fail("Expected IllegalArgumentException.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
     }
 
-    public void testGetInt() throws Exception {
-        JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+    JsoMap obj = map.getObj("d");
+    assertNotNull(obj);
+    assertEquals("f", obj.get("e"));
+  }
 
-        try {
-            map.getInt("a");
-            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"));
+  }
 
-        assertEquals(-1, map.getInt("b"));
-        assertEquals(1, map.getInt("c"));
+  public void testMergeData() throws Exception {
+    JsoMap mapA = JsoMap.createEmptyJsoMap();
+    JsoMap mapB = JsoMap.createEmptyJsoMap();
 
-        try {
-            map.getInt("d");
-            fail("Expected RuntimeException.");
-        } catch (RuntimeException e) {
-            // Expected.
-        }
+    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 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);
+    map.delKey("c");
+    try {
+      // This should fail on the object "d".
+      map.string();
+      fail("Expected ClassCastException.");
+    } catch (ClassCastException e) {
+      // Expected.
     }
 
-    public void testGetObj() throws Exception {
-        JsoMap map = JsoMap.buildJsoMap(VALID_JSON);
+    map.delKey("d");
+    assertEquals("JsoMap[\n(a:b)\n]", map.string());
+  }
 
-        try {
-            map.getObj("a");
-            fail("Expected ClassCastException.");
-        } catch (ClassCastException e) {
-            // Expected.
-        }
-
-        assertNull(map.getObj("b"));
-
-        try {
-            map.getObj("c");
-            fail("Expected IllegalArgumentException.");
-        } catch (IllegalArgumentException e) {
-            // Expected.
-        }
-
-        JsoMap obj = map.getObj("d");
-        assertNotNull(obj);
-        assertEquals("f", obj.get("e"));
+  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 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"));
+    map.delKey("a");
+    try {
+      // This should fail on the integer "c".
+      map.map();
+      fail("Expected IllegalArgumentException.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
     }
 
-    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.
-        }
-
-        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());
-    }
-
-    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("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.SocketTimeoutException;
 
 public class JsonpRequestBuilderTest extends AsyncTestCase {
-    private JsonpRequestBuilder builder;
+  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 {
+    /**
+     * 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() + "/";
+    }
 
     @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 {
-        /**
-         * 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 void run() {
+      try {
+        Socket clientSocket = serverSocket.accept();
+        try {
+          synchronized (this) {
+            wait(waitMillis);
+          }
+        } catch (InterruptedException 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 long waitMillis;
-        private byte[] response;
-        private ServerSocket serverSocket;
-
-        private static final String header = "HTTP/1.0 200 OK\nContent-Type: text/plain\n\n";
+        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 long waitMillis;
+    private byte[] response;
+    private ServerSocket serverSocket;
+
+    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 @@
  * 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";
+  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";
+  // 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 (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";
+  // 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";
+  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());
+  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());
+    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 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 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);
     }
 
-    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());
+    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 testExampleRootKeys() {
-        LookupKey key = new LookupKey.Builder(KeyType.EXAMPLES).build();
-        assertEquals(ROOT_EXAMPLE_KEY, key.toString());
-    }
+  public void testGetValueForUpperLevelField() {
+    LookupKey key = new LookupKey.Builder("data/US/CA").build();
+    assertEquals("US", key.getValueForUpperLevelField(AddressField.COUNTRY));
+  }
 
-    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 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 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));
-    }
-
-    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));
-    }
+  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 @@
  * 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 @@
  * 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 @@
  */
 public class StandardAddressVerifierTest extends TestCase {
 
-    private AddressProblems problems = new AddressProblems();
-    private StandardAddressVerifier verifier;
+  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);
-    }
+  @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 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);
+  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));
-    }
+    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);
+  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));
-    }
+    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 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();
+  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());
+    verifier.verify(addr, problems);
+    assertTrue(problems.toString(), problems.isEmpty());
 
-        // Clones address but leave city empty.
-        addr = new AddressData.Builder().set(addr).setLocality(null).build();
+    // 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));
-    }
+    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();
+  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());
+    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();
+    // 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());
-    }
+    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);
+  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));
-    }
+    // 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());
+  /**
+   * 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();
+    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);
+    // 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));
-    }
+    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 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);
+  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));
-    }
+    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();
+  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());
+    assertNull(addr.getAddressLine1());
+    assertNull(addr.getAddressLine2());
 
-        verifier.verify(addr, problems);
+    verifier.verify(addr, problems);
 
-        assertEquals(AddressProblemType.MISSING_REQUIRED_FIELD,
-                     problems.getProblem(AddressField.STREET_ADDRESS));
-    }
+    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());
-    }
+  // 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 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());
-    }
+  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 @@
  */
 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(""));
+  }
 }