Merge tag android-5.1.0_r1 into AOSP_5.1_MERGE

Change-Id: I1bfeb0d9aa9e441e0962baf17b8f9b28dfc206b3
diff --git a/cpp/include/libaddressinput/address_data.h b/cpp/include/libaddressinput/address_data.h
index e2d057a..89d3273 100644
--- a/cpp/include/libaddressinput/address_data.h
+++ b/cpp/include/libaddressinput/address_data.h
@@ -55,6 +55,10 @@
   // Language code of the address. Should be in BCP-47 format.
   std::string language_code;
 
+  // The organization, firm, company, or institution at this address. This
+  // corresponds to the FirmName sub-element of the xAL FirmType element.
+  std::string organization;
+
   // Name of recipient or contact person. Not present in xAL.
   std::string recipient;
 
diff --git a/cpp/include/libaddressinput/address_field.h b/cpp/include/libaddressinput/address_field.h
index 1adc97b..8f2ee05 100644
--- a/cpp/include/libaddressinput/address_field.h
+++ b/cpp/include/libaddressinput/address_field.h
@@ -31,6 +31,7 @@
   SORTING_CODE,        // Sorting code.
   POSTAL_CODE,         // Zip or postal code.
   STREET_ADDRESS,      // Street address lines.
+  ORGANIZATION,        // Organization, company, firm, institution, etc.
   RECIPIENT            // Name.
 };
 
diff --git a/cpp/include/libaddressinput/address_input_helper.h b/cpp/include/libaddressinput/address_input_helper.h
index ce52cf9..feb04d7 100644
--- a/cpp/include/libaddressinput/address_input_helper.h
+++ b/cpp/include/libaddressinput/address_input_helper.h
@@ -15,17 +15,17 @@
 #ifndef I18N_ADDRESSINPUT_ADDRESS_INPUT_HELPER_H_
 #define I18N_ADDRESSINPUT_ADDRESS_INPUT_HELPER_H_
 
-#include <vector>
-
 #include <libaddressinput/util/basictypes.h>
 
+#include <vector>
+
 namespace i18n {
 namespace addressinput {
 
 class LookupKey;
-class Node;
 class PreloadSupplier;
 struct AddressData;
+struct Node;
 
 class AddressInputHelper {
  public:
diff --git a/cpp/include/libaddressinput/address_metadata.h b/cpp/include/libaddressinput/address_metadata.h
index 269f982..cbe72db 100644
--- a/cpp/include/libaddressinput/address_metadata.h
+++ b/cpp/include/libaddressinput/address_metadata.h
@@ -17,6 +17,8 @@
 
 #include <libaddressinput/address_field.h>
 
+#include <string>
+
 namespace i18n {
 namespace addressinput {
 
diff --git a/cpp/include/libaddressinput/address_normalizer.h b/cpp/include/libaddressinput/address_normalizer.h
index 6bd3366..06b7eb2 100644
--- a/cpp/include/libaddressinput/address_normalizer.h
+++ b/cpp/include/libaddressinput/address_normalizer.h
@@ -21,9 +21,9 @@
 namespace i18n {
 namespace addressinput {
 
-class AddressData;
 class PreloadSupplier;
 class StringCompare;
+struct AddressData;
 
 class AddressNormalizer {
  public:
diff --git a/cpp/include/libaddressinput/address_validator.h b/cpp/include/libaddressinput/address_validator.h
index d3a09f3..cdb1edf 100644
--- a/cpp/include/libaddressinput/address_validator.h
+++ b/cpp/include/libaddressinput/address_validator.h
@@ -38,7 +38,8 @@
 //    class MyClass {
 //     public:
 //      MyClass()
-//          : validator_(kMyServerUrl, new MyDownloader, new MyStorage),
+//          : supplier_(new MySupplier),
+//            validator_(new AddressValidator(supplier_.get())),
 //            validated_(BuildCallback(this, &MyClass::Validated)) {}
 //
 //      virtual ~MyClass() {}
@@ -61,7 +62,8 @@
 //      AddressData address_;
 //      FieldProblemMap filter_;
 //      FieldProblemMap problems_;
-//      const AddressValidator validator_;
+//      const scoped_ptr<Supplier> supplier_;
+//      const scoped_ptr<AddressValidator> validator_;
 //      const scoped_ptr<const AddressValidator::Callback> validated_;
 //    };
 class AddressValidator {
diff --git a/cpp/include/libaddressinput/downloader.h b/cpp/include/libaddressinput/downloader.h
deleted file mode 100644
index 0da4e1f..0000000
--- a/cpp/include/libaddressinput/downloader.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2013 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// The interface to be implemented by the user of the library to enable
-// downloading validation rules from a server.
-
-#ifndef I18N_ADDRESSINPUT_DOWNLOADER_H_
-#define I18N_ADDRESSINPUT_DOWNLOADER_H_
-
-#include <libaddressinput/callback.h>
-
-#include <string>
-
-namespace i18n {
-namespace addressinput {
-
-// Downloads validation rules from the server. The downloaded data must be
-// allocated on the heap, passing ownership to the callback. Sample usage:
-//
-//    class MyDownloader : public Downloader {
-//     public:
-//      virtual void Download(const std::string& url,
-//                            const Callback& downloaded) const {
-//        bool success = ...
-//        std::string* data = new ...
-//        downloaded(success, url, data);
-//      }
-//    };
-class Downloader {
- public:
-  typedef i18n::addressinput::Callback<const std::string&,
-                                       std::string*> Callback;
-
-  virtual ~Downloader() {}
-
-  // Downloads |url| and invokes the |downloaded| callback.
-  virtual void Download(const std::string& url,
-                        const Callback& downloaded) const = 0;
-};
-
-}  // namespace addressinput
-}  // namespace i18n
-
-#endif  // I18N_ADDRESSINPUT_DOWNLOADER_H_
diff --git a/cpp/include/libaddressinput/localization.h b/cpp/include/libaddressinput/localization.h
index acfdf7e..5e7896d 100644
--- a/cpp/include/libaddressinput/localization.h
+++ b/cpp/include/libaddressinput/localization.h
@@ -17,9 +17,9 @@
 
 #include <libaddressinput/address_field.h>
 #include <libaddressinput/address_problem.h>
+#include <libaddressinput/util/basictypes.h>
 
 #include <string>
-#include <vector>
 
 namespace i18n {
 namespace addressinput {
@@ -84,6 +84,8 @@
 
   // The string getter.
   std::string (*get_string_)(int);
+
+  DISALLOW_COPY_AND_ASSIGN(Localization);
 };
 
 }  // namespace addressinput
diff --git a/cpp/include/libaddressinput/ondemand_supplier.h b/cpp/include/libaddressinput/ondemand_supplier.h
index 0fe33f8..6212d34 100644
--- a/cpp/include/libaddressinput/ondemand_supplier.h
+++ b/cpp/include/libaddressinput/ondemand_supplier.h
@@ -26,10 +26,10 @@
 namespace i18n {
 namespace addressinput {
 
-class Downloader;
 class LookupKey;
 class Retriever;
 class Rule;
+class Source;
 class Storage;
 
 // An implementation of the Supplier interface that owns a Retriever object,
@@ -46,14 +46,8 @@
 // in total less than 2 MB of JSON data.)
 class OndemandSupplier : public Supplier {
  public:
-  // Takes ownership of |downloader| and |storage|. The |validation_data_url|
-  // should be a URL to an address data server that |downloader| can access.
-  //
-  // (See the documentation for the Downloader implementation used for
-  // information about what URLs are useable with that Downloader.)
-  OndemandSupplier(const std::string& validation_data_url,
-                   const Downloader* downloader,
-                   Storage* storage);
+  // Takes ownership of |source| and |storage|.
+  OndemandSupplier(const Source* source, Storage* storage);
   virtual ~OndemandSupplier();
 
   // Loads the metadata needed for |lookup_key|, then calls |supplied|.
diff --git a/cpp/include/libaddressinput/preload_supplier.h b/cpp/include/libaddressinput/preload_supplier.h
index 740b4d0..5987c79 100644
--- a/cpp/include/libaddressinput/preload_supplier.h
+++ b/cpp/include/libaddressinput/preload_supplier.h
@@ -20,6 +20,7 @@
 #include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
 
+#include <map>
 #include <set>
 #include <string>
 #include <vector>
@@ -27,11 +28,11 @@
 namespace i18n {
 namespace addressinput {
 
-class Downloader;
 class IndexMap;
 class LookupKey;
 class Retriever;
 class Rule;
+class Source;
 class Storage;
 
 // An implementation of the Supplier interface that owns a Retriever object,
@@ -41,8 +42,8 @@
 // or in progress of being loaded.
 //
 // When using a PreloadSupplier, it becomes possible to do synchronous address
-// validation using an asynchronous Downloader, and to have full control over
-// when network access is being done.
+// validation using an asynchronous Source, and to have full control over when
+// network access is being done.
 //
 // The maximum size of this cache is naturally limited to the amount of data
 // available from the data server. (Currently this is less than 12,000 items of
@@ -51,15 +52,8 @@
  public:
   typedef i18n::addressinput::Callback<const std::string&, int> Callback;
 
-  // Takes ownership of |downloader| and |storage|. The |validation_data_url|
-  // should be a URL to a service that returns address metadata aggregated per
-  // region, and which |downloader| can access.
-  //
-  // (See the documentation for the Downloader implementation used for
-  // information about what URLs are useable with that Downloader.)
-  PreloadSupplier(const std::string& validation_data_url,
-                  const Downloader* downloader,
-                  Storage* storage);
+  // Takes ownership of |source| and |storage|.
+  PreloadSupplier(const Source* source, Storage* storage);
   virtual ~PreloadSupplier();
 
   // Collects the metadata needed for |lookup_key| from the cache, then calls
@@ -80,6 +74,11 @@
   // Calls |loaded| when the loading has finished.
   void LoadRules(const std::string& region_code, const Callback& loaded);
 
+  // Returns a mapping of lookup keys to rules. Should be called only when
+  // IsLoaded() returns true for the |region_code|.
+  const std::map<std::string, const Rule*>& GetRulesForRegion(
+      const std::string& region_code) const;
+
   bool IsLoaded(const std::string& region_code) const;
   bool IsPending(const std::string& region_code) const;
 
@@ -93,6 +92,7 @@
   std::set<std::string> pending_;
   const scoped_ptr<IndexMap> rule_index_;
   std::vector<const Rule*> rule_storage_;
+  std::map<std::string, std::map<std::string, const Rule*> > region_rules_;
 
   DISALLOW_COPY_AND_ASSIGN(PreloadSupplier);
 };
diff --git a/cpp/include/libaddressinput/source.h b/cpp/include/libaddressinput/source.h
new file mode 100644
index 0000000..4d91b68
--- /dev/null
+++ b/cpp/include/libaddressinput/source.h
@@ -0,0 +1,56 @@
+// Copyright (C) 2013 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// The interface to be implemented by the user of the library to access address
+// metadata, typically by downloading this from the address metadata server or
+// by linking the metadata into the binary.
+
+#ifndef I18N_ADDRESSINPUT_SOURCE_H_
+#define I18N_ADDRESSINPUT_SOURCE_H_
+
+#include <libaddressinput/callback.h>
+
+#include <string>
+
+namespace i18n {
+namespace addressinput {
+
+// Gets address metadata. The callback data must be allocated on the heap,
+// passing ownership to the callback. Sample usage:
+//
+//    class MySource : public Source {
+//     public:
+//      virtual void Get(const std::string& key,
+//                       const Callback& data_ready) const {
+//        bool success = ...
+//        std::string* data = new ...
+//        data_ready(success, key, data);
+//      }
+//    };
+class Source {
+ public:
+  typedef i18n::addressinput::Callback<const std::string&,
+                                       std::string*> Callback;
+
+  virtual ~Source() {}
+
+  // Gets metadata for |key| and invokes the |data_ready| callback.
+  virtual void Get(const std::string& key,
+                   const Callback& data_ready) const = 0;
+};
+
+}  // namespace addressinput
+}  // namespace i18n
+
+#endif  // I18N_ADDRESSINPUT_SOURCE_H_
diff --git a/cpp/include/libaddressinput/storage.h b/cpp/include/libaddressinput/storage.h
index 38fb887..94ad13b 100644
--- a/cpp/include/libaddressinput/storage.h
+++ b/cpp/include/libaddressinput/storage.h
@@ -13,7 +13,7 @@
 // limitations under the License.
 //
 // The interface to be implemented by the user of the library to enable storing
-// the downloaded validation rules (e.g. on disk).
+// address metadata (e.g. on disk).
 
 #ifndef I18N_ADDRESSINPUT_STORAGE_H_
 #define I18N_ADDRESSINPUT_STORAGE_H_
@@ -25,8 +25,8 @@
 namespace i18n {
 namespace addressinput {
 
-// Stores downloaded validation rules. The data must be allocated on the heap,
-// passing ownership to the called function. Sample usage:
+// Stores address metadata. The data must be allocated on the heap, passing
+// ownership to the called function. Sample usage:
 //
 //    class MyStorage : public Storage {
 //     public:
diff --git a/cpp/include/libaddressinput/supplier.h b/cpp/include/libaddressinput/supplier.h
index fcd64ad..7d079cf 100644
--- a/cpp/include/libaddressinput/supplier.h
+++ b/cpp/include/libaddressinput/supplier.h
@@ -16,7 +16,6 @@
 #define I18N_ADDRESSINPUT_SUPPLIER_H_
 
 #include <libaddressinput/callback.h>
-#include <libaddressinput/util/basictypes.h>
 
 namespace i18n {
 namespace addressinput {
diff --git a/cpp/include/libaddressinput/util/basictypes.h b/cpp/include/libaddressinput/util/basictypes.h
index 763b179..663133f 100644
--- a/cpp/include/libaddressinput/util/basictypes.h
+++ b/cpp/include/libaddressinput/util/basictypes.h
@@ -20,9 +20,8 @@
 #ifndef I18N_ADDRESSINPUT_UTIL_BASICTYPES_H_
 #define I18N_ADDRESSINPUT_UTIL_BASICTYPES_H_
 
-#include <limits.h>         // So we can set the bounds of our types
-#include <stddef.h>         // For size_t
-#include <string.h>         // for memcpy
+#include <climits>         // So we can set the bounds of our types
+#include <cstddef>         // For size_t
 
 #if !defined(_WIN32)
 // stdint.h is part of C99 but MSVC doesn't have it.
diff --git a/cpp/include/libaddressinput/util/scoped_ptr.h b/cpp/include/libaddressinput/util/scoped_ptr.h
index fe15fca..a88c2a9 100644
--- a/cpp/include/libaddressinput/util/scoped_ptr.h
+++ b/cpp/include/libaddressinput/util/scoped_ptr.h
@@ -11,15 +11,14 @@
 // This is an implementation designed to match the anticipated future TR2
 // implementation of the scoped_ptr class and scoped_ptr_malloc (deprecated).
 
-#include <assert.h>
-#include <stddef.h>
-#include <stdlib.h>
-
-#include <algorithm>  // For std::swap().
-
 #include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/template_util.h>
 
+#include <algorithm>  // For std::swap().
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+
 namespace i18n {
 namespace addressinput {
 
diff --git a/cpp/libaddressinput.gypi b/cpp/libaddressinput.gypi
index 8d9030f..e36ee95 100644
--- a/cpp/libaddressinput.gypi
+++ b/cpp/libaddressinput.gypi
@@ -28,7 +28,6 @@
       'src/language.cc',
       'src/localization.cc',
       'src/lookup_key.cc',
-      'src/lookup_key_util.cc',
       'src/null_storage.cc',
       'src/ondemand_supplier.cc',
       'src/ondemand_supply_task.cc',
@@ -40,6 +39,7 @@
       'src/retriever.cc',
       'src/rule.cc',
       'src/rule_retriever.cc',
+      'src/util/cctype_tolower_equal.cc',
       'src/util/json.cc',
       'src/util/md5.cc',
       'src/util/string_compare.cc',
@@ -60,16 +60,13 @@
       'test/address_problem_test.cc',
       'test/address_ui_test.cc',
       'test/address_validator_test.cc',
-      'test/fake_downloader.cc',
-      'test/fake_downloader_test.cc',
       'test/fake_storage.cc',
       'test/fake_storage_test.cc',
       'test/format_element_test.cc',
       'test/language_test.cc',
       'test/localization_test.cc',
       'test/lookup_key_test.cc',
-      'test/lookup_key_util_test.cc',
-      'test/mock_downloader.cc',
+      'test/mock_source.cc',
       'test/null_storage_test.cc',
       'test/ondemand_supply_task_test.cc',
       'test/post_box_matchers_test.cc',
@@ -81,6 +78,8 @@
       'test/rule_retriever_test.cc',
       'test/rule_test.cc',
       'test/supplier_test.cc',
+      'test/testdata_source.cc',
+      'test/testdata_source_test.cc',
       'test/util/json_test.cc',
       'test/util/md5_unittest.cc',
       'test/util/scoped_ptr_unittest.cc',
diff --git a/cpp/res/messages.grdp b/cpp/res/messages.grdp
index 1e1bcf2..7ca2000 100644
--- a/cpp/res/messages.grdp
+++ b/cpp/res/messages.grdp
@@ -85,6 +85,12 @@
     Island
   </message>
   <message
+      name="IDS_LIBADDRESSINPUT_OBLAST"
+      desc="Administrative Area for certain countries (e.g., Russia's
+            Leningrad).">
+    Oblast
+  </message>
+  <message
       name="IDS_LIBADDRESSINPUT_PARISH"
       desc="Administrative Area for certain countries (e.g., Andorra's
             Canillo).">
@@ -107,6 +113,13 @@
     State
   </message>
   <message
+      name="IDS_LIBADDRESSINPUT_ORGANIZATION_LABEL"
+      desc="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.">
+    Organization
+  </message>
+  <message
       name="IDS_LIBADDRESSINPUT_RECIPIENT_LABEL"
       desc="Label for the field for a person's name in an address.">
     Name
diff --git a/cpp/src/address_data.cc b/cpp/src/address_data.cc
index a3549ed..40d3ee7 100644
--- a/cpp/src/address_data.cc
+++ b/cpp/src/address_data.cc
@@ -41,6 +41,7 @@
   &AddressData::sorting_code,
   &AddressData::postal_code,
   NULL,
+  &AddressData::organization,
   &AddressData::recipient
 };
 
@@ -53,6 +54,7 @@
   NULL,
   NULL,
   &AddressData::address_line,
+  NULL,
   NULL
 };
 
@@ -76,9 +78,9 @@
     return IsStringEmpty(value);
   } else {
     const std::vector<std::string>& value = GetRepeatedFieldValue(field);
-    return std::find_if(value.begin(), value.end(),
-                        std::not1(std::ptr_fun(&IsStringEmpty))) ==
-           value.end();
+    return std::find_if(value.begin(),
+                        value.end(),
+                        std::not1(std::ptr_fun(&IsStringEmpty))) == value.end();
   }
 }
 
@@ -104,16 +106,16 @@
 }
 
 bool AddressData::operator==(const AddressData& other) const {
-  return
-      region_code == other.region_code &&
-      address_line == other.address_line &&
-      administrative_area == other.administrative_area &&
-      locality == other.locality &&
-      dependent_locality == other.dependent_locality &&
-      postal_code == other.postal_code &&
-      sorting_code == other.sorting_code &&
-      language_code == other.language_code &&
-      recipient == other.recipient;
+  return region_code == other.region_code &&
+         address_line == other.address_line &&
+         administrative_area == other.administrative_area &&
+         locality == other.locality &&
+         dependent_locality == other.dependent_locality &&
+         postal_code == other.postal_code &&
+         sorting_code == other.sorting_code &&
+         language_code == other.language_code &&
+         organization == other.organization &&
+         recipient == other.recipient;
 }
 
 // static
@@ -144,6 +146,7 @@
   }
 
   o << "language_code: \"" << address.language_code << "\"\n"
+    "organization: \"" << address.organization << "\"\n"
     "recipient: \"" << address.recipient << "\"\n";
 
   return o;
diff --git a/cpp/src/address_field.cc b/cpp/src/address_field.cc
index 9831479..c5c96d8 100644
--- a/cpp/src/address_field.cc
+++ b/cpp/src/address_field.cc
@@ -14,11 +14,11 @@
 
 #include <libaddressinput/address_field.h>
 
+#include <libaddressinput/util/basictypes.h>
+
 #include <cstddef>
 #include <ostream>
 
-#include <libaddressinput/util/basictypes.h>
-
 using i18n::addressinput::AddressField;
 using i18n::addressinput::COUNTRY;
 using i18n::addressinput::RECIPIENT;
@@ -32,6 +32,7 @@
     "SORTING_CODE",
     "POSTAL_CODE",
     "STREET_ADDRESS",
+    "ORGANIZATION",
     "RECIPIENT"
   };
   COMPILE_ASSERT(COUNTRY == 0, bad_base);
diff --git a/cpp/src/address_field_util.cc b/cpp/src/address_field_util.cc
index 1cac289..26de3c0 100644
--- a/cpp/src/address_field_util.cc
+++ b/cpp/src/address_field_util.cc
@@ -40,6 +40,7 @@
   fields.insert(std::make_pair('X', SORTING_CODE));
   fields.insert(std::make_pair('Z', POSTAL_CODE));
   fields.insert(std::make_pair('A', STREET_ADDRESS));
+  fields.insert(std::make_pair('O', ORGANIZATION));
   fields.insert(std::make_pair('N', RECIPIENT));
   return fields;
 }
diff --git a/cpp/src/address_field_util.h b/cpp/src/address_field_util.h
index 62a6b7e..123672b 100644
--- a/cpp/src/address_field_util.h
+++ b/cpp/src/address_field_util.h
@@ -20,11 +20,11 @@
 #include <string>
 #include <vector>
 
-#include "format_element.h"
-
 namespace i18n {
 namespace addressinput {
 
+class FormatElement;
+
 // Clears |fields|, parses |format|, and adds the format address fields to
 // |fields|. The |fields| may also contain NEWLINE elements. For example, parses
 // "%S%C%n%D%X" into {ADMIN_AREA, LOCALITY, NEWLINE, DEPENDENT_LOCALITY,
diff --git a/cpp/src/address_formatter.cc b/cpp/src/address_formatter.cc
index 29f3486..b54cbac 100644
--- a/cpp/src/address_formatter.cc
+++ b/cpp/src/address_formatter.cc
@@ -14,20 +14,22 @@
 
 #include <libaddressinput/address_formatter.h>
 
-#include <strings.h>
-
-#include <algorithm>
-#include <cstddef>
-#include <string>
-#include <vector>
-
 #include <libaddressinput/address_data.h>
 #include <libaddressinput/address_field.h>
+#include <libaddressinput/util/basictypes.h>
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <functional>
+#include <string>
+#include <vector>
 
 #include "format_element.h"
 #include "language.h"
 #include "region_data_constants.h"
 #include "rule.h"
+#include "util/cctype_tolower_equal.h"
 
 namespace i18n {
 namespace addressinput {
@@ -66,15 +68,6 @@
   "uz"
 };
 
-// Case insensitive matcher for language tags.
-struct LanguageMatcher {
-  LanguageMatcher(const std::string& tag) : tag(tag) {}
-  std::string tag;
-  bool operator() (const std::string& s) {
-    return strcasecmp(tag.c_str(), s.c_str()) == 0;
-  }
-};
-
 std::string GetLineSeparatorForLanguage(const std::string& language_tag) {
   Language address_language(language_tag);
 
@@ -87,42 +80,45 @@
   const std::string& base_language = address_language.base;
   if (std::find_if(kLanguagesThatUseSpace,
                    kLanguagesThatUseSpace + arraysize(kLanguagesThatUseSpace),
-                   LanguageMatcher(base_language)) !=
+                   std::bind2nd(EqualToTolowerString(), base_language)) !=
       kLanguagesThatUseSpace + arraysize(kLanguagesThatUseSpace)) {
     return kSpaceSeparator;
-  } else if (std::find_if(kLanguagesThatHaveNoSeparator,
-                          kLanguagesThatHaveNoSeparator +
-                              arraysize(kLanguagesThatHaveNoSeparator),
-                          LanguageMatcher(base_language)) !=
+  } else if (std::find_if(
+                 kLanguagesThatHaveNoSeparator,
+                 kLanguagesThatHaveNoSeparator +
+                     arraysize(kLanguagesThatHaveNoSeparator),
+                 std::bind2nd(EqualToTolowerString(), base_language)) !=
              kLanguagesThatHaveNoSeparator +
                  arraysize(kLanguagesThatHaveNoSeparator)) {
     return "";
-  } else if (std::find_if(kLanguagesThatUseAnArabicComma,
-                          kLanguagesThatUseAnArabicComma +
-                              arraysize(kLanguagesThatUseAnArabicComma),
-                          LanguageMatcher(base_language)) !=
+  } else if (std::find_if(
+                 kLanguagesThatUseAnArabicComma,
+                 kLanguagesThatUseAnArabicComma +
+                     arraysize(kLanguagesThatUseAnArabicComma),
+                 std::bind2nd(EqualToTolowerString(), base_language)) !=
              kLanguagesThatUseAnArabicComma +
                  arraysize(kLanguagesThatUseAnArabicComma)) {
     return kArabicCommaSeparator;
   }
-  // Either the language is a latin-script language, or no language was
+  // Either the language is a Latin-script language, or no language was
   // specified. In the latter case we still return ", " as the most common
   // separator in use. In countries that don't use this, e.g. Thailand,
-  // addresses are often written in latin script where this would still be
+  // addresses are often written in Latin script where this would still be
   // appropriate, so this is a reasonable default in the absence of information.
   return kCommaSeparator;
 }
 
-void CombineLinesForLanguage(
-    const std::vector<std::string>& lines, const std::string& language_tag,
-    std::string *line) {
-  if (lines.size() > 0) {
-    line->assign(lines[0]);
-  }
+void CombineLinesForLanguage(const std::vector<std::string>& lines,
+                             const std::string& language_tag,
+                             std::string* line) {
+  line->clear();
   std::string separator = GetLineSeparatorForLanguage(language_tag);
-  for (std::vector<std::string>::const_iterator it = lines.begin() + 1;
-       it < lines.end(); ++it) {
-    line->append(separator);
+  for (std::vector<std::string>::const_iterator it = lines.begin();
+       it != lines.end();
+       ++it) {
+    if (it != lines.begin()) {
+      line->append(separator);
+    }
     line->append(*it);
   }
 }
@@ -143,36 +139,73 @@
 
   Language language(address_data.language_code);
 
-  // If latinized rules are available and the |language_code| of this address is
-  // explicitly tagged as being Latin, then use the latinized formatting rules.
+  // If Latin-script rules are available and the |language_code| of this address
+  // is explicitly tagged as being Latin, then use the Latin-script formatting
+  // rules.
   const std::vector<FormatElement>& format =
       language.has_latin_script && !rule.GetLatinFormat().empty()
-          ? rule.GetLatinFormat() : rule.GetFormat();
+          ? rule.GetLatinFormat()
+          : rule.GetFormat();
+
+  // Address format without the unnecessary elements (based on which address
+  // fields are empty). We assume all literal strings that are not at the start
+  // or end of a line are separators, and therefore only relevant if the
+  // surrounding fields are filled in. This works with the data we have
+  // currently.
+  std::vector<FormatElement> pruned_format;
+  for (std::vector<FormatElement>::const_iterator
+       element_it = format.begin();
+       element_it != format.end();
+       ++element_it) {
+    // Always keep the newlines.
+    if (element_it->IsNewline() ||
+        // Always keep the non-empty address fields.
+        (element_it->IsField() &&
+         !address_data.IsFieldEmpty(element_it->GetField())) ||
+        // Only keep literals that satisfy these 2 conditions:
+        (!element_it->IsField() &&
+         // (1) Not preceding an empty field.
+         (element_it + 1 == format.end() ||
+          !(element_it + 1)->IsField() ||
+          !address_data.IsFieldEmpty((element_it + 1)->GetField())) &&
+         // (2) Not following a removed field.
+         (element_it == format.begin() ||
+          !(element_it - 1)->IsField() ||
+          (!pruned_format.empty() && pruned_format.back().IsField())))) {
+      pruned_format.push_back(*element_it);
+    }
+  }
 
   std::string line;
-  for (size_t i = 0; i < format.size(); ++i) {
-    FormatElement element = format[i];
-    if (element.IsNewline()) {
+  for (std::vector<FormatElement>::const_iterator
+       element_it = pruned_format.begin();
+       element_it != pruned_format.end();
+       ++element_it) {
+    if (element_it->IsNewline()) {
       if (!line.empty()) {
         lines->push_back(line);
         line.clear();
       }
-    } else if (element.IsField()) {
-      AddressField field = element.GetField();
+    } else if (element_it->IsField()) {
+      AddressField field = element_it->GetField();
       if (field == STREET_ADDRESS) {
         // The field "street address" represents the street address lines of an
         // address, so there can be multiple values.
-        if (!line.empty()) {
-          lines->push_back(line);
-          line.clear();
+        if (!address_data.IsFieldEmpty(field)) {
+          line.append(address_data.address_line.front());
+          if (address_data.address_line.size() > 1U) {
+            lines->push_back(line);
+            line.clear();
+            lines->insert(lines->end(),
+                          address_data.address_line.begin() + 1,
+                          address_data.address_line.end());
+          }
         }
-        lines->insert(lines->end(), address_data.address_line.begin(),
-                      address_data.address_line.end());
       } else {
         line.append(address_data.GetFieldValue(field));
       }
     } else {
-      line.append(element.GetLiteral());
+      line.append(element_it->GetLiteral());
     }
   }
   if (!line.empty()) {
diff --git a/cpp/src/address_input_helper.cc b/cpp/src/address_input_helper.cc
index a8ce92f..c492760 100644
--- a/cpp/src/address_input_helper.cc
+++ b/cpp/src/address_input_helper.cc
@@ -14,15 +14,17 @@
 
 #include <libaddressinput/address_input_helper.h>
 
+#include <libaddressinput/address_data.h>
+#include <libaddressinput/address_field.h>
+#include <libaddressinput/preload_supplier.h>
+#include <libaddressinput/util/basictypes.h>
+
 #include <cassert>
 #include <cstddef>
 #include <string>
 #include <vector>
 
-#include <libaddressinput/address_data.h>
-#include <libaddressinput/address_field.h>
-#include <libaddressinput/preload_supplier.h>
-#include <libaddressinput/util/basictypes.h>
+#include <re2/re2.h>
 
 #include "language.h"
 #include "lookup_key.h"
@@ -97,7 +99,7 @@
 
 AddressInputHelper::AddressInputHelper(PreloadSupplier* supplier)
     : supplier_(supplier) {
-  assert(supplier_ !=  NULL);
+  assert(supplier_ != NULL);
 }
 
 AddressInputHelper::~AddressInputHelper() {
diff --git a/cpp/src/address_metadata.cc b/cpp/src/address_metadata.cc
index 59030ef..c088e0d 100644
--- a/cpp/src/address_metadata.cc
+++ b/cpp/src/address_metadata.cc
@@ -17,7 +17,9 @@
 #include <libaddressinput/address_field.h>
 
 #include <algorithm>
+#include <string>
 
+#include "format_element.h"
 #include "region_data_constants.h"
 #include "rule.h"
 
diff --git a/cpp/src/address_normalizer.cc b/cpp/src/address_normalizer.cc
index e80489d..562203e 100644
--- a/cpp/src/address_normalizer.cc
+++ b/cpp/src/address_normalizer.cc
@@ -20,9 +20,10 @@
 
 #include <cassert>
 #include <cstddef>
+#include <string>
+#include <vector>
 
 #include "lookup_key.h"
-#include "region_data_constants.h"
 #include "rule.h"
 #include "util/string_compare.h"
 
diff --git a/cpp/src/address_problem.cc b/cpp/src/address_problem.cc
index e6cf446..0fade17 100644
--- a/cpp/src/address_problem.cc
+++ b/cpp/src/address_problem.cc
@@ -14,11 +14,11 @@
 
 #include <libaddressinput/address_problem.h>
 
+#include <libaddressinput/util/basictypes.h>
+
 #include <cstddef>
 #include <ostream>
 
-#include <libaddressinput/util/basictypes.h>
-
 using i18n::addressinput::AddressProblem;
 using i18n::addressinput::UNEXPECTED_FIELD;
 using i18n::addressinput::USES_P_O_BOX;
diff --git a/cpp/src/address_ui.cc b/cpp/src/address_ui.cc
index a099335..33f0797 100644
--- a/cpp/src/address_ui.cc
+++ b/cpp/src/address_ui.cc
@@ -24,7 +24,6 @@
 #include <string>
 #include <vector>
 
-#include "address_field_util.h"
 #include "format_element.h"
 #include "grit.h"
 #include "language.h"
@@ -64,6 +63,9 @@
     case STREET_ADDRESS:
       messageId = IDS_LIBADDRESSINPUT_ADDRESS_LINE_1_LABEL;
       break;
+    case ORGANIZATION:
+      messageId = IDS_LIBADDRESSINPUT_ORGANIZATION_LABEL;
+      break;
     case RECIPIENT:
       messageId = IDS_LIBADDRESSINPUT_RECIPIENT_LABEL;
       break;
@@ -99,9 +101,9 @@
   *best_address_language_tag = best_address_language.tag;
 
   const std::vector<FormatElement>& format =
-      !rule.GetLatinFormat().empty() &&
-      best_address_language.has_latin_script
-          ? rule.GetLatinFormat() : rule.GetFormat();
+      !rule.GetLatinFormat().empty() && best_address_language.has_latin_script
+          ? rule.GetLatinFormat()
+          : rule.GetFormat();
 
   // For avoiding showing an input field twice, when the field is displayed
   // twice on an envelope.
@@ -127,8 +129,10 @@
                                 : AddressUiComponent::HINT_SHORT;
     preceded_by_newline = false;
     component.field = format_it->GetField();
-    component.name = GetLabelForField(localization, format_it->GetField(),
-        rule.GetAdminAreaNameMessageId(), rule.GetPostalCodeNameMessageId());
+    component.name = GetLabelForField(localization,
+                                      format_it->GetField(),
+                                      rule.GetAdminAreaNameMessageId(),
+                                      rule.GetPostalCodeNameMessageId());
     result.push_back(component);
   }
 
diff --git a/cpp/src/address_validator.cc b/cpp/src/address_validator.cc
index b3e4aae..8f0c33c 100644
--- a/cpp/src/address_validator.cc
+++ b/cpp/src/address_validator.cc
@@ -14,6 +14,9 @@
 
 #include <libaddressinput/address_validator.h>
 
+#include <cassert>
+#include <cstddef>
+
 #include "validation_task.h"
 
 namespace i18n {
diff --git a/cpp/src/language.cc b/cpp/src/language.cc
index 9e456f0..28817dc 100644
--- a/cpp/src/language.cc
+++ b/cpp/src/language.cc
@@ -32,13 +32,13 @@
   // legacy code generates tags with '_' instead of '-'.
   static const char kSubtagsSeparator = '-';
   static const char kAlternativeSubtagsSeparator = '_';
-  std::replace(tag.begin(), tag.end(), kAlternativeSubtagsSeparator,
-               kSubtagsSeparator);
+  std::replace(
+      tag.begin(), tag.end(), kAlternativeSubtagsSeparator, kSubtagsSeparator);
 
   // OK to use 'tolower' because BCP 47 tags are always in ASCII.
   std::string lowercase = tag;
-  std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(),
-                 tolower);
+  std::transform(
+      lowercase.begin(), lowercase.end(), lowercase.begin(), tolower);
 
   base = lowercase.substr(0, lowercase.find(kSubtagsSeparator));
 
diff --git a/cpp/src/localization.cc b/cpp/src/localization.cc
index 9bb32a5..b544cd9 100644
--- a/cpp/src/localization.cc
+++ b/cpp/src/localization.cc
@@ -21,8 +21,9 @@
 #include <cassert>
 #include <cstddef>
 #include <string>
+#include <vector>
 
-#include "grit.h"
+#include "messages.h"
 #include "region_data_constants.h"
 #include "rule.h"
 #include "util/string_split.h"
@@ -30,10 +31,11 @@
 
 namespace {
 
-void PushBackUrl(std::vector<std::string>& parameters, const std::string url) {
+void PushBackUrl(const std::string& url, std::vector<std::string>* parameters) {
+  assert(parameters != NULL);
   // TODO: HTML-escape the "url".
-  parameters.push_back("<a href=\"" + url + "\">");
-  parameters.push_back("</a>");
+  parameters->push_back("<a href=\"" + url + "\">");
+  parameters->push_back("</a>");
 }
 
 }  // namespace
@@ -136,7 +138,7 @@
           IDS_LIBADDRESSINPUT_MISSING_REQUIRED_POSTAL_CODE_EXAMPLE_AND_URL :
           IDS_LIBADDRESSINPUT_MISSING_REQUIRED_ZIP_CODE_EXAMPLE_AND_URL;
       parameters.push_back(postal_code_example);
-      PushBackUrl(parameters, post_service_url);
+      PushBackUrl(post_service_url, &parameters);
     } else if (!postal_code_example.empty()) {
       message_id = uses_postal_code_as_label ?
           IDS_LIBADDRESSINPUT_MISSING_REQUIRED_POSTAL_CODE_EXAMPLE :
@@ -152,7 +154,7 @@
           IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_POSTAL_CODE_EXAMPLE_AND_URL :
           IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_ZIP_CODE_EXAMPLE_AND_URL;
       parameters.push_back(postal_code_example);
-      PushBackUrl(parameters, post_service_url);
+      PushBackUrl(post_service_url, &parameters);
     } else if (!postal_code_example.empty()) {
       message_id = uses_postal_code_as_label ?
           IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_POSTAL_CODE_EXAMPLE :
@@ -169,7 +171,7 @@
       message_id = uses_postal_code_as_label ?
           IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_POSTAL_CODE_URL :
           IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_ZIP_URL;
-      PushBackUrl(parameters, post_service_url);
+      PushBackUrl(post_service_url, &parameters);
     } else {
       message_id = uses_postal_code_as_label ?
           IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_POSTAL_CODE :
diff --git a/cpp/src/lookup_key.cc b/cpp/src/lookup_key.cc
index b6f73fc..d793a2b 100644
--- a/cpp/src/lookup_key.cc
+++ b/cpp/src/lookup_key.cc
@@ -14,20 +14,23 @@
 
 #include "lookup_key.h"
 
+#include <libaddressinput/address_data.h>
+#include <libaddressinput/address_field.h>
+#include <libaddressinput/util/basictypes.h>
+
+#include <algorithm>
 #include <cassert>
 #include <cstddef>
+#include <functional>
 #include <map>
 #include <string>
 #include <utility>
 #include <vector>
 
-#include <libaddressinput/address_data.h>
-#include <libaddressinput/address_field.h>
-#include <libaddressinput/util/basictypes.h>
-
 #include "language.h"
 #include "region_data_constants.h"
 #include "rule.h"
+#include "util/cctype_tolower_equal.h"
 
 namespace i18n {
 namespace addressinput {
@@ -39,15 +42,6 @@
 const char kData[] = "data";
 const char kUnknown[] = "ZZ";
 
-// Case insensitive matcher for language tags.
-struct LanguageMatcher {
-  LanguageMatcher(const std::string& tag) : tag(tag) { }
-  std::string tag;
-  bool operator() (const std::string& s) {
-    return strcasecmp(tag.c_str(), s.c_str()) == 0;
-  }
-};
-
 // Assume the language_tag has had "Latn" script removed when this is called.
 bool ShouldSetLanguageForKey(const std::string& language_tag,
                              const std::string& region_code) {
@@ -69,10 +63,9 @@
     return false;
   }
   // Finally, only return true if the language is one of the remaining ones.
-  return std::find_if(languages.begin() + 1,
-                      languages.end(),
-                      LanguageMatcher(language_tag))
-      != languages.end();
+  return std::find_if(languages.begin() + 1, languages.end(),
+                      std::bind2nd(EqualToTolowerString(), language_tag)) !=
+         languages.end();
 }
 
 }  // namespace
@@ -105,8 +98,9 @@
     }
   }
   Language address_language(address.language_code);
-  std::string language_tag_no_latn = address_language.has_latin_script ?
-      address_language.base : address_language.tag;
+  std::string language_tag_no_latn = address_language.has_latin_script
+                                         ? address_language.base
+                                         : address_language.tag;
   if (ShouldSetLanguageForKey(language_tag_no_latn, address.region_code)) {
     language_ = language_tag_no_latn;
   }
@@ -117,7 +111,8 @@
   assert(parent.nodes_.size() < arraysize(kHierarchy));
   assert(!child_node.empty());
 
-  nodes_ = parent.nodes_;
+  // Copy its nodes if this isn't the parent object.
+  if (this != &parent) nodes_ = parent.nodes_;
   AddressField child_field = kHierarchy[nodes_.size()];
   nodes_.insert(std::make_pair(child_field, child_node));
 }
diff --git a/cpp/src/lookup_key_util.cc b/cpp/src/lookup_key_util.cc
deleted file mode 100644
index e63e9a5..0000000
--- a/cpp/src/lookup_key_util.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2013 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "lookup_key_util.h"
-
-#include <cassert>
-#include <string>
-
-namespace i18n {
-namespace addressinput {
-
-LookupKeyUtil::LookupKeyUtil(const std::string& validation_data_url)
-    : validation_data_url_(validation_data_url) {
-  assert(validation_data_url_.length() > 0);
-  assert(validation_data_url_[validation_data_url_.length() - 1] == '/');
-}
-
-LookupKeyUtil::~LookupKeyUtil() {}
-
-std::string LookupKeyUtil::GetUrlForKey(const std::string& key) const {
-  return validation_data_url_ + key;
-}
-
-std::string LookupKeyUtil::GetKeyForUrl(const std::string& url) const {
-  return IsValidationDataUrl(url) ? url.substr(validation_data_url_.length())
-                                  : std::string();
-}
-
-bool LookupKeyUtil::IsValidationDataUrl(const std::string& url) const {
-  return
-      url.compare(0, validation_data_url_.length(), validation_data_url_) == 0;
-}
-
-}  // namespace addressinput
-}  // namespace i18n
diff --git a/cpp/src/lookup_key_util.h b/cpp/src/lookup_key_util.h
deleted file mode 100644
index 4996c1c..0000000
--- a/cpp/src/lookup_key_util.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (C) 2013 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// Functions for working with lookup keys. The lookup keys are strings that
-// identify serialized validation rules.
-
-#ifndef I18N_ADDRESSINPUT_LOOKUP_KEY_UTIL_H_
-#define I18N_ADDRESSINPUT_LOOKUP_KEY_UTIL_H_
-
-#include <string>
-
-namespace i18n {
-namespace addressinput {
-
-// Utility functions for lookup keys. Sample usage:
-//    LookupKeyUtil lookup_keys("https://i18napis.appspot.com/ssl-address/");
-//    Download(lookup_keys.GetUrlForKey("data/US"));
-class LookupKeyUtil {
- public:
-  // Builds a lookup key utility for the |validation_data_url| parameter. The
-  // parameter must end with a '/'.
-  explicit LookupKeyUtil(const std::string& validation_data_url);
-  ~LookupKeyUtil();
-
-  // Returns the URL where the |key| can be retrieved. For example, returns
-  // "https://i18napis.appspot.com/ssl-address/data/US" for input "data/US".
-  // Assumes that the input string is a valid URL segment.
-  std::string GetUrlForKey(const std::string& key) const;
-
-  // Returns the key for the |url|. For example, returns "data/US" for
-  // "https://i18napis.appspot.com/ssl-address/data/US". If the |url| does not
-  // start with |validation_data_url| that was passed to the constructor, then
-  // returns an empty string. (This can happen if the user of the library
-  // returns a bad URL in their Downloader implementation.)
-  std::string GetKeyForUrl(const std::string& url) const;
-
-  // Returns true if the |url| starts with |validation_data_url| that was passed
-  // to the constructor.
-  bool IsValidationDataUrl(const std::string& url) const;
-
- private:
-  const std::string validation_data_url_;
-};
-
-}  // namespace addressinput
-}  // namespace i18n
-
-#endif  // I18N_ADDRESSINPUT_LOOKUP_KEY_UTIL_H_
diff --git a/cpp/src/ondemand_supplier.cc b/cpp/src/ondemand_supplier.cc
index 9228570..fa3f88e 100644
--- a/cpp/src/ondemand_supplier.cc
+++ b/cpp/src/ondemand_supplier.cc
@@ -19,8 +19,6 @@
 #include <map>
 #include <string>
 
-#include <libaddressinput/util/scoped_ptr.h>
-
 #include "lookup_key.h"
 #include "ondemand_supply_task.h"
 #include "region_data_constants.h"
@@ -30,10 +28,8 @@
 namespace i18n {
 namespace addressinput {
 
-OndemandSupplier::OndemandSupplier(const std::string& validation_data_url,
-                                   const Downloader* downloader,
-                                   Storage* storage)
-    : retriever_(new Retriever(validation_data_url, downloader, storage)) {
+OndemandSupplier::OndemandSupplier(const Source* source, Storage* storage)
+    : retriever_(new Retriever(source, storage)) {
 }
 
 OndemandSupplier::~OndemandSupplier() {
diff --git a/cpp/src/ondemand_supply_task.cc b/cpp/src/ondemand_supply_task.cc
index ab92746..a4f6a12 100644
--- a/cpp/src/ondemand_supply_task.cc
+++ b/cpp/src/ondemand_supply_task.cc
@@ -14,6 +14,11 @@
 
 #include "ondemand_supply_task.h"
 
+#include <libaddressinput/address_field.h>
+#include <libaddressinput/callback.h>
+#include <libaddressinput/supplier.h>
+#include <libaddressinput/util/basictypes.h>
+
 #include <algorithm>
 #include <cassert>
 #include <cstddef>
@@ -22,12 +27,6 @@
 #include <string>
 #include <utility>
 
-#include <libaddressinput/address_field.h>
-#include <libaddressinput/callback.h>
-#include <libaddressinput/supplier.h>
-#include <libaddressinput/util/basictypes.h>
-#include <libaddressinput/util/scoped_ptr.h>
-
 #include "lookup_key.h"
 #include "retriever.h"
 #include "rule.h"
@@ -64,7 +63,7 @@
   } else {
     // When the final pending rule has been retrieved, the retrieved_ callback,
     // implemented by Load(), will finish by calling Loaded(), which will finish
-    // by delete'ing this RuleHierarchy object. So after the final call to
+    // by delete'ing this OndemandSupplyTask object. So after the final call to
     // retriever.Retrieve() no attributes of this object can be accessed (as the
     // object then no longer will exist, if the final callback has finished by
     // then), and the condition statement of the loop must therefore not use the
@@ -82,21 +81,20 @@
 void OndemandSupplyTask::Load(bool success,
                               const std::string& key,
                               const std::string& data) {
+  size_t depth = std::count(key.begin(), key.end(), '/') - 1;
+  assert(depth < arraysize(LookupKey::kHierarchy));
+
   // Sanity check: This key should be present in the set of pending requests.
   size_t status = pending_.erase(key);
   assert(status == 1);  // There will always be one item erased from the set.
   (void)status;  // Prevent unused variable if assert() is optimized away.
 
-  size_t depth = std::count(key.begin(), key.end(), '/') - 1;
-  assert(depth < arraysize(LookupKey::kHierarchy));
-  AddressField field = LookupKey::kHierarchy[depth];
-
   if (success) {
     // The address metadata server will return the empty JSON "{}" when it
     // successfully performed a lookup, but didn't find any data for that key.
     if (data != "{}") {
       Rule* rule = new Rule;
-      if (field == COUNTRY) {
+      if (LookupKey::kHierarchy[depth] == COUNTRY) {
         // All rules on the COUNTRY level inherit from the default rule.
         rule->CopyFrom(Rule::GetDefault());
       }
diff --git a/cpp/src/ondemand_supply_task.h b/cpp/src/ondemand_supply_task.h
index 61e3567..45b33c9 100644
--- a/cpp/src/ondemand_supply_task.h
+++ b/cpp/src/ondemand_supply_task.h
@@ -29,7 +29,6 @@
 namespace addressinput {
 
 class LookupKey;
-class Retriever;
 class Rule;
 
 // An OndemandSupplyTask object encapsulates the information necessary to
diff --git a/cpp/src/post_box_matchers.cc b/cpp/src/post_box_matchers.cc
index 1edd8b3..f1ad6dd 100644
--- a/cpp/src/post_box_matchers.cc
+++ b/cpp/src/post_box_matchers.cc
@@ -20,12 +20,12 @@
 #include <utility>
 #include <vector>
 
+#include <re2/re2.h>
+
 #include "language.h"
 #include "rule.h"
 #include "util/re2ptr.h"
 
-#include <re2/re2.h>
-
 namespace i18n {
 namespace addressinput {
 
@@ -97,7 +97,7 @@
   return matchers;
 }
 
-} // namespace
+}  // namespace
 
 // static
 std::vector<const RE2ptr*> PostBoxMatchers::GetMatchers(
diff --git a/cpp/src/post_box_matchers.h b/cpp/src/post_box_matchers.h
index 8f9f44b..9924a2c 100644
--- a/cpp/src/post_box_matchers.h
+++ b/cpp/src/post_box_matchers.h
@@ -17,19 +17,24 @@
 #ifndef I18N_ADDRESSINPUT_POST_BOX_MATCHERS_H_
 #define I18N_ADDRESSINPUT_POST_BOX_MATCHERS_H_
 
+#include <libaddressinput/util/basictypes.h>
+
 #include <vector>
 
 namespace i18n {
 namespace addressinput {
 
-class RE2ptr;
 class Rule;
+struct RE2ptr;
 
 class PostBoxMatchers {
  public:
   // Returns pointers to RE2 regular expression objects to test address lines
   // for those languages that are relevant for |country_rule|.
   static std::vector<const RE2ptr*> GetMatchers(const Rule& country_rule);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PostBoxMatchers);
 };
 
 }  // namespace addressinput
diff --git a/cpp/src/preload_supplier.cc b/cpp/src/preload_supplier.cc
index 31325bd..79119bd 100644
--- a/cpp/src/preload_supplier.cc
+++ b/cpp/src/preload_supplier.cc
@@ -32,7 +32,6 @@
 #include <utility>
 #include <vector>
 
-#include "language.h"
 #include "lookup_key.h"
 #include "region_data_constants.h"
 #include "retriever.h"
@@ -53,15 +52,11 @@
  public:
   result_type operator()(const first_argument_type& a,
                          const second_argument_type& b) const {
+    static const StringCompare kStringCompare;
     return kStringCompare.NaturalLess(a, b);
   }
-
- private:
-  static const StringCompare kStringCompare;
 };
 
-const StringCompare IndexLess::kStringCompare;
-
 }  // namespace
 
 class IndexMap : public std::map<std::string, const Rule*, IndexLess> {};
@@ -77,16 +72,19 @@
          const Retriever& retriever,
          std::set<std::string>* pending,
          IndexMap* rule_index,
-         std::vector<const Rule*>* rule_storage)
+         std::vector<const Rule*>* rule_storage,
+         std::map<std::string, const Rule*>* region_rules)
       : region_code_(region_code),
         loaded_(loaded),
         pending_(pending),
         rule_index_(rule_index),
         rule_storage_(rule_storage),
+        region_rules_(region_rules),
         retrieved_(BuildCallback(this, &Helper::OnRetrieved)) {
     assert(pending_ != NULL);
     assert(rule_index_ != NULL);
     assert(rule_storage_ != NULL);
+    assert(region_rules_ != NULL);
     assert(retrieved_ != NULL);
     pending_->insert(key);
     retriever.Retrieve(key, *retrieved_);
@@ -105,8 +103,17 @@
     (void)status;  // Prevent unused variable if assert() is optimized away.
 
     Json json;
+    std::string id;
     std::vector<const Rule*> sub_rules;
 
+    IndexMap::iterator last_index_it = rule_index_->end();
+    IndexMap::iterator last_latin_it = rule_index_->end();
+    std::map<std::string, const Rule*>::iterator last_region_it =
+        region_rules_->end();
+
+    IndexMap::const_iterator hints[arraysize(LookupKey::kHierarchy) - 1];
+    std::fill(hints, hints + arraysize(hints), rule_index_->end());
+
     if (!success) {
       goto callback;
     }
@@ -116,20 +123,17 @@
       goto callback;
     }
 
-    for (std::vector<std::string>::const_iterator
-         it = json.GetKeys().begin(); it != json.GetKeys().end(); ++it) {
-      if (!json.HasDictionaryValueForKey(*it)) {
+    for (std::vector<const Json*>::const_iterator
+         it = json.GetSubDictionaries().begin();
+         it != json.GetSubDictionaries().end();
+         ++it) {
+      const Json* value = *it;
+      assert(value != NULL);
+      if (!value->GetStringValueForKey("id", &id)) {
         success = false;
         goto callback;
       }
-      const Json& value = json.GetDictionaryValueForKey(*it);
-
-      if (!value.HasStringValueForKey("id")) {
-        success = false;
-        goto callback;
-      }
-      const std::string& id = value.GetStringValueForKey("id");
-      assert(*it == id);  // Sanity check.
+      assert(!id.empty());
 
       size_t depth = std::count(id.begin(), id.end(), '/') - 1;
       assert(depth < arraysize(LookupKey::kHierarchy));
@@ -140,7 +144,7 @@
         // All rules on the COUNTRY level inherit from the default rule.
         rule->CopyFrom(Rule::GetDefault());
       }
-      rule->ParseJsonRule(value);
+      rule->ParseJsonRule(*value);
       assert(id == rule->GetId());  // Sanity check.
 
       rule_storage_->push_back(rule);
@@ -148,11 +152,15 @@
         sub_rules.push_back(rule);
       }
 
-      // Add the ID of this Rule object to the rule index.
-      std::pair<IndexMap::iterator, bool> result =
-          rule_index_->insert(std::make_pair(id, rule));
-      assert(result.second);
-      (void)result;  // Prevent unused variable if assert() is optimized away.
+      // Add the ID of this Rule object to the rule index with natural string
+      // comparison for keys.
+      last_index_it =
+          rule_index_->insert(last_index_it, std::make_pair(id, rule));
+
+      // Add the ID of this Rule object to the region-specific rule index with
+      // exact string comparison for keys.
+      last_region_it =
+          region_rules_->insert(last_region_it, std::make_pair(id, rule));
 
       ++rule_count;
     }
@@ -184,9 +192,12 @@
         }
         parent_id.resize(pos);
 
-        IndexMap::const_iterator jt = rule_index_->find(parent_id);
-        assert(jt != rule_index_->end());
-        hierarchy.push(jt->second);
+        IndexMap::const_iterator* const hint = &hints[hierarchy.size() - 1];
+        if (*hint == rule_index_->end() || (*hint)->first != parent_id) {
+          *hint = rule_index_->find(parent_id);
+        }
+        assert(*hint != rule_index_->end());
+        hierarchy.push((*hint)->second);
       }
 
       std::string human_id((*it)->GetId().substr(0, sizeof "data/ZZ" - 1));
@@ -222,13 +233,15 @@
         }
       }
 
-      rule_index_->insert(std::make_pair(human_id, *it));
+      last_index_it =
+          rule_index_->insert(last_index_it, std::make_pair(human_id, *it));
 
       // Add the Latin script ID, if a Latin script name could be found for
       // every part of the ID.
       if (std::count(human_id.begin(), human_id.end(), '/') ==
           std::count(latin_id.begin(), latin_id.end(), '/')) {
-        rule_index_->insert(std::make_pair(latin_id, *it));
+        last_latin_it =
+            rule_index_->insert(last_latin_it, std::make_pair(latin_id, *it));
       }
     }
 
@@ -242,6 +255,7 @@
   std::set<std::string>* const pending_;
   IndexMap* const rule_index_;
   std::vector<const Rule*>* const rule_storage_;
+  std::map<std::string, const Rule*>* const region_rules_;
   const scoped_ptr<const Retriever::Callback> retrieved_;
 
   DISALLOW_COPY_AND_ASSIGN(Helper);
@@ -257,13 +271,12 @@
 
 }  // namespace
 
-PreloadSupplier::PreloadSupplier(const std::string& validation_data_url,
-                                 const Downloader* downloader,
-                                 Storage* storage)
-    : retriever_(new Retriever(validation_data_url, downloader, storage)),
+PreloadSupplier::PreloadSupplier(const Source* source, Storage* storage)
+    : retriever_(new Retriever(source, storage)),
       pending_(),
       rule_index_(new IndexMap),
-      rule_storage_() {}
+      rule_storage_(),
+      region_rules_() {}
 
 PreloadSupplier::~PreloadSupplier() {
   for (std::vector<const Rule*>::const_iterator
@@ -308,7 +321,14 @@
       *retriever_,
       &pending_,
       rule_index_.get(),
-      &rule_storage_);
+      &rule_storage_,
+      &region_rules_[region_code]);
+}
+
+const std::map<std::string, const Rule*>& PreloadSupplier::GetRulesForRegion(
+    const std::string& region_code) const {
+  assert(IsLoaded(region_code));
+  return region_rules_.find(region_code)->second;
 }
 
 bool PreloadSupplier::IsLoaded(const std::string& region_code) const {
diff --git a/cpp/src/region_data.cc b/cpp/src/region_data.cc
index f5f0275..798501e 100644
--- a/cpp/src/region_data.cc
+++ b/cpp/src/region_data.cc
@@ -14,7 +14,6 @@
 
 #include <libaddressinput/region_data.h>
 
-#include <cassert>
 #include <cstddef>
 #include <string>
 #include <vector>
diff --git a/cpp/src/region_data_builder.cc b/cpp/src/region_data_builder.cc
index 82d223c..b600d09 100644
--- a/cpp/src/region_data_builder.cc
+++ b/cpp/src/region_data_builder.cc
@@ -17,6 +17,7 @@
 #include <libaddressinput/address_data.h>
 #include <libaddressinput/preload_supplier.h>
 #include <libaddressinput/region_data.h>
+#include <libaddressinput/util/basictypes.h>
 
 #include <cassert>
 #include <cstddef>
@@ -34,56 +35,91 @@
 
 namespace {
 
-// Does not take ownership of |supplier| or |parent_region|, neither of which is
-// allowed to be NULL.
-void BuildRegionTreeRecursively(PreloadSupplier* supplier,
-                                const LookupKey& parent_key,
-                                RegionData* parent_region,
-                                const std::vector<std::string>& keys,
-                                bool prefer_latin_name) {
-  assert(supplier != NULL);
+// The maximum depth of lookup keys.
+static const size_t kLookupKeysMaxDepth = arraysize(LookupKey::kHierarchy) - 1;
+
+// Does not take ownership of |parent_region|, which is not allowed to be NULL.
+void BuildRegionTreeRecursively(
+    const std::map<std::string, const Rule*>& rules,
+    std::map<std::string, const Rule*>::const_iterator hint,
+    const LookupKey& parent_key,
+    RegionData* parent_region,
+    const std::vector<std::string>& keys,
+    bool prefer_latin_name,
+    size_t region_max_depth) {
   assert(parent_region != NULL);
 
   LookupKey lookup_key;
   for (std::vector<std::string>::const_iterator key_it = keys.begin();
        key_it != keys.end(); ++key_it) {
     lookup_key.FromLookupKey(parent_key, *key_it);
-    const Rule* rule = supplier->GetRule(lookup_key);
-    if (rule == NULL) {
-      return;
+    const std::string& lookup_key_string =
+        lookup_key.ToKeyString(kLookupKeysMaxDepth);
+
+    ++hint;
+    if (hint == rules.end() || hint->first != lookup_key_string) {
+      hint = rules.find(lookup_key_string);
+      if (hint == rules.end()) {
+        return;
+      }
     }
+
+    const Rule* rule = hint->second;
+    assert(rule != NULL);
+
     const std::string& local_name = rule->GetName().empty()
         ? *key_it : rule->GetName();
     const std::string& name =
         prefer_latin_name && !rule->GetLatinName().empty()
             ? rule->GetLatinName() : local_name;
     RegionData* region = parent_region->AddSubRegion(*key_it, name);
-    if (!rule->GetSubKeys().empty()) {
-      BuildRegionTreeRecursively(supplier, lookup_key, region,
-                                 rule->GetSubKeys(), prefer_latin_name);
+
+    if (!rule->GetSubKeys().empty() &&
+        region_max_depth > parent_key.GetDepth()) {
+      BuildRegionTreeRecursively(rules,
+                                 hint,
+                                 lookup_key,
+                                 region,
+                                 rule->GetSubKeys(),
+                                 prefer_latin_name,
+                                 region_max_depth);
     }
   }
 }
 
-// Does not take ownership of |supplier|, which cannot be NULL. The caller owns
-// the result.
-RegionData* BuildRegion(PreloadSupplier* supplier,
+// The caller owns the result.
+RegionData* BuildRegion(const std::map<std::string, const Rule*>& rules,
                         const std::string& region_code,
                         const Language& language) {
-  assert(supplier != NULL);
-
   AddressData address;
   address.region_code = region_code;
 
   LookupKey lookup_key;
   lookup_key.FromAddress(address);
 
-  const Rule* const rule = supplier->GetRule(lookup_key);
+  std::map<std::string, const Rule*>::const_iterator hint =
+      rules.find(lookup_key.ToKeyString(kLookupKeysMaxDepth));
+  assert(hint != rules.end());
+
+  const Rule* rule = hint->second;
   assert(rule != NULL);
 
   RegionData* region = new RegionData(region_code);
-  BuildRegionTreeRecursively(supplier, lookup_key, region,
-                             rule->GetSubKeys(), language.has_latin_script);
+
+  // If there're sub-keys for field X, but field X is not used in this region
+  // code, then these sub-keys are skipped over. For example, CH has sub-keys
+  // for field ADMIN_AREA, but CH does not use ADMIN_AREA field.
+  size_t region_max_depth =
+      RegionDataConstants::GetMaxLookupKeyDepth(region_code);
+  if (region_max_depth > 0) {
+    BuildRegionTreeRecursively(rules,
+                               hint,
+                               lookup_key,
+                               region,
+                               rule->GetSubKeys(),
+                               language.has_latin_script,
+                               region_max_depth);
+  }
 
   return region;
 }
@@ -127,17 +163,23 @@
   Rule rule;
   rule.ParseSerializedRule(RegionDataConstants::GetRegionData(region_code));
   static const Language kUndefinedLanguage("und");
-  const Language& best_language = rule.GetLanguages().empty()
-      ? kUndefinedLanguage
-      : ChooseBestAddressLanguage(rule, Language(ui_language_tag));
+  const Language& best_language =
+      rule.GetLanguages().empty()
+          ? kUndefinedLanguage
+          : ChooseBestAddressLanguage(rule, Language(ui_language_tag));
   *best_region_tree_language_tag = best_language.tag;
 
   LanguageRegionMap::const_iterator language_it =
       region_it->second->find(best_language.tag);
   if (language_it == region_it->second->end()) {
-    language_it = region_it->second->insert(std::make_pair(
-        best_language.tag,
-        BuildRegion(supplier_, region_code, best_language))).first;
+    const std::map<std::string, const Rule*>& rules =
+        supplier_->GetRulesForRegion(region_code);
+    language_it =
+        region_it->second->insert(std::make_pair(best_language.tag,
+                                                 BuildRegion(rules,
+                                                             region_code,
+                                                             best_language)))
+            .first;
   }
 
   return *language_it->second;
diff --git a/cpp/src/region_data_constants.cc b/cpp/src/region_data_constants.cc
index cabee28..e21d4b8 100644
--- a/cpp/src/region_data_constants.cc
+++ b/cpp/src/region_data_constants.cc
@@ -16,6 +16,9 @@
 
 #include "region_data_constants.h"
 
+#include <libaddressinput/address_field.h>
+#include <libaddressinput/util/basictypes.h>
+
 #include <algorithm>
 #include <cstddef>
 #include <map>
@@ -24,10 +27,8 @@
 #include <utility>
 #include <vector>
 
-#include <libaddressinput/address_field.h>
-#include <libaddressinput/util/basictypes.h>
-
 #include "address_field_util.h"
+#include "format_element.h"
 #include "lookup_key.h"
 
 namespace i18n {
@@ -43,9 +44,8 @@
       "\"languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("AD", "{"
-      "\"fmt\":\"%N%n%O%n%A%n%Z %S\","
-      "\"require\":\"AS\","
-      "\"state_name_type\":\"parish\","
+      "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
+      "\"require\":\"A\","
       "\"zipex\":\"AD100,AD501,AD700\","
       "\"posturl\":\"http://www.correos.es/comun/CodigosPostales/1010_s-CodPostal.asp\?Provincia=\","
       "\"languages\":\"ca\""
@@ -119,7 +119,7 @@
       "\"languages\":\"nl~pap\""
       "}"));
   region_data.insert(std::make_pair("AX", "{"
-      "\"fmt\":\"%O%n%N%n%A%nAX-%Z %C%n\u00c5LAND\","
+      "\"fmt\":\"%O%n%N%n%A%nAX-%Z %C%n\\u00c5LAND\","
       "\"require\":\"ACZ\","
       "\"zipex\":\"22150,22550,22240,22710,22270,22730,22430\","
       "\"posturl\":\"http://www.posten.ax/department.con\?iPage=123\","
@@ -329,7 +329,7 @@
       "\"languages\":\"ar~fr\""
       "}"));
   region_data.insert(std::make_pair("DK", "{"
-      "\"fmt\":\"%O%n%N%n%A%n%Z %C\","
+      "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
       "\"require\":\"ACZ\","
       "\"zipex\":\"8660,1566\","
       "\"posturl\":\"http://www.postdanmark.dk/da/Privat/Kundeservice/postnummerkort/Sider/Find-postnummer.aspx\","
@@ -634,7 +634,7 @@
       "\"languages\":\"ar\""
       "}"));
   region_data.insert(std::make_pair("JP", "{"
-      "\"fmt\":\"\u3012%Z%n%S%C%n%A%n%O%n%N\","
+      "\"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\","
       "\"state_name_type\":\"prefecture\","
@@ -1062,8 +1062,9 @@
       "\"languages\":\"sr-Cyrl~sr-Latn\""
       "}"));
   region_data.insert(std::make_pair("RU", "{"
-      "\"fmt\":\"%Z %C  %n%A%n%O%n%N\","
+      "\"fmt\":\"%N%n%O%n%A%n%C%n%S%n%Z\","
       "\"require\":\"ACZ\","
+      "\"state_name_type\":\"oblast\","
       "\"zipex\":\"125075,247112,103375\","
       "\"posturl\":\"http://info.russianpost.ru/servlet/department\","
       "\"languages\":\"ru\""
@@ -1242,7 +1243,9 @@
       "\"languages\":\"sw~en\""
       "}"));
   region_data.insert(std::make_pair("UA", "{"
-      "\"fmt\":\"%Z %C%n%A%n%O%n%N\","
+      "\"fmt\":\"%N%n%O%n%A%n%C%n%S%n%Z\","
+      "\"require\":\"ACZ\","
+      "\"state_name_type\":\"oblast\","
       "\"zipex\":\"15432,01055,01001\","
       "\"posturl\":\"http://services.ukrposhta.com/postindex_new/\","
       "\"languages\":\"uk~ru\""
@@ -1396,8 +1399,10 @@
 
 std::vector<std::string> InitRegionCodes() {
   std::vector<std::string> region_codes(GetAllRegionData().size());
-  std::transform(GetAllRegionData().begin(), GetAllRegionData().end(),
-                 region_codes.begin(), SelectFirst());
+  std::transform(GetAllRegionData().begin(),
+                 GetAllRegionData().end(),
+                 region_codes.begin(),
+                 SelectFirst());
   return region_codes;
 }
 
diff --git a/cpp/src/region_data_constants.h b/cpp/src/region_data_constants.h
index 7a2c133..4159e72 100644
--- a/cpp/src/region_data_constants.h
+++ b/cpp/src/region_data_constants.h
@@ -15,6 +15,8 @@
 #ifndef I18N_ADDRESSINPUT_REGION_DATA_CONSTANTS_H_
 #define I18N_ADDRESSINPUT_REGION_DATA_CONSTANTS_H_
 
+#include <libaddressinput/util/basictypes.h>
+
 #include <cstddef>
 #include <string>
 #include <vector>
@@ -29,6 +31,9 @@
   static const std::string& GetRegionData(const std::string& region_code);
   static const std::string& GetDefaultRegionData();
   static size_t GetMaxLookupKeyDepth(const std::string& region_code);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RegionDataConstants);
 };
 
 }  // namespace addressinput
diff --git a/cpp/src/retriever.cc b/cpp/src/retriever.cc
index 8fa76b7..151b74d 100644
--- a/cpp/src/retriever.cc
+++ b/cpp/src/retriever.cc
@@ -15,7 +15,7 @@
 #include "retriever.h"
 
 #include <libaddressinput/callback.h>
-#include <libaddressinput/downloader.h>
+#include <libaddressinput/source.h>
 #include <libaddressinput/storage.h>
 #include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
@@ -24,7 +24,6 @@
 #include <cstddef>
 #include <string>
 
-#include "lookup_key_util.h"
 #include "validating_storage.h"
 
 namespace i18n {
@@ -37,14 +36,12 @@
   // Does not take ownership of its parameters.
   Helper(const std::string& key,
          const Retriever::Callback& retrieved,
-         const LookupKeyUtil& lookup_key_util,
-         const Downloader& downloader,
+         const Source& source,
          ValidatingStorage* storage)
       : retrieved_(retrieved),
-        lookup_key_util_(lookup_key_util),
-        downloader_(downloader),
+        source_(source),
         storage_(storage),
-        downloaded_(BuildCallback(this, &Helper::OnDownloaded)),
+        fresh_data_ready_(BuildCallback(this, &Helper::OnFreshDataReady)),
         validated_data_ready_(
             BuildCallback(this, &Helper::OnValidatedDataReady)),
         stale_data_() {
@@ -68,13 +65,14 @@
       if (data != NULL && !data->empty()) {
         stale_data_ = *data;
       }
-      downloader_.Download(lookup_key_util_.GetUrlForKey(key), *downloaded_);
+      source_.Get(key, *fresh_data_ready_);
     }
     delete data;
   }
 
-  void OnDownloaded(bool success, const std::string& url, std::string* data) {
-    const std::string& key = lookup_key_util_.GetKeyForUrl(url);
+  void OnFreshDataReady(bool success,
+                        const std::string& key,
+                        std::string* data) {
     if (success) {
       assert(data != NULL);
       retrieved_(true, key, *data);
@@ -92,11 +90,10 @@
   }
 
   const Retriever::Callback& retrieved_;
-  const LookupKeyUtil& lookup_key_util_;
-  const Downloader& downloader_;
+  const Source& source_;
   ValidatingStorage* storage_;
-  scoped_ptr<Downloader::Callback> downloaded_;
-  scoped_ptr<Storage::Callback> validated_data_ready_;
+  const scoped_ptr<const Source::Callback> fresh_data_ready_;
+  const scoped_ptr<const Storage::Callback> validated_data_ready_;
   std::string stale_data_;
 
   DISALLOW_COPY_AND_ASSIGN(Helper);
@@ -104,21 +101,17 @@
 
 }  // namespace
 
-Retriever::Retriever(const std::string& validation_data_url,
-                     const Downloader* downloader,
-                     Storage* storage)
-    : lookup_key_util_(validation_data_url),
-      downloader_(downloader),
-      storage_(new ValidatingStorage(storage)) {
+Retriever::Retriever(const Source* source, Storage* storage)
+    : source_(source), storage_(new ValidatingStorage(storage)) {
+  assert(source_ != NULL);
   assert(storage_ != NULL);
-  assert(downloader_ != NULL);
 }
 
 Retriever::~Retriever() {}
 
 void Retriever::Retrieve(const std::string& key,
                          const Callback& retrieved) const {
-  new Helper(key, retrieved, lookup_key_util_, *downloader_, storage_.get());
+  new Helper(key, retrieved, *source_, storage_.get());
 }
 
 }  // namespace addressinput
diff --git a/cpp/src/retriever.h b/cpp/src/retriever.h
index 17d17ec..4bf27a5 100644
--- a/cpp/src/retriever.h
+++ b/cpp/src/retriever.h
@@ -23,46 +23,40 @@
 
 #include <string>
 
-#include "lookup_key_util.h"
-
 namespace i18n {
 namespace addressinput {
 
-class Downloader;
+class Source;
 class Storage;
 class ValidatingStorage;
 
 // Retrieves data. Sample usage:
+//    Source* source = ...;
 //    Storage* storage = ...;
-//    Downloader* downloader = ...;
-//    Retriever retriever("https://i18napis.appspot.com/ssl-address/",
-//                        downloader, storage);
-//    scoped_ptr<Retriever::Callback> retrieved(BuildCallback(
-//        this, &MyClass::OnDataRetrieved));
+//    Retriever retriever(source, storage);
+//    const scoped_ptr<const Retriever::Callback> retrieved(
+//        BuildCallback(this, &MyClass::OnDataRetrieved));
 //    retriever.Retrieve("data/CA/AB--fr", *retrieved);
 class Retriever {
  public:
   typedef i18n::addressinput::Callback<const std::string&,
                                        const std::string&> Callback;
 
-  // Takes ownership of |downloader| and |storage|.
-  Retriever(const std::string& validation_data_url,
-            const Downloader* downloader,
-            Storage* storage);
+  // Takes ownership of |source| and |storage|.
+  Retriever(const Source* source, Storage* storage);
   ~Retriever();
 
   // Retrieves the data for |key| and invokes the |retrieved| callback. Checks
-  // for the data in storage first. If storage does not have the data for |key|,
-  // then downloads the data and places it in storage. If the data in storage is
-  // corrupted, then it's discarded and redownloaded. If the data is stale, then
-  // it's redownloaded. If the download fails, then stale data will be returned
-  // this one time. The next call to Retrieve() will attempt to download fresh
-  // data again.
+  // for the data in |storage_| first. If storage does not have the data for
+  // |key|, then gets the data from |source_| and places it in storage. If the
+  // data in storage is corrupted, then it's discarded and requested anew. If
+  // the data is stale, then it's requested anew. If the request fails, then
+  // stale data will be returned this one time. Any subsequent call to
+  // Retrieve() will attempt to get fresh data again.
   void Retrieve(const std::string& key, const Callback& retrieved) const;
 
  private:
-  const LookupKeyUtil lookup_key_util_;
-  scoped_ptr<const Downloader> downloader_;
+  scoped_ptr<const Source> source_;
   scoped_ptr<ValidatingStorage> storage_;
 
   DISALLOW_COPY_AND_ASSIGN(Retriever);
diff --git a/cpp/src/rule.cc b/cpp/src/rule.cc
index e25142f..7ab84e5 100644
--- a/cpp/src/rule.cc
+++ b/cpp/src/rule.cc
@@ -14,14 +14,16 @@
 
 #include "rule.h"
 
-#include <libaddressinput/address_field.h>
-
+#include <cassert>
 #include <cstddef>
 #include <map>
 #include <string>
 #include <utility>
 
+#include <re2/re2.h>
+
 #include "address_field_util.h"
+#include "format_element.h"
 #include "grit.h"
 #include "messages.h"
 #include "region_data_constants.h"
@@ -29,8 +31,6 @@
 #include "util/re2ptr.h"
 #include "util/string_split.h"
 
-#include <re2/re2.h>
-
 namespace i18n {
 namespace addressinput {
 
@@ -38,20 +38,6 @@
 
 typedef std::map<std::string, int> NameMessageIdMap;
 
-const char kAdminAreaNameTypeKey[] = "state_name_type";
-const char kFormatKey[] = "fmt";
-const char kIdKey[] = "id";
-const char kLanguagesKey[] = "languages";
-const char kLatinFormatKey[] = "lfmt";
-const char kLatinNameKey[] = "lname";
-const char kNameKey[] = "name";
-const char kPostalCodeNameTypeKey[] = "zip_name_type";
-const char kRequireKey[] = "require";
-const char kSubKeysKey[] = "sub_keys";
-const char kZipKey[] = "zip";
-const char kPostalCodeExampleKey[] = "zipex";
-const char kPostServiceUrlKey[] = "posturl";
-
 // Used as a separator in a list of items. For example, the list of supported
 // languages can be "de~fr~it".
 const char kSeparator = '~';
@@ -73,6 +59,8 @@
   message_ids.insert(std::make_pair(
       "island", IDS_LIBADDRESSINPUT_ISLAND));
   message_ids.insert(std::make_pair(
+      "oblast", IDS_LIBADDRESSINPUT_OBLAST));
+  message_ids.insert(std::make_pair(
       "parish", IDS_LIBADDRESSINPUT_PARISH));
   message_ids.insert(std::make_pair(
       "prefecture", IDS_LIBADDRESSINPUT_PREFECTURE));
@@ -150,6 +138,7 @@
 }
 
 void Rule::CopyFrom(const Rule& rule) {
+  assert(this != &rule);
   id_ = rule.id_;
   format_ = rule.format_;
   latin_format_ = rule.latin_format_;
@@ -180,36 +169,33 @@
 }
 
 void Rule::ParseJsonRule(const Json& json) {
-  if (json.HasStringValueForKey(kIdKey)) {
-    id_ = json.GetStringValueForKey(kIdKey);
+  std::string value;
+  if (json.GetStringValueForKey("id", &value)) {
+    id_.swap(value);
   }
 
-  if (json.HasStringValueForKey(kFormatKey)) {
-    ParseFormatRule(json.GetStringValueForKey(kFormatKey), &format_);
+  if (json.GetStringValueForKey("fmt", &value)) {
+    ParseFormatRule(value, &format_);
   }
 
-  if (json.HasStringValueForKey(kLatinFormatKey)) {
-    ParseFormatRule(json.GetStringValueForKey(kLatinFormatKey), &latin_format_);
+  if (json.GetStringValueForKey("lfmt", &value)) {
+    ParseFormatRule(value, &latin_format_);
   }
 
-  if (json.HasStringValueForKey(kRequireKey)) {
-    ParseAddressFieldsRequired(
-        json.GetStringValueForKey(kRequireKey), &required_);
+  if (json.GetStringValueForKey("require", &value)) {
+    ParseAddressFieldsRequired(value, &required_);
   }
 
-  if (json.HasStringValueForKey(kSubKeysKey)) {
-    SplitString(
-        json.GetStringValueForKey(kSubKeysKey), kSeparator, &sub_keys_);
+  if (json.GetStringValueForKey("sub_keys", &value)) {
+    SplitString(value, kSeparator, &sub_keys_);
   }
 
-  if (json.HasStringValueForKey(kLanguagesKey)) {
-    SplitString(
-        json.GetStringValueForKey(kLanguagesKey), kSeparator, &languages_);
+  if (json.GetStringValueForKey("languages", &value)) {
+    SplitString(value, kSeparator, &languages_);
   }
 
   sole_postal_code_.clear();
-  if (json.HasStringValueForKey(kZipKey)) {
-    const std::string& zip = json.GetStringValueForKey(kZipKey);
+  if (json.GetStringValueForKey("zip", &value)) {
     // The "zip" field in the JSON data is used in two different ways to
     // validate the postal code. At the country level, the "zip" field indicates
     // a Java compatible regular expression corresponding to all postal codes in
@@ -223,7 +209,7 @@
     // RE2::FullMatch() to perform matching against the entire string.
     RE2::Options options;
     options.set_never_capture(true);
-    RE2* matcher = new RE2("^(" + zip + ")", options);
+    RE2* matcher = new RE2("^(" + value + ")", options);
     if (matcher->ok()) {
       postal_code_matcher_.reset(new RE2ptr(matcher));
     } else {
@@ -232,37 +218,35 @@
     }
     // If the "zip" field is not a regular expression, then it is the sole
     // postal code for this rule.
-    if (!ContainsRegExSpecialCharacters(zip)) {
-      sole_postal_code_ = zip;
+    if (!ContainsRegExSpecialCharacters(value)) {
+      sole_postal_code_.swap(value);
     }
   }
 
-  if (json.HasStringValueForKey(kAdminAreaNameTypeKey)) {
+  if (json.GetStringValueForKey("state_name_type", &value)) {
     admin_area_name_message_id_ =
-        GetMessageIdFromName(json.GetStringValueForKey(kAdminAreaNameTypeKey),
-                             GetAdminAreaMessageIds());
+        GetMessageIdFromName(value, GetAdminAreaMessageIds());
   }
 
-  if (json.HasStringValueForKey(kPostalCodeNameTypeKey)) {
+  if (json.GetStringValueForKey("zip_name_type", &value)) {
     postal_code_name_message_id_ =
-        GetMessageIdFromName(json.GetStringValueForKey(kPostalCodeNameTypeKey),
-                             GetPostalCodeMessageIds());
+        GetMessageIdFromName(value, GetPostalCodeMessageIds());
   }
 
-  if (json.HasStringValueForKey(kNameKey)) {
-    name_ = json.GetStringValueForKey(kNameKey);
+  if (json.GetStringValueForKey("name", &value)) {
+    name_.swap(value);
   }
 
-  if (json.HasStringValueForKey(kLatinNameKey)) {
-    latin_name_ = json.GetStringValueForKey(kLatinNameKey);
+  if (json.GetStringValueForKey("lname", &value)) {
+    latin_name_.swap(value);
   }
 
-  if (json.HasStringValueForKey(kPostalCodeExampleKey)) {
-    postal_code_example_ = json.GetStringValueForKey(kPostalCodeExampleKey);
+  if (json.GetStringValueForKey("zipex", &value)) {
+    postal_code_example_.swap(value);
   }
 
-  if (json.HasStringValueForKey(kPostServiceUrlKey)) {
-    post_service_url_ = json.GetStringValueForKey(kPostServiceUrlKey);
+  if (json.GetStringValueForKey("posturl", &value)) {
+    post_service_url_.swap(value);
   }
 }
 
diff --git a/cpp/src/rule.h b/cpp/src/rule.h
index c722932..1286bcb 100644
--- a/cpp/src/rule.h
+++ b/cpp/src/rule.h
@@ -27,13 +27,12 @@
 #include <string>
 #include <vector>
 
-#include "format_element.h"
-
 namespace i18n {
 namespace addressinput {
 
+class FormatElement;
 class Json;
-class RE2ptr;
+struct RE2ptr;
 
 // Stores address metadata addressing rules, to be used for determining the
 // layout of an address input widget or for address validation. Sample usage:
@@ -99,9 +98,7 @@
   }
 
   // Returns the sole postal code for this rule, if there is one.
-  const std::string& GetSolePostalCode() const {
-    return sole_postal_code_;
-  }
+  const std::string& GetSolePostalCode() const { return sole_postal_code_; }
 
   // The message string identifier for admin area name. If not set, then
   // INVALID_MESSAGE_ID.
@@ -127,9 +124,7 @@
   }
 
   // Returns the post service URL string for this rule.
-  const std::string& GetPostServiceUrl() const {
-    return post_service_url_;
-  }
+  const std::string& GetPostServiceUrl() const { return post_service_url_; }
 
  private:
   std::string id_;
diff --git a/cpp/src/rule_retriever.cc b/cpp/src/rule_retriever.cc
index a77c93a..f0ed848 100644
--- a/cpp/src/rule_retriever.cc
+++ b/cpp/src/rule_retriever.cc
@@ -57,7 +57,7 @@
   }
 
   const RuleRetriever::Callback& rule_ready_;
-  scoped_ptr<Retriever::Callback> data_retrieved_;
+  const scoped_ptr<const Retriever::Callback> data_retrieved_;
 
   DISALLOW_COPY_AND_ASSIGN(Helper);
 };
diff --git a/cpp/src/rule_retriever.h b/cpp/src/rule_retriever.h
index ba3b4c7..ae4b5ee 100644
--- a/cpp/src/rule_retriever.h
+++ b/cpp/src/rule_retriever.h
@@ -32,8 +32,8 @@
 // Retrieves validation rules. Sample usage:
 //    const Retriever* retriever = ...
 //    RuleRetriever rules(retriever);
-//    scoped_ptr<RuleRetriever::Callback> rule_ready(BuildCallback(
-//        this, &MyClass::OnRuleReady));
+//    const scoped_ptr<const RuleRetriever::Callback> rule_ready(
+//        BuildCallback(this, &MyClass::OnRuleReady));
 //    rules.RetrieveRule("data/CA/AB--fr", *rule_ready);
 class RuleRetriever {
  public:
diff --git a/cpp/src/util/cctype_tolower_equal.cc b/cpp/src/util/cctype_tolower_equal.cc
new file mode 100644
index 0000000..819138f
--- /dev/null
+++ b/cpp/src/util/cctype_tolower_equal.cc
@@ -0,0 +1,44 @@
+// Copyright (C) 2014 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cctype_tolower_equal.h"
+
+#include <algorithm>
+#include <cctype>
+#include <functional>
+#include <string>
+
+namespace i18n {
+namespace addressinput {
+
+namespace {
+
+struct EqualToTolowerChar
+    : public std::binary_function<std::string::value_type,
+                                  std::string::value_type, bool> {
+  result_type operator()(first_argument_type a, second_argument_type b) const {
+    return std::tolower(a) == std::tolower(b);
+  }
+};
+
+}  // namespace
+
+EqualToTolowerString::result_type EqualToTolowerString::operator()(
+    const first_argument_type& a, const second_argument_type& b) const {
+  return a.size() == b.size() &&
+         std::equal(a.begin(), a.end(), b.begin(), EqualToTolowerChar());
+}
+
+}  // addressinput
+}  // i18n
diff --git a/cpp/src/util/cctype_tolower_equal.h b/cpp/src/util/cctype_tolower_equal.h
new file mode 100644
index 0000000..106087e
--- /dev/null
+++ b/cpp/src/util/cctype_tolower_equal.h
@@ -0,0 +1,35 @@
+// Copyright (C) 2014 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef I18N_ADDRESSINPUT_UTIL_CCTYPE_TOLOWER_EQUAL_H_
+#define I18N_ADDRESSINPUT_UTIL_CCTYPE_TOLOWER_EQUAL_H_
+
+#include <functional>
+#include <string>
+
+namespace i18n {
+namespace addressinput {
+
+// Performs case insensitive comparison of |a| and |b| by calling std::tolower()
+// from <cctype>.
+struct EqualToTolowerString
+    : public std::binary_function<std::string, std::string, bool> {
+  result_type operator()(const first_argument_type& a,
+                         const second_argument_type& b) const;
+};
+
+}  // addressinput
+}  // i18n
+
+#endif  // I18N_ADDRESSINPUT_UTIL_CCTYPE_TOLOWER_EQUAL_H_
diff --git a/cpp/src/util/json.cc b/cpp/src/util/json.cc
index d819bb2..730479c 100644
--- a/cpp/src/util/json.cc
+++ b/cpp/src/util/json.cc
@@ -19,9 +19,7 @@
 
 #include <cassert>
 #include <cstddef>
-#include <map>
 #include <string>
-#include <utility>
 #include <vector>
 
 #include <rapidjson/document.h>
@@ -36,161 +34,100 @@
 
 class Json::JsonImpl {
  public:
-  // Takes ownership of |document|.
-  explicit JsonImpl(const Document* document)
-      : document_(document), value_(document), dictionaries_() {
-    assert(value_ != NULL);
-    assert(value_->IsObject());
-    BuildKeyList();
-  }
-
-  // Does not take ownership of |value|.
-  explicit JsonImpl(const Value* value)
-      : document_(), value_(value), dictionaries_() {
-    assert(value_ != NULL);
-    assert(value_->IsObject());
-    BuildKeyList();
+  explicit JsonImpl(const std::string& json)
+      : document_(new Document),
+        value_(document_.get()),
+        dictionaries_(),
+        valid_(false) {
+    document_->Parse<kParseValidateEncodingFlag>(json.c_str());
+    valid_ = !document_->HasParseError() && document_->IsObject();
   }
 
   ~JsonImpl() {
-    for (std::map<std::string, const Json*>::const_iterator
-         it = dictionaries_.begin();
+    for (std::vector<const Json*>::const_iterator it = dictionaries_.begin();
          it != dictionaries_.end(); ++it) {
-      delete it->second;
+      delete *it;
     }
   }
 
-  // The caller does not own the result.
-  const Value::Member* FindMember(const std::string& key) {
-    return value_->FindMember(key.c_str());
+  bool valid() const { return valid_; }
+
+  const std::vector<const Json*>& GetSubDictionaries() {
+    if (dictionaries_.empty()) {
+      for (Value::ConstMemberIterator member = value_->MemberBegin();
+           member != value_->MemberEnd(); ++member) {
+        if (member->value.IsObject()) {
+          dictionaries_.push_back(new Json(new JsonImpl(&member->value)));
+        }
+      }
+    }
+    return dictionaries_;
   }
 
-  // The caller does not own the result. The result can be NULL if there's no
-  // dictionary for |key|.
-  const Json* FindDictionary(const std::string& key) const {
-    std::map<std::string, const Json*>::const_iterator it =
-        dictionaries_.find(key);
-    return it != dictionaries_.end() ? it->second : NULL;
-  }
+  bool GetStringValueForKey(const std::string& key, std::string* value) const {
+    assert(value != NULL);
 
-  // Takes ownership of |dictionary|. Should be called only once per |key| and
-  // per |dictionary|.
-  void AddDictionary(const std::string& key, const Json* dictionary) {
-    bool inserted =
-        dictionaries_.insert(std::make_pair(key, dictionary)).second;
-    // Cannot do work inside of assert(), because the compiler can optimize it
-    // away.
-    assert(inserted);
-    // Avoid unused variable warning when assert() is optimized away.
-    (void)inserted;
-  }
+    Value::ConstMemberIterator member = value_->FindMember(key.c_str());
+    if (member == NULL || !member->value.IsString()) {
+      return false;
+    }
 
-  const std::vector<std::string>& GetKeys() const {
-    return keys_;
+    value->assign(member->value.GetString(),
+                  member->value.GetStringLength());
+    return true;
   }
 
  private:
-  void BuildKeyList() {
-    assert(keys_.empty());
-    for (Value::ConstMemberIterator it = value_->MemberBegin();
-         it != value_->MemberEnd(); ++it) {
-      keys_.push_back(it->name.GetString());
-    }
+  // Does not take ownership of |value|.
+  explicit JsonImpl(const Value* value)
+      : document_(),
+        value_(value),
+        dictionaries_(),
+        valid_(true) {
+    assert(value_ != NULL);
+    assert(value_->IsObject());
   }
 
   // An owned JSON document. Can be NULL if the JSON document is not owned.
-  //
-  // When a JsonImpl object is constructed using a Document object, then
-  // JsonImpl is supposed to take ownership of that object, making sure to
-  // delete it in its own destructor. But when a JsonImpl object is constructed
-  // using a Value object, then that object is owned by a Member object which is
-  // owned by a Document object, and should therefore not be deleted by
-  // JsonImpl.
-  const scoped_ptr<const Document> document_;
+  const scoped_ptr<Document> document_;
 
   // A JSON document that is not owned. Cannot be NULL. Can point to document_.
   const Value* const value_;
 
-  // Owned JSON objects.
-  std::map<std::string, const Json*> dictionaries_;
+  // Owned JSON objects of sub-dictionaries.
+  std::vector<const Json*> dictionaries_;
 
-  std::vector<std::string> keys_;
+  // True if the JSON object was parsed successfully.
+  bool valid_;
 
   DISALLOW_COPY_AND_ASSIGN(JsonImpl);
 };
 
-Json::Json() {}
+Json::Json() : impl_() {}
 
 Json::~Json() {}
 
 bool Json::ParseObject(const std::string& json) {
   assert(impl_ == NULL);
-  scoped_ptr<Document> document(new Document);
-  document->Parse<kParseValidateEncodingFlag>(json.c_str());
-  bool valid = !document->HasParseError() && document->IsObject();
-  if (valid) {
-    impl_.reset(new JsonImpl(document.release()));
+  impl_.reset(new JsonImpl(json));
+  if (!impl_->valid()) {
+    impl_.reset();
   }
-  return valid;
+  return impl_ != NULL;
 }
 
-const std::vector<std::string>& Json::GetKeys() const {
+const std::vector<const Json*>& Json::GetSubDictionaries() const {
   assert(impl_ != NULL);
-  return impl_->GetKeys();
+  return impl_->GetSubDictionaries();
 }
 
-bool Json::HasStringValueForKey(const std::string& key) const {
+bool Json::GetStringValueForKey(const std::string& key,
+                                std::string* value) const {
   assert(impl_ != NULL);
-
-  // Member is owned by impl_.
-  const Value::Member* member = impl_->FindMember(key);
-  return member != NULL && member->value.IsString();
+  return impl_->GetStringValueForKey(key, value);
 }
 
-std::string Json::GetStringValueForKey(const std::string& key) const {
-  assert(impl_ != NULL);
-
-  // Member is owned by impl_.
-  const Value::Member* member = impl_->FindMember(key.c_str());
-  assert(member != NULL);
-  assert(member->value.IsString());
-  return std::string(member->value.GetString(),
-                     member->value.GetStringLength());
-}
-
-bool Json::HasDictionaryValueForKey(const std::string& key) const {
-  assert(impl_ != NULL);
-
-  // The value returned by FindDictionary() is owned by impl_.
-  if (impl_->FindDictionary(key) != NULL) {
-    return true;
-  }
-
-  // Member is owned by impl_.
-  const Value::Member* member = impl_->FindMember(key);
-  return member != NULL && member->value.IsObject();
-}
-
-const Json& Json::GetDictionaryValueForKey(const std::string& key) const {
-  assert(impl_ != NULL);
-
-  // Existing_dictionary is owned by impl_.
-  const Json* existing_dictionary = impl_->FindDictionary(key);
-  if (existing_dictionary != NULL) {
-    return *existing_dictionary;
-  }
-
-  // Member is owned by impl_.
-  const Value::Member* member = impl_->FindMember(key);
-  assert(member != NULL);
-  assert(member->value.IsObject());
-
-  // Dictionary is owned by impl_.
-  Json* dictionary = new Json;
-  dictionary->impl_.reset(new JsonImpl(&member->value));
-  impl_->AddDictionary(key, dictionary);
-  return *dictionary;
-}
+Json::Json(JsonImpl* impl) : impl_(impl) {}
 
 }  // namespace addressinput
 }  // namespace i18n
diff --git a/cpp/src/util/json.h b/cpp/src/util/json.h
index 1fbf500..1aac803 100644
--- a/cpp/src/util/json.h
+++ b/cpp/src/util/json.h
@@ -39,32 +39,24 @@
   // object.
   bool ParseObject(const std::string& json);
 
-  // Returns the list of keys in the parsed JSON. The JSON object must be parsed
-  // successfully in ParseObject() before invoking this method.
-  const std::vector<std::string>& GetKeys() const;
+  // Returns the list of sub dictionaries. The JSON object must be parsed
+  // successfully in ParseObject() before invoking this method. The caller does
+  // not own the result.
+  const std::vector<const Json*>& GetSubDictionaries() const;
 
-  // Returns true if the parsed JSON contains a string value for |key|. The JSON
-  // object must be parsed successfully in ParseObject() before invoking this
-  // method.
-  bool HasStringValueForKey(const std::string& key) const;
-
-  // Returns the string value for the |key|. The |key| must be present and its
-  // value must be of string type, i.e., HasStringValueForKey(key) must return
-  // true before invoking this method.
-  std::string GetStringValueForKey(const std::string& key) const;
-
-  // Returns true if the parsed JSON contains a dictionary value for |key|. The
-  // JSON object must be parsed successfully in ParseObject() before invoking
-  // this method.
-  bool HasDictionaryValueForKey(const std::string& key) const;
-
-  // Returns the dictionary value for the |key|. The |key| must be present and
-  // its value must be of the dictionary type, i.e., HasDictionaryValueForKey()
-  // must return true before invoking this method.
-  const Json& GetDictionaryValueForKey(const std::string& key) const;
+  // Returns true if the parsed JSON contains a string value for |key|. Sets
+  // |value| to the string value of the |key|. The JSON object must be parsed
+  // successfully in ParseObject() before invoking this method. The |value|
+  // parameter should not be NULL.
+  bool GetStringValueForKey(const std::string& key, std::string* value) const;
 
  private:
   class JsonImpl;
+  friend class JsonImpl;
+
+  // Constructor to be called by JsonImpl.
+  explicit Json(JsonImpl* impl);
+
   scoped_ptr<JsonImpl> impl_;
 
   DISALLOW_COPY_AND_ASSIGN(Json);
diff --git a/cpp/src/util/lru_cache_using_std.h b/cpp/src/util/lru_cache_using_std.h
index 25aced7..6062d28 100644
--- a/cpp/src/util/lru_cache_using_std.h
+++ b/cpp/src/util/lru_cache_using_std.h
@@ -21,8 +21,10 @@
 #define I18N_ADDRESSINPUT_UTIL_LRU_CACHE_USING_STD_H_
 
 #include <cassert>
+#include <cstddef>
 #include <list>
 #include <map>
+#include <utility>
 
 // Class providing fixed-size (by number of records)
 // LRU-replacement cache of a function with signature
diff --git a/cpp/src/util/md5.cc b/cpp/src/util/md5.cc
index 4a629d0..ea7561b 100644
--- a/cpp/src/util/md5.cc
+++ b/cpp/src/util/md5.cc
@@ -28,7 +28,9 @@
 
 #include <libaddressinput/util/basictypes.h>
 
+#include <cstddef>
 #include <string>
+#include <string.h>
 
 namespace {
 
diff --git a/cpp/src/util/md5.h b/cpp/src/util/md5.h
index 8d05301..98bc325 100644
--- a/cpp/src/util/md5.h
+++ b/cpp/src/util/md5.h
@@ -8,6 +8,7 @@
 #ifndef I18N_ADDRESSINPUT_UTIL_MD5_H_
 #define I18N_ADDRESSINPUT_UTIL_MD5_H_
 
+#include <cstddef>
 #include <string>
 
 namespace i18n {
diff --git a/cpp/src/util/string_util.cc b/cpp/src/util/string_util.cc
index 18d0a87..8396d51 100644
--- a/cpp/src/util/string_util.cc
+++ b/cpp/src/util/string_util.cc
@@ -10,10 +10,9 @@
 
 #include "string_util.h"
 
-#include <libaddressinput/util/basictypes.h>
-
-#include <algorithm>
 #include <cassert>
+#include <cstddef>
+#include <stdint.h>
 #include <string>
 #include <vector>
 
diff --git a/cpp/src/validating_storage.cc b/cpp/src/validating_storage.cc
index 7dc231c..a504db4 100644
--- a/cpp/src/validating_storage.cc
+++ b/cpp/src/validating_storage.cc
@@ -52,7 +52,7 @@
                           std::string* data) {
     if (success) {
       assert(data != NULL);
-      bool is_stale = !ValidatingUtil::UnwrapTimestamp(data, time(NULL));
+      bool is_stale = !ValidatingUtil::UnwrapTimestamp(data, std::time(NULL));
       bool is_corrupted = !ValidatingUtil::UnwrapChecksum(data);
       success = !is_corrupted && !is_stale;
       if (is_corrupted) {
@@ -68,7 +68,7 @@
   }
 
   const Storage::Callback& data_ready_;
-  scoped_ptr<Storage::Callback> wrapped_data_ready_;
+  const scoped_ptr<const Storage::Callback> wrapped_data_ready_;
 
   DISALLOW_COPY_AND_ASSIGN(Helper);
 };
@@ -84,7 +84,7 @@
 
 void ValidatingStorage::Put(const std::string& key, std::string* data) {
   assert(data != NULL);
-  ValidatingUtil::Wrap(time(NULL), data);
+  ValidatingUtil::Wrap(std::time(NULL), data);
   wrapped_storage_->Put(key, data);
 }
 
diff --git a/cpp/src/validating_storage.h b/cpp/src/validating_storage.h
index 11e74cd..1cf3f95 100644
--- a/cpp/src/validating_storage.h
+++ b/cpp/src/validating_storage.h
@@ -32,8 +32,8 @@
 //    scoped_ptr<Storage> file_storage = ...;
 //    ValidatingStorage storage(file_storage));
 //    storage.Put("key", new std::string("data"));
-//    scoped_ptr<ValidatingStorage::Callback> data_ready(BuildCallback(
-//        this, &MyClass::OnDataReady));
+//    const scoped_ptr<const ValidatingStorage::Callback> data_ready(
+//        BuildCallback(this, &MyClass::OnDataReady));
 //    storage.Get("key", *data_ready);
 class ValidatingStorage : public Storage {
  public:
diff --git a/cpp/src/validating_util.cc b/cpp/src/validating_util.cc
index 6b52e8b..9356689 100644
--- a/cpp/src/validating_util.cc
+++ b/cpp/src/validating_util.cc
@@ -84,7 +84,11 @@
 void ValidatingUtil::Wrap(time_t timestamp, std::string* data) {
   assert(data != NULL);
   char timestamp_string[2 + 3 * sizeof timestamp];
-  snprintf(timestamp_string, sizeof timestamp_string, "%ld", timestamp);
+  int size =
+      std::sprintf(timestamp_string, "%ld", static_cast<long>(timestamp));
+  assert(size > 0);
+  assert(size < sizeof timestamp_string);
+  (void)size;
 
   std::string header;
   header.append(kTimestampPrefix, kTimestampPrefixLength);
@@ -108,7 +112,7 @@
 
   std::string timestamp_string;
   if (!UnwrapHeader(
-           kTimestampPrefix, kTimestampPrefixLength, data, &timestamp_string)) {
+          kTimestampPrefix, kTimestampPrefixLength, data, &timestamp_string)) {
     return false;
   }
 
diff --git a/cpp/src/validating_util.h b/cpp/src/validating_util.h
index 1357651..20d541b 100644
--- a/cpp/src/validating_util.h
+++ b/cpp/src/validating_util.h
@@ -19,6 +19,8 @@
 #ifndef I18N_ADDRESSINPUT_VALIDATING_UTIL_H_
 #define I18N_ADDRESSINPUT_VALIDATING_UTIL_H_
 
+#include <libaddressinput/util/basictypes.h>
+
 #include <ctime>
 #include <string>
 
@@ -47,6 +49,9 @@
   // Strips out the checksum from |data|. Returns |true| if the checksum is
   // present, formatted correctly, and valid for this data.
   static bool UnwrapChecksum(std::string* data);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ValidatingUtil);
 };
 
 }  // namespace addressinput
diff --git a/cpp/src/validation_task.cc b/cpp/src/validation_task.cc
index e5beb1a..1e7911a 100644
--- a/cpp/src/validation_task.cc
+++ b/cpp/src/validation_task.cc
@@ -19,6 +19,7 @@
 #include <libaddressinput/address_metadata.h>
 #include <libaddressinput/address_problem.h>
 #include <libaddressinput/address_validator.h>
+#include <libaddressinput/callback.h>
 #include <libaddressinput/supplier.h>
 #include <libaddressinput/util/basictypes.h>
 
@@ -29,13 +30,13 @@
 #include <utility>
 #include <vector>
 
+#include <re2/re2.h>
+
 #include "lookup_key.h"
 #include "post_box_matchers.h"
 #include "rule.h"
 #include "util/re2ptr.h"
 
-#include <re2/re2.h>
-
 namespace i18n {
 namespace addressinput {
 
@@ -109,6 +110,7 @@
     SORTING_CODE,
     POSTAL_CODE,
     STREET_ADDRESS,
+    ORGANIZATION,
     RECIPIENT
   };
 
@@ -131,7 +133,8 @@
     DEPENDENT_LOCALITY,
     SORTING_CODE,
     POSTAL_CODE,
-    STREET_ADDRESS,
+    STREET_ADDRESS
+    // ORGANIZATION is never required.
     // RECIPIENT is handled separately.
   };
 
@@ -255,9 +258,10 @@
 bool ValidationTask::ShouldReport(AddressField field,
                                   AddressProblem problem) const {
   return filter_ == NULL || filter_->empty() ||
-         std::find(filter_->begin(), filter_->end(),
+         std::find(filter_->begin(),
+                   filter_->end(),
                    FieldProblemMap::value_type(field, problem)) !=
-         filter_->end();
+             filter_->end();
 }
 
 }  // namespace addressinput
diff --git a/cpp/src/validation_task.h b/cpp/src/validation_task.h
index f0895f3..1658678 100644
--- a/cpp/src/validation_task.h
+++ b/cpp/src/validation_task.h
@@ -22,11 +22,12 @@
 #include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
 
+#include <string>
+
 namespace i18n {
 namespace addressinput {
 
 class LookupKey;
-class Rule;
 struct AddressData;
 
 // A ValidationTask object encapsulates the information necessary to perform
@@ -64,16 +65,14 @@
   void CheckMissingRequiredField(const std::string& region_code) const;
 
   // Checks the hierarchical fields for UNKNOWN_VALUE problems.
-  void CheckUnknownValue(
-      const Supplier::RuleHierarchy& hierarchy) const;
+  void CheckUnknownValue(const Supplier::RuleHierarchy& hierarchy) const;
 
   // Checks the POSTAL_CODE field for problems.
   void CheckPostalCodeFormatAndValue(
       const Supplier::RuleHierarchy& hierarchy) const;
 
   // Checks the STREET_ADDRESS field for USES_P_O_BOX problems.
-  void CheckUsesPoBox(
-      const Supplier::RuleHierarchy& hierarchy) const;
+  void CheckUsesPoBox(const Supplier::RuleHierarchy& hierarchy) const;
 
   // Writes (|field|,|problem|) to |problems_|.
   void ReportProblem(AddressField field, AddressProblem problem) const;
diff --git a/cpp/test/address_data_test.cc b/cpp/test/address_data_test.cc
index 8ba0f4b..46491c9 100644
--- a/cpp/test/address_data_test.cc
+++ b/cpp/test/address_data_test.cc
@@ -32,6 +32,7 @@
 using i18n::addressinput::SORTING_CODE;
 using i18n::addressinput::POSTAL_CODE;
 using i18n::addressinput::STREET_ADDRESS;
+using i18n::addressinput::ORGANIZATION;
 using i18n::addressinput::RECIPIENT;
 
 TEST(AddressDataTest, GetFieldValue) {
@@ -42,6 +43,7 @@
   address.dependent_locality = "ddd";
   address.sorting_code = "xxx";
   address.postal_code = "zzz";
+  address.organization = "ooo";
   address.recipient = "nnn";
 
   EXPECT_EQ(address.region_code,
@@ -56,6 +58,8 @@
             address.GetFieldValue(SORTING_CODE));
   EXPECT_EQ(address.postal_code,
             address.GetFieldValue(POSTAL_CODE));
+  EXPECT_EQ(address.organization,
+            address.GetFieldValue(ORGANIZATION));
   EXPECT_EQ(address.recipient,
             address.GetFieldValue(RECIPIENT));
 }
@@ -78,6 +82,7 @@
   EXPECT_TRUE(address.IsFieldEmpty(SORTING_CODE));
   EXPECT_TRUE(address.IsFieldEmpty(POSTAL_CODE));
   EXPECT_TRUE(address.IsFieldEmpty(STREET_ADDRESS));
+  EXPECT_TRUE(address.IsFieldEmpty(ORGANIZATION));
   EXPECT_TRUE(address.IsFieldEmpty(RECIPIENT));
 
   address.region_code = "rrr";
@@ -87,6 +92,7 @@
   address.sorting_code = "xxx";
   address.postal_code = "zzz";
   address.address_line.push_back("aaa");
+  address.organization = "ooo";
   address.recipient = "nnn";
 
   EXPECT_FALSE(address.IsFieldEmpty(COUNTRY));
@@ -96,6 +102,7 @@
   EXPECT_FALSE(address.IsFieldEmpty(SORTING_CODE));
   EXPECT_FALSE(address.IsFieldEmpty(POSTAL_CODE));
   EXPECT_FALSE(address.IsFieldEmpty(STREET_ADDRESS));
+  EXPECT_FALSE(address.IsFieldEmpty(ORGANIZATION));
   EXPECT_FALSE(address.IsFieldEmpty(RECIPIENT));
 }
 
@@ -149,6 +156,7 @@
   address.dependent_locality = "D";
   address.sorting_code = "X";
   address.language_code = "zh-Hant";
+  address.organization = "O";
   oss << address;
   EXPECT_EQ("region_code: \"R\"\n"
             "administrative_area: \"S\"\n"
@@ -159,6 +167,7 @@
             "address_line: \"Line 1\"\n"
             "address_line: \"Line 2\"\n"
             "language_code: \"zh-Hant\"\n"
+            "organization: \"O\"\n"
             "recipient: \"N\"\n", oss.str());
 }
 
@@ -173,6 +182,7 @@
   address.locality = "C";
   address.dependent_locality = "D";
   address.sorting_code = "X";
+  address.organization = "O";
   address.language_code = "zh-Hant";
 
   AddressData clone = address;
diff --git a/cpp/test/address_field_util_test.cc b/cpp/test/address_field_util_test.cc
index 4a1d7a2..0cde367 100644
--- a/cpp/test/address_field_util_test.cc
+++ b/cpp/test/address_field_util_test.cc
@@ -26,20 +26,22 @@
 namespace {
 
 using i18n::addressinput::AddressField;
-using i18n::addressinput::COUNTRY;
-using i18n::addressinput::LOCALITY;
 using i18n::addressinput::FormatElement;
 using i18n::addressinput::ParseFormatRule;
+
+using i18n::addressinput::COUNTRY;
+using i18n::addressinput::LOCALITY;
 using i18n::addressinput::POSTAL_CODE;
-using i18n::addressinput::RECIPIENT;
 using i18n::addressinput::STREET_ADDRESS;
+using i18n::addressinput::ORGANIZATION;
+using i18n::addressinput::RECIPIENT;
 
 TEST(AddressFieldUtilTest, FormatParseNewline) {
   std::vector<FormatElement> actual;
-  ParseFormatRule("%O%n%N%n%A%nAX-%Z %C%nÅLAND", &actual);
+  ParseFormatRule("%O%n%N%n%A%nAX-%Z %C%n\xC3\x85LAND", &actual);  /* "ÅLAND" */
 
   std::vector<FormatElement> expected;
-  // Organization is skipped.
+  expected.push_back(FormatElement(ORGANIZATION));
   expected.push_back(FormatElement());
   expected.push_back(FormatElement(RECIPIENT));
   expected.push_back(FormatElement());
@@ -50,7 +52,7 @@
   expected.push_back(FormatElement(" "));
   expected.push_back(FormatElement(LOCALITY));
   expected.push_back(FormatElement());
-  expected.push_back(FormatElement("ÅLAND"));
+  expected.push_back(FormatElement("\xC3\x85LAND"));  /* "ÅLAND" */
 
   EXPECT_EQ(expected, actual);
 }
diff --git a/cpp/test/address_formatter_test.cc b/cpp/test/address_formatter_test.cc
index ca94a32..c656ec8 100644
--- a/cpp/test/address_formatter_test.cc
+++ b/cpp/test/address_formatter_test.cc
@@ -28,6 +28,13 @@
 using i18n::addressinput::GetFormattedNationalAddressLine;
 using i18n::addressinput::GetStreetAddressLinesAsSingleLine;
 
+TEST(AddressFormatterTest, GetStreetAddressLinesAsSingleLine_EmptyAddress) {
+  AddressData address;
+  std::string result;
+  GetStreetAddressLinesAsSingleLine(address, &result);
+  EXPECT_TRUE(result.empty());
+}
+
 TEST(AddressFormatterTest, GetStreetAddressLinesAsSingleLine_1Line) {
   AddressData address;
   address.region_code = "US";  // Not used.
@@ -198,4 +205,163 @@
   EXPECT_EQ(expected, lines);
 }
 
+TEST(AddressFormatterTest, GetFormattedNationalAddress_InlineStreetAddress) {
+  AddressData address;
+  address.region_code = "CI";
+  address.address_line.push_back("32 Boulevard Carde");
+  address.locality = "Abidjan";
+  address.sorting_code = "64";
+
+  std::vector<std::string> expected;
+  expected.push_back("64 32 Boulevard Carde Abidjan 64");
+
+  std::vector<std::string> lines;
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+}
+
+TEST(AddressFormatterTest,
+     GetFormattedNationalAddressMissingFields_LiteralsAroundField) {
+  AddressData address;
+  address.region_code = "CH";
+  std::vector<std::string> expected;
+  std::vector<std::string> lines;
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.locality = "Zurich";
+  expected.push_back("Zurich");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.postal_code = "8001";
+  expected.back().assign("CH-8001 Zurich");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.locality.clear();
+  expected.back().assign("CH-8001");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+}
+
+TEST(AddressFormatterTest,
+     GetFormattedNationalAddressMissingFields_LiteralsBetweenFields) {
+  AddressData address;
+  address.region_code = "US";
+  std::vector<std::string> expected;
+  std::vector<std::string> lines;
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.administrative_area = "CA";
+  expected.push_back("CA");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.locality = "Los Angeles";
+  expected.back().assign("Los Angeles, CA");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.postal_code = "90291";
+  expected.back().assign("Los Angeles, CA 90291");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.administrative_area.clear();
+  expected.back().assign("Los Angeles 90291");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.locality.clear();
+  address.administrative_area = "CA";
+  expected.back().assign("CA 90291");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+}
+
+TEST(AddressFormatterTest,
+     GetFormattedNationalAddressMissingFields_LiteralOnSeparateLine) {
+  AddressData address;
+  address.region_code = "AX";
+  std::vector<std::string> expected;
+  expected.push_back("\xC3\x85LAND");  /* ÅLAND */
+  std::vector<std::string> lines;
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.locality = "City";
+  expected.insert(expected.begin(), "City");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.postal_code = "123";
+  expected.front().assign("AX-123 City");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+}
+
+TEST(AddressFormatterTest,
+     GetFormattedNationalAddressMissingFields_LiteralBeforeField) {
+  AddressData address;
+  address.region_code = "JP";
+  address.language_code = "ja";
+  std::vector<std::string> expected;
+  std::vector<std::string> lines;
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.postal_code = "123";
+  expected.push_back("\xE3\x80\x92" "123");  /* 〒123 */
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.administrative_area = "Prefecture";
+  expected.push_back("Prefecture");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.postal_code.clear();
+  expected.erase(expected.begin());
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+}
+
+TEST(AddressFormatterTest,
+     GetFormattedNationalAddressMissingFields_DuplicateField) {
+  AddressData address;
+  address.region_code = "CI";
+  std::vector<std::string> expected;
+  std::vector<std::string> lines;
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.sorting_code = "123";
+  expected.push_back("123 123");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.address_line.push_back("456 Main St");
+  expected.back().assign("123 456 Main St 123");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.locality = "Yamoussoukro";
+  expected.back().assign("123 456 Main St Yamoussoukro 123");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.sorting_code.erase();
+  expected.back().assign("456 Main St Yamoussoukro");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+
+  address.address_line.clear();
+  expected.back().assign("Yamoussoukro");
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+}
+
+
 }  // namespace
diff --git a/cpp/test/address_input_helper_test.cc b/cpp/test/address_input_helper_test.cc
index 84a2286..4014c91 100644
--- a/cpp/test/address_input_helper_test.cc
+++ b/cpp/test/address_input_helper_test.cc
@@ -26,8 +26,8 @@
 
 #include <gtest/gtest.h>
 
-#include "fake_downloader.h"
-#include "mock_downloader.h"
+#include "mock_source.h"
+#include "testdata_source.h"
 
 namespace {
 
@@ -35,24 +35,20 @@
 using i18n::addressinput::AddressInputHelper;
 using i18n::addressinput::BuildCallback;
 using i18n::addressinput::Callback;
-using i18n::addressinput::FakeDownloader;
-using i18n::addressinput::MockDownloader;
+using i18n::addressinput::MockSource;
 using i18n::addressinput::NullStorage;
 using i18n::addressinput::PreloadSupplier;
 using i18n::addressinput::scoped_ptr;
+using i18n::addressinput::TestdataSource;
 
 class AddressInputHelperTest : public testing::Test {
  protected:
   AddressInputHelperTest()
       // Our PreloadSupplier loads all data for a country at a time.
-      : supplier_(FakeDownloader::kFakeAggregateDataUrl,
-                  new FakeDownloader,
-                  new NullStorage),
+      : supplier_(new TestdataSource(true), new NullStorage),
         address_input_helper_(&supplier_),
         loaded_(BuildCallback(this, &AddressInputHelperTest::Loaded)) {}
 
-  ~AddressInputHelperTest() {}
-
   // Helper method to test FillAddress that ensures the PreloadSupplier has the
   // necessary data preloaded.
   void FillAddress(AddressData* address) {
@@ -65,9 +61,7 @@
 
  private:
   // Used to preload data that we need.
-  void Loaded(bool success, const std::string&, int) {
-    ASSERT_TRUE(success);
-  }
+  void Loaded(bool success, const std::string&, int) { ASSERT_TRUE(success); }
 
   PreloadSupplier supplier_;
   const AddressInputHelper address_input_helper_;
@@ -194,8 +188,8 @@
   address.postal_code = "527-111";
 
   AddressData expected = address;
-   /* The province, Jeonnam - 전라남도 - is known, but we have several locality
-    * matches so none of them are populated. */
+  /* The province, Jeonnam - 전라남도 - is known, but we have several locality
+   * matches so none of them are populated. */
   expected.administrative_area =
       "\xEC\xA0\x84\xEB\x9D\xBC\xEB\x82\xA8\xEB\x8F\x84";
   FillAddress(&address);
@@ -247,16 +241,12 @@
 class AddressInputHelperMockDataTest : public testing::Test {
  protected:
   AddressInputHelperMockDataTest()
-      : downloader_(new MockDownloader),
+      : source_(new MockSource),
         // Our PreloadSupplier loads all data for a country at a time.
-        supplier_(MockDownloader::kMockDataUrl,
-                  downloader_,
-                  new NullStorage),
+        supplier_(source_, new NullStorage),
         address_input_helper_(&supplier_),
         loaded_(BuildCallback(this, &AddressInputHelperMockDataTest::Loaded)) {}
 
-  ~AddressInputHelperMockDataTest() {}
-
   // Helper method to test FillAddress that ensures the PreloadSupplier has the
   // necessary data preloaded.
   void FillAddress(AddressData* address) {
@@ -267,13 +257,11 @@
     address_input_helper_.FillAddress(address);
   }
 
-  MockDownloader* const downloader_;
+  MockSource* const source_;
 
  private:
-  // Our mock downloader we assume will always succeed.
-  void Loaded(bool success, const std::string&, int) {
-    ASSERT_TRUE(success);
-  }
+  // Our mock source we assume will always succeed.
+  void Loaded(bool success, const std::string&, int) { ASSERT_TRUE(success); }
 
   PreloadSupplier supplier_;
   const AddressInputHelper address_input_helper_;
@@ -285,7 +273,7 @@
        PostalCodeSharedAcrossDifferentHierarchies) {
   // Note that this data is in the format of data that would be returned from
   // the aggregate server.
-  downloader_->data_.insert(std::make_pair(
+  source_->data_.insert(std::make_pair(
       // We use KR since we need a country where we format all fields down to
       // dependent locality, or the hierarchy won't be loaded.
       "data/KR",
@@ -319,14 +307,14 @@
   // Create data where one state matches the ZIP code, but the other doesn't:
   // within the state which does, multiple cities and sub-cities match. The only
   // thing we can be certain of is therefore the state.
-  downloader_->data_.insert(std::make_pair(
+  source_->data_.insert(std::make_pair(
       // We use KR since we need a country where we format all fields down to
       // dependent locality, or the hierarchy won't be loaded.
       "data/KR",
       "{\"data/KR\": "
       // The top-level ZIP expression must be present for sub-key matches to be
       // evaluated.
-      "{\"id\":\"data/KR\", \"sub_keys\":\"A~B\", \"zip\":\"\\\\d\{5}\"}, "
+      "{\"id\":\"data/KR\", \"sub_keys\":\"A~B\", \"zip\":\"\\\\d{5}\"}, "
       "\"data/KR/A\": "
       "{\"id\":\"data/KR/A\", \"sub_keys\":\"A1~A2\"}, "
       "\"data/KR/A/A1\": "
diff --git a/cpp/test/address_metadata_test.cc b/cpp/test/address_metadata_test.cc
index e1959cd..b60619b 100644
--- a/cpp/test/address_metadata_test.cc
+++ b/cpp/test/address_metadata_test.cc
@@ -20,13 +20,13 @@
 
 namespace {
 
+using i18n::addressinput::IsFieldRequired;
+using i18n::addressinput::IsFieldUsed;
+
 using i18n::addressinput::COUNTRY;
 using i18n::addressinput::ADMIN_AREA;
 using i18n::addressinput::DEPENDENT_LOCALITY;
 
-using i18n::addressinput::IsFieldRequired;
-using i18n::addressinput::IsFieldUsed;
-
 TEST(AddressMetadataTest, IsFieldRequiredCountry) {
   EXPECT_TRUE(IsFieldRequired(COUNTRY, "US"));
   EXPECT_TRUE(IsFieldRequired(COUNTRY, "CH"));
diff --git a/cpp/test/address_normalizer_test.cc b/cpp/test/address_normalizer_test.cc
index 6f2d9f4..3a7acf2 100644
--- a/cpp/test/address_normalizer_test.cc
+++ b/cpp/test/address_normalizer_test.cc
@@ -21,31 +21,29 @@
 #include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
 
-#include "fake_downloader.h"
+#include <string>
 
 #include <gtest/gtest.h>
 
+#include "testdata_source.h"
+
 namespace {
 
 using i18n::addressinput::AddressData;
 using i18n::addressinput::AddressNormalizer;
 using i18n::addressinput::BuildCallback;
-using i18n::addressinput::FakeDownloader;
 using i18n::addressinput::NullStorage;
 using i18n::addressinput::PreloadSupplier;
 using i18n::addressinput::scoped_ptr;
+using i18n::addressinput::TestdataSource;
 
 class AddressNormalizerTest : public testing::Test {
  protected:
   AddressNormalizerTest()
-      : supplier_(FakeDownloader::kFakeAggregateDataUrl,
-                  new FakeDownloader,
-                  new NullStorage),
+      : supplier_(new TestdataSource(true), new NullStorage),
         loaded_(BuildCallback(this, &AddressNormalizerTest::OnLoaded)),
         normalizer_(&supplier_) {}
 
-  virtual ~AddressNormalizerTest() {}
-
   PreloadSupplier supplier_;
   const scoped_ptr<const PreloadSupplier::Callback> loaded_;
   const AddressNormalizer normalizer_;
@@ -86,12 +84,13 @@
   AddressData address;
   address.language_code = "ko-KR";
   address.region_code = "KR";
-  address.administrative_area = "강원";
+  address.administrative_area = "\xEA\xB0\x95\xEC\x9B\x90";  /* "강원" */
   normalizer_.Normalize(&address);
-  EXPECT_EQ("강원도", address.administrative_area);
+  EXPECT_EQ(
+      "\xEA\xB0\x95\xEC\x9B\x90\xEB\x8F\x84",  /* "강원도" */
+      address.administrative_area);
 }
 
-
 TEST_F(AddressNormalizerTest, DontSwitchLatinScriptForUnknownLanguage) {
   supplier_.LoadRules("KR", *loaded_);
   AddressData address;
@@ -105,9 +104,11 @@
   supplier_.LoadRules("KR", *loaded_);
   AddressData address;
   address.region_code = "KR";
-  address.administrative_area = "강원";
+  address.administrative_area = "\xEA\xB0\x95\xEC\x9B\x90";  /* "강원" */
   normalizer_.Normalize(&address);
-  EXPECT_EQ("강원도", address.administrative_area);
+  EXPECT_EQ(
+      "\xEA\xB0\x95\xEC\x9B\x90\xEB\x8F\x84",  /* "강원도" */
+      address.administrative_area);
 }
 
 }  // namespace
diff --git a/cpp/test/address_ui_test.cc b/cpp/test/address_ui_test.cc
index c23d205..d2e512f 100644
--- a/cpp/test/address_ui_test.cc
+++ b/cpp/test/address_ui_test.cc
@@ -17,6 +17,7 @@
 #include <libaddressinput/address_field.h>
 #include <libaddressinput/address_ui_component.h>
 #include <libaddressinput/localization.h>
+#include <libaddressinput/util/basictypes.h>
 
 #include <set>
 #include <string>
@@ -26,16 +27,18 @@
 
 namespace {
 
-using i18n::addressinput::ADMIN_AREA;
 using i18n::addressinput::AddressField;
 using i18n::addressinput::AddressUiComponent;
 using i18n::addressinput::BuildComponents;
-using i18n::addressinput::COUNTRY;
 using i18n::addressinput::GetRegionCodes;
 using i18n::addressinput::Localization;
+
+using i18n::addressinput::COUNTRY;
+using i18n::addressinput::ADMIN_AREA;
 using i18n::addressinput::POSTAL_CODE;
-using i18n::addressinput::RECIPIENT;
 using i18n::addressinput::STREET_ADDRESS;
+using i18n::addressinput::ORGANIZATION;
+using i18n::addressinput::RECIPIENT;
 
 static const char kUiLanguageTag[] = "en";
 
@@ -70,8 +73,12 @@
 // Tests for address UI functions.
 class AddressUiTest : public testing::TestWithParam<std::string> {
  protected:
+  AddressUiTest() {}
   Localization localization_;
   std::string best_address_language_tag_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AddressUiTest);
 };
 
 // Verifies that a region code consists of two characters, for example "TW".
@@ -142,8 +149,12 @@
 class BestAddressLanguageTagTest
     : public testing::TestWithParam<LanguageTestCase> {
  protected:
+  BestAddressLanguageTagTest() {}
   Localization localization_;
   std::string best_address_language_tag_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BestAddressLanguageTagTest);
 };
 
 std::string GetterStub(int) { return std::string(); }
@@ -210,12 +221,12 @@
         LanguageTestCase("MO", "en", "zh-Latn", RECIPIENT),
 
         // Switzerland supports de, fr, and it.
-        LanguageTestCase("CH", "de", "de", RECIPIENT),
-        LanguageTestCase("CH", "de-DE", "de", RECIPIENT),
-        LanguageTestCase("CH", "de-Latn-DE", "de", RECIPIENT),
-        LanguageTestCase("CH", "fr", "fr", RECIPIENT),
-        LanguageTestCase("CH", "it", "it", RECIPIENT),
-        LanguageTestCase("CH", "en", "de", RECIPIENT),
+        LanguageTestCase("CH", "de", "de", ORGANIZATION),
+        LanguageTestCase("CH", "de-DE", "de", ORGANIZATION),
+        LanguageTestCase("CH", "de-Latn-DE", "de", ORGANIZATION),
+        LanguageTestCase("CH", "fr", "fr", ORGANIZATION),
+        LanguageTestCase("CH", "it", "it", ORGANIZATION),
+        LanguageTestCase("CH", "en", "de", ORGANIZATION),
 
         // Antarctica does not have language information.
         LanguageTestCase("AQ", "en", "en", RECIPIENT),
diff --git a/cpp/test/address_validator_test.cc b/cpp/test/address_validator_test.cc
index 79195e3..3177b01 100644
--- a/cpp/test/address_validator_test.cc
+++ b/cpp/test/address_validator_test.cc
@@ -15,6 +15,7 @@
 #include <libaddressinput/address_validator.h>
 
 #include <libaddressinput/address_data.h>
+#include <libaddressinput/address_field.h>
 #include <libaddressinput/address_problem.h>
 #include <libaddressinput/callback.h>
 #include <libaddressinput/null_storage.h>
@@ -23,28 +24,28 @@
 #include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
 
+#include <string>
 #include <utility>
 
 #include <gtest/gtest.h>
 
-#include "fake_downloader.h"
+#include "testdata_source.h"
 
 namespace {
 
 using i18n::addressinput::AddressData;
 using i18n::addressinput::AddressValidator;
 using i18n::addressinput::BuildCallback;
-using i18n::addressinput::FakeDownloader;
 using i18n::addressinput::FieldProblemMap;
 using i18n::addressinput::NullStorage;
 using i18n::addressinput::OndemandSupplier;
 using i18n::addressinput::PreloadSupplier;
 using i18n::addressinput::scoped_ptr;
+using i18n::addressinput::TestdataSource;
 
 using i18n::addressinput::COUNTRY;
 using i18n::addressinput::ADMIN_AREA;
 using i18n::addressinput::LOCALITY;
-using i18n::addressinput::DEPENDENT_LOCALITY;
 using i18n::addressinput::POSTAL_CODE;
 using i18n::addressinput::STREET_ADDRESS;
 
@@ -69,8 +70,6 @@
  public:
   static ValidatorWrapper* Build() { return new OndemandValidatorWrapper; }
 
-  virtual ~OndemandValidatorWrapper() {}
-
   virtual void Validate(const AddressData& address,
                         bool allow_postal,
                         bool require_name,
@@ -88,9 +87,7 @@
 
  private:
   OndemandValidatorWrapper()
-      : supplier_(FakeDownloader::kFakeDataUrl,
-                  new FakeDownloader,
-                  new NullStorage),
+      : supplier_(new TestdataSource(false), new NullStorage),
         validator_(&supplier_) {}
 
   OndemandSupplier supplier_;
@@ -102,8 +99,6 @@
  public:
   static ValidatorWrapper* Build() { return new PreloadValidatorWrapper; }
 
-  virtual ~PreloadValidatorWrapper() {}
-
   virtual void Validate(const AddressData& address,
                         bool allow_postal,
                         bool require_name,
@@ -125,15 +120,11 @@
 
  private:
   PreloadValidatorWrapper()
-      : supplier_(FakeDownloader::kFakeAggregateDataUrl,
-                  new FakeDownloader,
-                  new NullStorage),
+      : supplier_(new TestdataSource(true), new NullStorage),
         validator_(&supplier_),
         loaded_(BuildCallback(this, &PreloadValidatorWrapper::Loaded)) {}
 
-  void Loaded(bool success, const std::string&, int) {
-    ASSERT_TRUE(success);
-  }
+  void Loaded(bool success, const std::string&, int) { ASSERT_TRUE(success); }
 
   PreloadSupplier supplier_;
   const AddressValidator validator_;
@@ -155,8 +146,6 @@
         validator_wrapper_((*GetParam())()),
         validated_(BuildCallback(this, &AddressValidatorTest::Validated)) {}
 
-  virtual ~AddressValidatorTest() {}
-
   void Validate() {
     validator_wrapper_->Validate(
         address_,
diff --git a/cpp/test/fake_downloader.cc b/cpp/test/fake_downloader.cc
deleted file mode 100644
index 0f3f8f1..0000000
--- a/cpp/test/fake_downloader.cc
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (C) 2013 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "fake_downloader.h"
-
-#include <cassert>
-#include <fstream>
-#include <map>
-#include <string>
-#include <utility>
-
-#include "lookup_key_util.h"
-
-namespace i18n {
-namespace addressinput {
-
-// static
-const char FakeDownloader::kFakeDataUrl[] = "test:///plain/";
-
-// static
-const char FakeDownloader::kFakeAggregateDataUrl[] = "test:///aggregate/";
-
-namespace {
-
-// The name of the test data file.
-const char kDataFileName[] = TEST_DATA_DIR "/countryinfo.txt";
-
-// The number of characters in the fake data URL prefix.
-const size_t kFakeDataUrlLength = sizeof FakeDownloader::kFakeDataUrl - 1;
-
-// The number of characters in the fake aggregate data URL prefix.
-const size_t kFakeAggregateDataUrlLength =
-    sizeof FakeDownloader::kFakeAggregateDataUrl - 1;
-
-// Each data key begins with this string. Example of a data key:
-//     data/CH/AG
-const char kDataKeyPrefix[] = "data/";
-
-// The number of characters in the data key prefix.
-const size_t kDataKeyPrefixLength = sizeof kDataKeyPrefix - 1;
-
-// The number of characters in a CLDR region code, e.g. 'CH'.
-const size_t kCldrRegionCodeLength = 2;
-
-// The number of characters in an aggregate data key, e.g. 'data/CH'.
-const size_t kAggregateDataKeyLength =
-    kDataKeyPrefixLength + kCldrRegionCodeLength;
-
-const LookupKeyUtil& GetLookupKeyUtil() {
-  static const LookupKeyUtil kLookupKeyUtil(FakeDownloader::kFakeDataUrl);
-  return kLookupKeyUtil;
-}
-
-const LookupKeyUtil& GetAggregateLookupKeyUtil() {
-  static const LookupKeyUtil kLookupKeyUtil(
-      FakeDownloader::kFakeAggregateDataUrl);
-  return kLookupKeyUtil;
-}
-
-std::map<std::string, std::string> InitData() {
-  std::map<std::string, std::string> data;
-  std::ifstream file(kDataFileName);
-  assert(file.is_open());
-
-  std::string line;
-  while (file.good()) {
-    // Example line from countryinfo.txt:
-    //     data/CH/AG={"name": "Aargau"}
-    std::getline(file, line);
-
-    std::string::size_type divider = line.find('=');
-    if (divider != std::string::npos) {
-      // Example key:
-      //     data/CH/AG
-      const std::string& key = line.substr(0, divider);
-
-      // Example value:
-      //     {"name": "Aargau"}
-      const std::string& value = line.substr(divider + 1);
-
-      // For example, map 'test:///plain/data/CH/AG' to '{"name": "Aargau"}'.
-      data.insert(std::make_pair(GetLookupKeyUtil().GetUrlForKey(key), value));
-
-      // Aggregate keys that begin with 'data/'. We don't aggregate keys that
-      // begin with 'example/' because example data is not used anywhere.
-      if (key.compare(0,
-                      kDataKeyPrefixLength,
-                      kDataKeyPrefix,
-                      kDataKeyPrefixLength) == 0) {
-        // Example aggregate URL:
-        //     test:///aggregate/data/CH
-        const std::string& aggregate_url = GetAggregateLookupKeyUtil()
-            .GetUrlForKey(key.substr(0, kAggregateDataKeyLength));
-
-        std::map<std::string, std::string>::iterator aggregate_data_it =
-            data.find(aggregate_url);
-        if (aggregate_data_it != data.end()) {
-          // Append more data to the aggregate string, for example:
-          //     , "data/CH/AG": {"name": "Aargau"}
-          aggregate_data_it->second.append(", \"" + key + "\": " + value);
-        } else {
-          // Begin a new aggregate string, for example:
-          //     {"data/CH/AG": {"name": "Aargau"}
-          data.insert(
-              std::make_pair(aggregate_url, "{\"" + key + "\": " + value));
-        }
-      }
-    }
-  }
-  file.close();
-
-  // Make the aggregate data strings valid. For example, this incomplete JSON
-  // data:
-  //     {"data/CH/AG": {"name": "Aargau"},
-  //      "data/CH": {"name": "SWITZERLAND"}
-  //
-  // becomes valid JSON data like so:
-  //
-  //     {"data/CH/AG": {"name": "Aargau"},
-  //      "data/CH": {"name": "SWITZERLAND"}}
-  for (std::map<std::string, std::string>::iterator data_it = data.begin();
-       data_it != data.end(); ++data_it) {
-    if (data_it->first.compare(0,
-                               kFakeAggregateDataUrlLength,
-                               FakeDownloader::kFakeAggregateDataUrl,
-                               kFakeAggregateDataUrlLength) == 0) {
-      data_it->second.append("}");
-    }
-  }
-
-  return data;
-}
-
-const std::map<std::string, std::string>& GetData() {
-  static const std::map<std::string, std::string> kData(InitData());
-  return kData;
-}
-
-}  // namespace
-
-FakeDownloader::FakeDownloader() {}
-
-FakeDownloader::~FakeDownloader() {}
-
-void FakeDownloader::Download(const std::string& url,
-                              const Callback& downloaded) const {
-  std::map<std::string, std::string>::const_iterator data_it =
-      GetData().find(url);
-  bool success = data_it != GetData().end();
-  std::string* data = NULL;
-  if (success) {
-    data = new std::string(data_it->second);
-  } else if (GetLookupKeyUtil().IsValidationDataUrl(url) ||
-             GetAggregateLookupKeyUtil().IsValidationDataUrl(url)) {
-    // URLs that start with "https://i18napis.appspot.com/ssl-address/" or
-    // "https://i18napis.appspot.com/ssl-aggregate-address/" prefix, but do not
-    // have associated data will always return "{}" with status code 200.
-    // FakeDownloader imitates this behavior for URLs that start with
-    // "test://address/" and "test://aggregate-address/" prefixes.
-    success = true;
-    data = new std::string("{}");
-  }
-  downloaded(success, url, data);
-}
-
-}  // namespace addressinput
-}  // namespace i18n
diff --git a/cpp/test/fake_downloader.h b/cpp/test/fake_downloader.h
deleted file mode 100644
index 111ce7a..0000000
--- a/cpp/test/fake_downloader.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (C) 2013 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// A fake downloader object to use in tests. Reads data from a file instead of
-// downloading it from a server.
-
-#ifndef I18N_ADDRESSINPUT_TEST_FAKE_DOWNLOADER_H_
-#define I18N_ADDRESSINPUT_TEST_FAKE_DOWNLOADER_H_
-
-#include <libaddressinput/downloader.h>
-
-#include <string>
-
-namespace i18n {
-namespace addressinput {
-
-// "Downloads" serialized validation rules from a test data file. Sample usage:
-//    class MyClass {
-//     public:
-//      MyClass() : downloader_(),
-//                  callback_(BuildCallback(this, &MyClass::OnDownloaded)) {}
-//
-//      ~MyClass() {}
-//
-//      void GetData(const std::string& key) {
-//        downloader_.Download(std::string(FakeDownloader::kFakeDataUrl) + key,
-//                             *callback_);
-//      }
-//
-//     private:
-//      void OnDownloaded(bool success,
-//                        const std::string& url,
-//                        std::string* data) {
-//        ...
-//        delete data;
-//      }
-//
-//      FakeDownloader downloader_;
-//      scoped_ptr<Downloader::Callback> callback_;
-//
-//      DISALLOW_COPY_AND_ASSIGN(MyClass);
-//    };
-class FakeDownloader : public Downloader {
- public:
-  // The fake data URL to be used in tests for retrieving one key at a time.
-  static const char kFakeDataUrl[];
-
-  // The fake data URL to be used in tests for retrieving aggregate data, which
-  // is a JSON dictionary that maps from keys to dictionaries of what you would
-  // normally get from kFakeDataUrl.
-  static const char kFakeAggregateDataUrl[];
-
-  FakeDownloader();
-  virtual ~FakeDownloader();
-
-  // Downloader implementation.
-  virtual void Download(const std::string& url,
-                        const Callback& downloaded) const;
-};
-
-}  // namespace addressinput
-}  // namespace i18n
-
-#endif  // I18N_ADDRESSINPUT_TEST_FAKE_DOWNLOADER_H_
diff --git a/cpp/test/fake_downloader_test.cc b/cpp/test/fake_downloader_test.cc
deleted file mode 100644
index 2d88acc..0000000
--- a/cpp/test/fake_downloader_test.cc
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright (C) 2013 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "fake_downloader.h"
-
-#include <libaddressinput/callback.h>
-#include <libaddressinput/downloader.h>
-#include <libaddressinput/util/scoped_ptr.h>
-
-#include <cstddef>
-#include <string>
-
-#include <gtest/gtest.h>
-
-#include "region_data_constants.h"
-
-namespace {
-
-using i18n::addressinput::BuildCallback;
-using i18n::addressinput::Downloader;
-using i18n::addressinput::FakeDownloader;
-using i18n::addressinput::RegionDataConstants;
-using i18n::addressinput::scoped_ptr;
-
-// Tests for FakeDownloader object.
-class FakeDownloaderTest : public testing::TestWithParam<std::string> {
- protected:
-  FakeDownloaderTest() : downloader_(), success_(false), url_(), data_() {}
-  virtual ~FakeDownloaderTest() {}
-
-  Downloader::Callback* BuildCallback() {
-    return ::BuildCallback(this, &FakeDownloaderTest::OnDownloaded);
-  }
-
-  FakeDownloader downloader_;
-  bool success_;
-  std::string url_;
-  std::string data_;
-
- private:
-  void OnDownloaded(bool success, const std::string& url, std::string* data) {
-    ASSERT_FALSE(success && data == NULL);
-    success_ = success;
-    url_ = url;
-    if (data != NULL) {
-      data_ = *data;
-      delete data;
-    }
-  }
-};
-
-// Returns testing::AssertionSuccess if |data| is valid downloaded data for
-// |key|.
-testing::AssertionResult DataIsValid(const std::string& data,
-                                     const std::string& key) {
-  if (data.empty()) {
-    return testing::AssertionFailure() << "empty data";
-  }
-
-  std::string expected_data_begin = "{\"id\":\"" + key + "\"";
-  if (data.compare(0, expected_data_begin.length(), expected_data_begin) != 0) {
-    return testing::AssertionFailure() << data << " does not begin with "
-                                       << expected_data_begin;
-  }
-
-  // Verify that the data ends on "}.
-  static const char kDataEnd[] = "\"}";
-  static const size_t kDataEndLength = sizeof kDataEnd - 1;
-  if (data.compare(data.length() - kDataEndLength,
-                   kDataEndLength,
-                   kDataEnd,
-                   kDataEndLength) != 0) {
-    return testing::AssertionFailure() << data << " does not end with "
-                                       << kDataEnd;
-  }
-
-  return testing::AssertionSuccess();
-}
-
-// Verifies that FakeDownloader downloads valid data for a region code.
-TEST_P(FakeDownloaderTest, FakeDownloaderHasValidDataForRegion) {
-  std::string key = "data/" + GetParam();
-  std::string url = std::string(FakeDownloader::kFakeDataUrl) + key;
-  scoped_ptr<Downloader::Callback> callback(BuildCallback());
-  downloader_.Download(url, *callback);
-
-  EXPECT_TRUE(success_);
-  EXPECT_EQ(url, url_);
-  EXPECT_TRUE(DataIsValid(data_, key));
-};
-
-// Returns testing::AssertionSuccess if |data| is valid aggregated downloaded
-// data for |key|.
-testing::AssertionResult AggregateDataIsValid(const std::string& data,
-                                              const std::string& key) {
-  if (data.empty()) {
-    return testing::AssertionFailure() << "empty data";
-  }
-
-  std::string expected_data_begin = "{\"" + key;
-  if (data.compare(0, expected_data_begin.length(), expected_data_begin) != 0) {
-    return testing::AssertionFailure() << data << " does not begin with "
-                                       << expected_data_begin;
-  }
-
-  // Verify that the data ends on "}}.
-  static const char kDataEnd[] = "\"}}";
-  static const size_t kDataEndLength = sizeof kDataEnd - 1;
-  if (data.compare(data.length() - kDataEndLength,
-                   kDataEndLength,
-                   kDataEnd,
-                   kDataEndLength) != 0) {
-    return testing::AssertionFailure() << data << " does not end with "
-                                       << kDataEnd;
-  }
-
-  return testing::AssertionSuccess();
-}
-
-// Verifies that FakeDownloader downloads valid aggregated data for a region
-// code.
-TEST_P(FakeDownloaderTest, FakeDownloaderHasValidAggregatedDataForRegion) {
-  std::string key = "data/" + GetParam();
-  std::string url = std::string(FakeDownloader::kFakeAggregateDataUrl) + key;
-  scoped_ptr<Downloader::Callback> callback(BuildCallback());
-  downloader_.Download(url, *callback);
-
-  EXPECT_TRUE(success_);
-  EXPECT_EQ(url, url_);
-  EXPECT_TRUE(AggregateDataIsValid(data_, key));
-};
-
-// Test all region codes.
-INSTANTIATE_TEST_CASE_P(
-    AllRegions, FakeDownloaderTest,
-    testing::ValuesIn(RegionDataConstants::GetRegionCodes()));
-
-// Verifies that the key "data" also contains valid data.
-TEST_F(FakeDownloaderTest, DownloadExistingData) {
-  static const std::string kKey = "data";
-  static const std::string kUrl =
-      std::string(FakeDownloader::kFakeDataUrl) + kKey;
-  scoped_ptr<Downloader::Callback> callback(BuildCallback());
-  downloader_.Download(kUrl, *callback);
-
-  EXPECT_TRUE(success_);
-  EXPECT_EQ(kUrl, url_);
-  EXPECT_TRUE(DataIsValid(data_, kKey));
-}
-
-// Verifies that downloading a missing key will return "{}".
-TEST_F(FakeDownloaderTest, DownloadMissingKeyReturnsEmptyDictionary) {
-  static const std::string kJunkUrl =
-      std::string(FakeDownloader::kFakeDataUrl) + "junk";
-  scoped_ptr<Downloader::Callback> callback(BuildCallback());
-  downloader_.Download(kJunkUrl, *callback);
-
-  EXPECT_TRUE(success_);
-  EXPECT_EQ(kJunkUrl, url_);
-  EXPECT_EQ("{}", data_);
-}
-
-// Verifies that aggregate downloading of a missing key will also return "{}".
-TEST_F(FakeDownloaderTest, AggregateDownloadMissingKeyReturnsEmptyDictionary) {
-  static const std::string kJunkUrl =
-      std::string(FakeDownloader::kFakeAggregateDataUrl) + "junk";
-  scoped_ptr<Downloader::Callback> callback(BuildCallback());
-  downloader_.Download(kJunkUrl, *callback);
-
-  EXPECT_TRUE(success_);
-  EXPECT_EQ(kJunkUrl, url_);
-  EXPECT_EQ("{}", data_);
-}
-
-// Verifies that downloading an empty key will return "{}".
-TEST_F(FakeDownloaderTest, DownloadEmptyKeyReturnsEmptyDictionary) {
-  static const std::string kPrefixOnlyUrl = FakeDownloader::kFakeDataUrl;
-  scoped_ptr<Downloader::Callback> callback(BuildCallback());
-  downloader_.Download(kPrefixOnlyUrl, *callback);
-
-  EXPECT_TRUE(success_);
-  EXPECT_EQ(kPrefixOnlyUrl, url_);
-  EXPECT_EQ("{}", data_);
-}
-
-// Verifies that downloading a real URL fails.
-TEST_F(FakeDownloaderTest, DownloadRealUrlFals) {
-  static const std::string kRealUrl = "http://www.google.com/";
-  scoped_ptr<Downloader::Callback> callback(BuildCallback());
-  downloader_.Download(kRealUrl, *callback);
-
-  EXPECT_FALSE(success_);
-  EXPECT_EQ(kRealUrl, url_);
-  EXPECT_TRUE(data_.empty());
-}
-
-}  // namespace
diff --git a/cpp/test/fake_storage.h b/cpp/test/fake_storage.h
index 5e07cb0..3a164c4 100644
--- a/cpp/test/fake_storage.h
+++ b/cpp/test/fake_storage.h
@@ -19,6 +19,7 @@
 #define I18N_ADDRESSINPUT_FAKE_STORAGE_H_
 
 #include <libaddressinput/storage.h>
+#include <libaddressinput/util/basictypes.h>
 
 #include <map>
 #include <string>
@@ -30,7 +31,7 @@
 //    class MyClass {
 //     public:
 //      MyClass() : storage_(),
-//                  callback(BuildCallback(this, &MyClass::OnDataReady)) {}
+//                  data_ready_(BuildCallback(this, &MyClass::OnDataReady)) {}
 //
 //      ~MyClass() {}
 //
@@ -39,7 +40,7 @@
 //      }
 //
 //      void Read() {
-//        storage_.Get("key", *callback_);
+//        storage_.Get("key", *data_ready_);
 //      }
 //
 //     private:
@@ -51,7 +52,7 @@
 //      }
 //
 //      FakeStorage storage_;
-//      scoped_ptr<Storage::Callback> callback_;
+//      const scoped_ptr<const Storage::Callback> data_ready_;
 //
 //      DISALLOW_COPY_AND_ASSIGN(MyClass);
 //    };
@@ -66,6 +67,7 @@
 
  private:
   std::map<std::string, std::string*> data_;
+  DISALLOW_COPY_AND_ASSIGN(FakeStorage);
 };
 
 }  // namespace addressinput
diff --git a/cpp/test/fake_storage_test.cc b/cpp/test/fake_storage_test.cc
index 49663ca..5905f02 100644
--- a/cpp/test/fake_storage_test.cc
+++ b/cpp/test/fake_storage_test.cc
@@ -16,6 +16,7 @@
 
 #include <libaddressinput/callback.h>
 #include <libaddressinput/storage.h>
+#include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
 
 #include <cstddef>
@@ -33,22 +34,21 @@
 // Tests for FakeStorage object.
 class FakeStorageTest : public testing::Test {
  protected:
-  FakeStorageTest() : storage_(), success_(false), key_(), data_() {}
-  virtual ~FakeStorageTest() {}
-
-  Storage::Callback* BuildCallback() {
-    return ::BuildCallback(this, &FakeStorageTest::OnDataReady);
-  }
+  FakeStorageTest()
+      : storage_(),
+        success_(false),
+        key_(),
+        data_(),
+        data_ready_(BuildCallback(this, &FakeStorageTest::OnDataReady)) {}
 
   FakeStorage storage_;
   bool success_;
   std::string key_;
   std::string data_;
+  const scoped_ptr<const Storage::Callback> data_ready_;
 
  private:
-  void OnDataReady(bool success,
-                   const std::string& key,
-                   std::string* data) {
+  void OnDataReady(bool success, const std::string& key, std::string* data) {
     ASSERT_FALSE(success && data == NULL);
     success_ = success;
     key_ = key;
@@ -57,11 +57,12 @@
       delete data;
     }
   }
+
+  DISALLOW_COPY_AND_ASSIGN(FakeStorageTest);
 };
 
 TEST_F(FakeStorageTest, GetWithoutPutReturnsEmptyData) {
-  scoped_ptr<Storage::Callback> callback(BuildCallback());
-  storage_.Get("key", *callback);
+  storage_.Get("key", *data_ready_);
 
   EXPECT_FALSE(success_);
   EXPECT_EQ("key", key_);
@@ -70,9 +71,7 @@
 
 TEST_F(FakeStorageTest, GetReturnsWhatWasPut) {
   storage_.Put("key", new std::string("value"));
-
-  scoped_ptr<Storage::Callback> callback(BuildCallback());
-  storage_.Get("key", *callback);
+  storage_.Get("key", *data_ready_);
 
   EXPECT_TRUE(success_);
   EXPECT_EQ("key", key_);
@@ -82,9 +81,7 @@
 TEST_F(FakeStorageTest, SecondPutOverwritesData) {
   storage_.Put("key", new std::string("bad-value"));
   storage_.Put("key", new std::string("good-value"));
-
-  scoped_ptr<Storage::Callback> callback(BuildCallback());
-  storage_.Get("key", *callback);
+  storage_.Get("key", *data_ready_);
 
   EXPECT_TRUE(success_);
   EXPECT_EQ("key", key_);
diff --git a/cpp/test/format_element_test.cc b/cpp/test/format_element_test.cc
index f4b8ae5..d23203f 100644
--- a/cpp/test/format_element_test.cc
+++ b/cpp/test/format_element_test.cc
@@ -14,6 +14,8 @@
 
 #include "format_element.h"
 
+#include <libaddressinput/address_field.h>
+
 #include <sstream>
 
 #include <gtest/gtest.h>
diff --git a/cpp/test/language_test.cc b/cpp/test/language_test.cc
index 197459e..502031b 100644
--- a/cpp/test/language_test.cc
+++ b/cpp/test/language_test.cc
@@ -14,6 +14,8 @@
 
 #include "language.h"
 
+#include <libaddressinput/util/basictypes.h>
+
 #include <string>
 
 #include <gtest/gtest.h>
@@ -40,7 +42,13 @@
   const bool expected_has_latin_script;
 };
 
-class LanguageTest : public testing::TestWithParam<LanguageTestCase> {};
+class LanguageTest : public testing::TestWithParam<LanguageTestCase> {
+ protected:
+  LanguageTest() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LanguageTest);
+};
 
 TEST_P(LanguageTest, ExtractedDataIsCorrect) {
   Language language(GetParam().input_language_tag);
diff --git a/cpp/test/localization_test.cc b/cpp/test/localization_test.cc
index 2ed4b07..1eba5b8 100644
--- a/cpp/test/localization_test.cc
+++ b/cpp/test/localization_test.cc
@@ -17,8 +17,10 @@
 #include <libaddressinput/address_data.h>
 #include <libaddressinput/address_field.h>
 #include <libaddressinput/address_problem.h>
+#include <libaddressinput/util/basictypes.h>
 
 #include <string>
+#include <vector>
 
 #include <gtest/gtest.h>
 
@@ -29,27 +31,33 @@
 
 using i18n::addressinput::AddressData;
 using i18n::addressinput::AddressField;
-using i18n::addressinput::AddressProblem;
-using i18n::addressinput::ADMIN_AREA;
-using i18n::addressinput::COUNTRY;
-using i18n::addressinput::DEPENDENT_LOCALITY;
-using i18n::addressinput::INVALID_FORMAT;
 using i18n::addressinput::INVALID_MESSAGE_ID;
-using i18n::addressinput::LOCALITY;
 using i18n::addressinput::Localization;
-using i18n::addressinput::MISMATCHING_VALUE;
-using i18n::addressinput::MISSING_REQUIRED_FIELD;
-using i18n::addressinput::POSTAL_CODE;
-using i18n::addressinput::RECIPIENT;
+
+using i18n::addressinput::COUNTRY;
+using i18n::addressinput::ADMIN_AREA;
+using i18n::addressinput::LOCALITY;
+using i18n::addressinput::DEPENDENT_LOCALITY;
 using i18n::addressinput::SORTING_CODE;
+using i18n::addressinput::POSTAL_CODE;
 using i18n::addressinput::STREET_ADDRESS;
+using i18n::addressinput::ORGANIZATION;
+using i18n::addressinput::RECIPIENT;
+
+using i18n::addressinput::MISSING_REQUIRED_FIELD;
 using i18n::addressinput::UNKNOWN_VALUE;
+using i18n::addressinput::INVALID_FORMAT;
+using i18n::addressinput::MISMATCHING_VALUE;
 using i18n::addressinput::USES_P_O_BOX;
 
 // Tests for Localization object.
 class LocalizationTest : public testing::TestWithParam<int> {
  protected:
+  LocalizationTest() {}
   Localization localization_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LocalizationTest);
 };
 
 // Verifies that a custom message getter can be used.
@@ -96,6 +104,7 @@
         IDS_LIBADDRESSINPUT_PREFECTURE,
         IDS_LIBADDRESSINPUT_PROVINCE,
         IDS_LIBADDRESSINPUT_STATE,
+        IDS_LIBADDRESSINPUT_ORGANIZATION_LABEL,
         IDS_LIBADDRESSINPUT_RECIPIENT_LABEL,
         IDS_LIBADDRESSINPUT_MISSING_REQUIRED_FIELD,
         IDS_LIBADDRESSINPUT_MISSING_REQUIRED_POSTAL_CODE_EXAMPLE_AND_URL,
@@ -125,9 +134,9 @@
   Localization localization;
   AddressData address;
   address.region_code = "CH";
-  EXPECT_EQ(std::string("You must provide a postal code, for example 2544.") +
-            " Don't know your postal code? Find it out" +
-            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">" +
+  EXPECT_EQ("You must provide a postal code, for example 2544."
+            " Don't know your postal code? Find it out"
+            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">"
             "here</a>.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          MISSING_REQUIRED_FIELD, true, true));
@@ -146,9 +155,9 @@
   Localization localization;
   AddressData address;
   address.region_code = "US";
-  EXPECT_EQ(std::string("You must provide a ZIP code, for example 95014.") +
-            " Don't know your ZIP code? Find it out" +
-            " <a href=\"https://tools.usps.com/go/ZipLookupAction!" +
+  EXPECT_EQ("You must provide a ZIP code, for example 95014."
+            " Don't know your ZIP code? Find it out"
+            " <a href=\"https://tools.usps.com/go/ZipLookupAction!"
             "input.action\">here</a>.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          MISSING_REQUIRED_FIELD, true, true));
@@ -174,6 +183,7 @@
   other_fields.push_back(DEPENDENT_LOCALITY);
   other_fields.push_back(SORTING_CODE);
   other_fields.push_back(STREET_ADDRESS);
+  other_fields.push_back(ORGANIZATION);
   other_fields.push_back(RECIPIENT);
   for (std::vector<AddressField>::iterator it = other_fields.begin();
        it != other_fields.end(); it++) {
@@ -204,116 +214,133 @@
   address_line.push_back("bad address line 1");
   address_line.push_back("bad address line 2");
   address.address_line = address_line;
+  address.organization = "bad organization";
   address.recipient = "bad recipient";
-  EXPECT_EQ(std::string("US ") +
+  EXPECT_EQ("US "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, COUNTRY, UNKNOWN_VALUE, true, true));
-  EXPECT_EQ(std::string("US ") +
+  EXPECT_EQ("US "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, COUNTRY, UNKNOWN_VALUE, true, false));
-  EXPECT_EQ(std::string("US ") +
+  EXPECT_EQ("US "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, COUNTRY, UNKNOWN_VALUE, false, false));
-  EXPECT_EQ(std::string("US ") +
+  EXPECT_EQ("US "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, COUNTRY, UNKNOWN_VALUE, false, true));
-  EXPECT_EQ(std::string("bad admin area ") +
+  EXPECT_EQ("bad admin area "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, ADMIN_AREA, UNKNOWN_VALUE, true, true));
-  EXPECT_EQ(std::string("bad admin area ") +
+  EXPECT_EQ("bad admin area "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, ADMIN_AREA, UNKNOWN_VALUE, true, false));
-  EXPECT_EQ(std::string("bad admin area ") +
+  EXPECT_EQ("bad admin area "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, ADMIN_AREA, UNKNOWN_VALUE, false, false));
-  EXPECT_EQ(std::string("bad admin area ") +
+  EXPECT_EQ("bad admin area "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, ADMIN_AREA, UNKNOWN_VALUE, false, true));
-  EXPECT_EQ(std::string("bad locality ") +
+  EXPECT_EQ("bad locality "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, LOCALITY, UNKNOWN_VALUE, true, true));
-  EXPECT_EQ(std::string("bad locality ") +
+  EXPECT_EQ("bad locality "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, LOCALITY, UNKNOWN_VALUE, true, false));
-  EXPECT_EQ(std::string("bad locality ") +
+  EXPECT_EQ("bad locality "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, LOCALITY, UNKNOWN_VALUE, false, false));
-  EXPECT_EQ(std::string("bad locality ") +
+  EXPECT_EQ("bad locality "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, LOCALITY, UNKNOWN_VALUE, false, true));
-  EXPECT_EQ(std::string("bad dependent locality ") +
+  EXPECT_EQ("bad dependent locality "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, DEPENDENT_LOCALITY, UNKNOWN_VALUE, true, true));
-  EXPECT_EQ(std::string("bad dependent locality ") +
+  EXPECT_EQ("bad dependent locality "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, DEPENDENT_LOCALITY, UNKNOWN_VALUE, true, false));
-  EXPECT_EQ(std::string("bad dependent locality ") +
+  EXPECT_EQ("bad dependent locality "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, DEPENDENT_LOCALITY, UNKNOWN_VALUE, false, false));
-  EXPECT_EQ(std::string("bad dependent locality ") +
+  EXPECT_EQ("bad dependent locality "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, DEPENDENT_LOCALITY, UNKNOWN_VALUE, false, true));
-  EXPECT_EQ(std::string("bad sorting code ") +
+  EXPECT_EQ("bad sorting code "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, SORTING_CODE, UNKNOWN_VALUE, true, true));
-  EXPECT_EQ(std::string("bad sorting code ") +
+  EXPECT_EQ("bad sorting code "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, SORTING_CODE, UNKNOWN_VALUE, true, false));
-  EXPECT_EQ(std::string("bad sorting code ") +
+  EXPECT_EQ("bad sorting code "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, SORTING_CODE, UNKNOWN_VALUE, false, false));
-  EXPECT_EQ(std::string("bad sorting code ") +
+  EXPECT_EQ("bad sorting code "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, SORTING_CODE, UNKNOWN_VALUE, false, true));
-  EXPECT_EQ(std::string("bad address line 1 ") +
+  EXPECT_EQ("bad address line 1 "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, STREET_ADDRESS, UNKNOWN_VALUE, true, true));
-  EXPECT_EQ(std::string("bad address line 1 ") +
+  EXPECT_EQ("bad address line 1 "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, STREET_ADDRESS, UNKNOWN_VALUE, true, false));
-  EXPECT_EQ(std::string("bad address line 1 ") +
+  EXPECT_EQ("bad address line 1 "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, STREET_ADDRESS, UNKNOWN_VALUE, false, false));
-  EXPECT_EQ(std::string("bad address line 1 ") +
+  EXPECT_EQ("bad address line 1 "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, STREET_ADDRESS, UNKNOWN_VALUE, false, true));
-  EXPECT_EQ(std::string("bad recipient ") +
+  EXPECT_EQ("bad organization "
+            "is not recognized as a known value for this field.",
+            localization.GetErrorMessage(
+                address, ORGANIZATION, UNKNOWN_VALUE, true, true));
+  EXPECT_EQ("bad organization "
+            "is not recognized as a known value for this field.",
+            localization.GetErrorMessage(
+                address, ORGANIZATION, UNKNOWN_VALUE, true, false));
+  EXPECT_EQ("bad organization "
+            "is not recognized as a known value for this field.",
+            localization.GetErrorMessage(
+                address, ORGANIZATION, UNKNOWN_VALUE, false, false));
+  EXPECT_EQ("bad organization "
+            "is not recognized as a known value for this field.",
+            localization.GetErrorMessage(
+                address, ORGANIZATION, UNKNOWN_VALUE, false, true));
+  EXPECT_EQ("bad recipient "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, RECIPIENT, UNKNOWN_VALUE, true, true));
-  EXPECT_EQ(std::string("bad recipient ") +
+  EXPECT_EQ("bad recipient "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, RECIPIENT, UNKNOWN_VALUE, true, false));
-  EXPECT_EQ(std::string("bad recipient ") +
+  EXPECT_EQ("bad recipient "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, RECIPIENT, UNKNOWN_VALUE, false, false));
-  EXPECT_EQ(std::string("bad recipient ") +
+  EXPECT_EQ("bad recipient "
             "is not recognized as a known value for this field.",
             localization.GetErrorMessage(
                 address, RECIPIENT, UNKNOWN_VALUE, false, true));
@@ -323,14 +350,14 @@
   Localization localization;
   AddressData address;
   address.region_code = "CH";
-  EXPECT_EQ(std::string("This postal code format is not recognized. Example ") +
-            "of a valid postal code: 2544." +
-            " Don't know your postal code? Find it out" +
-            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">" +
+  EXPECT_EQ("This postal code format is not recognized. Example "
+            "of a valid postal code: 2544."
+            " Don't know your postal code? Find it out"
+            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">"
             "here</a>.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          INVALID_FORMAT, true, true));
-  EXPECT_EQ(std::string("This postal code format is not recognized. Example ") +
+  EXPECT_EQ("This postal code format is not recognized. Example "
             "of a valid postal code: 2544.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          INVALID_FORMAT, true, false));
@@ -346,14 +373,14 @@
   Localization localization;
   AddressData address;
   address.region_code = "US";
-  EXPECT_EQ(std::string("This ZIP code format is not recognized. Example of ") +
-            "a valid ZIP code: 95014." +
-            " Don't know your ZIP code? Find it out" +
-            " <a href=\"https://tools.usps.com/go/ZipLookupAction!" +
+  EXPECT_EQ("This ZIP code format is not recognized. Example of "
+            "a valid ZIP code: 95014."
+            " Don't know your ZIP code? Find it out"
+            " <a href=\"https://tools.usps.com/go/ZipLookupAction!"
             "input.action\">here</a>.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          INVALID_FORMAT, true, true));
-  EXPECT_EQ(std::string("This ZIP code format is not recognized. Example of ") +
+  EXPECT_EQ("This ZIP code format is not recognized. Example of "
             "a valid ZIP code: 95014.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          INVALID_FORMAT, true, false));
@@ -369,25 +396,25 @@
   Localization localization;
   AddressData address;
   address.region_code = "CH";
-  EXPECT_EQ(std::string("This postal code does not appear to match the rest ") +
-            "of this address." +
-            " Don't know your postal code? Find it out" +
-            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">" +
+  EXPECT_EQ("This postal code does not appear to match the rest "
+            "of this address."
+            " Don't know your postal code? Find it out"
+            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">"
             "here</a>.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          MISMATCHING_VALUE, true, true));
-  EXPECT_EQ(std::string("This postal code does not appear to match the rest ") +
+  EXPECT_EQ("This postal code does not appear to match the rest "
             "of this address.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          MISMATCHING_VALUE, true, false));
-  EXPECT_EQ(std::string("This postal code does not appear to match the rest ") +
+  EXPECT_EQ("This postal code does not appear to match the rest "
             "of this address.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          MISMATCHING_VALUE, false, false));
-  EXPECT_EQ(std::string("This postal code does not appear to match the rest ") +
-            "of this address." +
-            " Don't know your postal code? Find it out" +
-            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">" +
+  EXPECT_EQ("This postal code does not appear to match the rest "
+            "of this address."
+            " Don't know your postal code? Find it out"
+            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">"
             "here</a>.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          MISMATCHING_VALUE, false, true));
@@ -397,25 +424,25 @@
   Localization localization;
   AddressData address;
   address.region_code = "US";
-  EXPECT_EQ(std::string("This ZIP code does not appear to match the rest of ") +
-            "this address." +
-            " Don't know your ZIP code? Find it out" +
-            " <a href=\"https://tools.usps.com/go/ZipLookupAction!" +
+  EXPECT_EQ("This ZIP code does not appear to match the rest of "
+            "this address."
+            " Don't know your ZIP code? Find it out"
+            " <a href=\"https://tools.usps.com/go/ZipLookupAction!"
             "input.action\">here</a>.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          MISMATCHING_VALUE, true, true));
-  EXPECT_EQ(std::string("This ZIP code does not appear to match the rest of ") +
+  EXPECT_EQ("This ZIP code does not appear to match the rest of "
             "this address.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          MISMATCHING_VALUE, true, false));
-  EXPECT_EQ(std::string("This ZIP code does not appear to match the rest of ") +
+  EXPECT_EQ("This ZIP code does not appear to match the rest of "
             "this address.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          MISMATCHING_VALUE, false, false));
-  EXPECT_EQ(std::string("This ZIP code does not appear to match the rest of ") +
-            "this address." +
-            " Don't know your ZIP code? Find it out" +
-            " <a href=\"https://tools.usps.com/go/ZipLookupAction!" +
+  EXPECT_EQ("This ZIP code does not appear to match the rest of "
+            "this address."
+            " Don't know your ZIP code? Find it out"
+            " <a href=\"https://tools.usps.com/go/ZipLookupAction!"
             "input.action\">here</a>.",
             localization.GetErrorMessage(address, POSTAL_CODE,
                                          MISMATCHING_VALUE, false, true));
@@ -432,26 +459,27 @@
   other_fields.push_back(DEPENDENT_LOCALITY);
   other_fields.push_back(SORTING_CODE);
   other_fields.push_back(STREET_ADDRESS);
+  other_fields.push_back(ORGANIZATION);
   other_fields.push_back(RECIPIENT);
   for (std::vector<AddressField>::iterator it = other_fields.begin();
        it != other_fields.end(); it++) {
-    EXPECT_EQ(std::string("This address line appears to contain a post ") +
-              "office box. Please use a street" +
+    EXPECT_EQ("This address line appears to contain a post "
+              "office box. Please use a street"
               " or building address.",
               localization.GetErrorMessage(
                   address, *it, USES_P_O_BOX, true, true));
-    EXPECT_EQ(std::string("This address line appears to contain a post ") +
-              "office box. Please use a street" +
+    EXPECT_EQ("This address line appears to contain a post "
+              "office box. Please use a street"
               " or building address.",
               localization.GetErrorMessage(
                   address, *it, USES_P_O_BOX, true, false));
-    EXPECT_EQ(std::string("This address line appears to contain a post ") +
-              "office box. Please use a street" +
+    EXPECT_EQ("This address line appears to contain a post "
+              "office box. Please use a street"
               " or building address.",
               localization.GetErrorMessage(
                   address, *it, USES_P_O_BOX, false, false));
-    EXPECT_EQ(std::string("This address line appears to contain a post ") +
-              "office box. Please use a street" +
+    EXPECT_EQ("This address line appears to contain a post "
+              "office box. Please use a street"
               " or building address.",
               localization.GetErrorMessage(
                   address, *it, USES_P_O_BOX, false, true));
diff --git a/cpp/test/lookup_key_test.cc b/cpp/test/lookup_key_test.cc
index 18668f8..3f1fab6 100644
--- a/cpp/test/lookup_key_test.cc
+++ b/cpp/test/lookup_key_test.cc
@@ -17,6 +17,8 @@
 #include <libaddressinput/address_data.h>
 #include <libaddressinput/util/basictypes.h>
 
+#include <cstddef>
+
 #include <gtest/gtest.h>
 
 namespace {
diff --git a/cpp/test/lookup_key_util_test.cc b/cpp/test/lookup_key_util_test.cc
deleted file mode 100644
index a210bd5..0000000
--- a/cpp/test/lookup_key_util_test.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2013 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "lookup_key_util.h"
-
-#include <gtest/gtest.h>
-
-namespace {
-
-using i18n::addressinput::LookupKeyUtil;
-
-TEST(LookupKeyUtilTest, GetUrlForKey) {
-  const LookupKeyUtil util("test:///");
-  EXPECT_EQ("test:///", util.GetUrlForKey(""));
-  EXPECT_EQ("test:///data", util.GetUrlForKey("data"));
-  EXPECT_EQ("test:///data/US", util.GetUrlForKey("data/US"));
-  EXPECT_EQ("test:///data/CA--fr", util.GetUrlForKey("data/CA--fr"));
-}
-
-TEST(LookupKeyUtilTest, GetKeyForUrl) {
-  const LookupKeyUtil util("test:///");
-  EXPECT_EQ("", util.GetKeyForUrl("test://"));
-  EXPECT_EQ("", util.GetKeyForUrl("http://www.google.com/"));
-  EXPECT_EQ("", util.GetKeyForUrl(""));
-  EXPECT_EQ("", util.GetKeyForUrl("test:///"));
-  EXPECT_EQ("data", util.GetKeyForUrl("test:///data"));
-  EXPECT_EQ("data/US", util.GetKeyForUrl("test:///data/US"));
-  EXPECT_EQ("data/CA--fr", util.GetKeyForUrl("test:///data/CA--fr"));
-}
-
-TEST(LookupKeyUtilTest, IsValidationDataUrl) {
-  const LookupKeyUtil util("test:///");
-  EXPECT_FALSE(util.IsValidationDataUrl("test://"));
-  EXPECT_FALSE(util.IsValidationDataUrl("http://www.google.com/"));
-  EXPECT_FALSE(util.IsValidationDataUrl(""));
-  EXPECT_TRUE(util.IsValidationDataUrl("test:///"));
-  EXPECT_TRUE(util.IsValidationDataUrl("test:///data"));
-  EXPECT_TRUE(util.IsValidationDataUrl("test:///data/US"));
-  EXPECT_TRUE(util.IsValidationDataUrl("test:///data/CA--fr"));
-}
-
-}  // namespace
diff --git a/cpp/test/mock_downloader.cc b/cpp/test/mock_downloader.cc
deleted file mode 100644
index 71256aa..0000000
--- a/cpp/test/mock_downloader.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (C) 2014 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "mock_downloader.h"
-
-#include <cassert>
-#include <cstddef>
-#include <map>
-#include <string>
-
-namespace i18n {
-namespace addressinput {
-
-// static
-const char MockDownloader::kMockDataUrl[] = "mock:///";
-
-namespace {
-
-// The number of characters in the mock data URL prefix.
-const size_t kMockDataUrlLength = sizeof MockDownloader::kMockDataUrl - 1;
-
-}  // namespace
-
-MockDownloader::MockDownloader() {}
-
-MockDownloader::~MockDownloader() {}
-
-void MockDownloader::Download(const std::string& url,
-                              const Callback& downloaded) const {
-  assert(url.compare(0, kMockDataUrlLength, kMockDataUrl) == 0);
-  std::string key(url, kMockDataUrlLength);
-  std::map<std::string, std::string>::const_iterator it = data_.find(key);
-  bool success = it != data_.end();
-  downloaded(success, url, success ? new std::string(it->second) : NULL);
-}
-
-}  // namespace addressinput
-}  // namespace i18n
diff --git a/cpp/test/mock_downloader.h b/cpp/test/mock_downloader.h
deleted file mode 100644
index b423660..0000000
--- a/cpp/test/mock_downloader.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (C) 2014 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// A mock downloader object to use in tests.
-
-#ifndef I18N_ADDRESSINPUT_TEST_MOCK_DOWNLOADER_H_
-#define I18N_ADDRESSINPUT_TEST_MOCK_DOWNLOADER_H_
-
-#include <libaddressinput/downloader.h>
-
-#include <map>
-#include <string>
-
-#include <libaddressinput/util/basictypes.h>
-
-namespace i18n {
-namespace addressinput {
-
-// "Downloads" serialized validation rules from a key-value map. Sample usage:
-//    class MyClass {
-//     public:
-//      MyClass() : downloader_(),
-//                  callback_(BuildCallback(this, &MyClass::OnDownloaded)) {
-//        downloader_.data_.insert(
-//            std::make_pair("data/XA", "{\"id\":\"data/XA\"}"));
-//      }
-//
-//      ~MyClass() {}
-//
-//      void GetData(const std::string& key) {
-//        downloader_.Download(std::string(MockDownloader::kMockDataUrl) + key,
-//                             *callback_);
-//      }
-//
-//     private:
-//      void OnDownloaded(bool success,
-//                        const std::string& url,
-//                        std::string* data) {
-//        ...
-//        delete data;
-//      }
-//
-//      MockDownloader downloader_;
-//      const scoped_ptr<const Downloader::Callback> callback_;
-//
-//      DISALLOW_COPY_AND_ASSIGN(MyClass);
-//    };
-class MockDownloader : public Downloader {
- public:
-  // The mock data URL to be used in tests.
-  static const char kMockDataUrl[];
-
-  MockDownloader();
-  virtual ~MockDownloader();
-
-  // Downloader implementation.
-  virtual void Download(const std::string& url,
-                        const Callback& downloaded) const;
-
-  std::map<std::string, std::string> data_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockDownloader);
-};
-
-}  // namespace addressinput
-}  // namespace i18n
-
-#endif  // I18N_ADDRESSINPUT_TEST_MOCK_DOWNLOADER_H_
diff --git a/cpp/test/mock_source.cc b/cpp/test/mock_source.cc
new file mode 100644
index 0000000..d04598b
--- /dev/null
+++ b/cpp/test/mock_source.cc
@@ -0,0 +1,35 @@
+// Copyright (C) 2014 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "mock_source.h"
+
+#include <cstddef>
+#include <map>
+#include <string>
+
+namespace i18n {
+namespace addressinput {
+
+MockSource::MockSource() {}
+
+MockSource::~MockSource() {}
+
+void MockSource::Get(const std::string& key, const Callback& data_ready) const {
+  std::map<std::string, std::string>::const_iterator it = data_.find(key);
+  bool success = it != data_.end();
+  data_ready(success, key, success ? new std::string(it->second) : NULL);
+}
+
+}  // namespace addressinput
+}  // namespace i18n
diff --git a/cpp/test/mock_source.h b/cpp/test/mock_source.h
new file mode 100644
index 0000000..27f75c4
--- /dev/null
+++ b/cpp/test/mock_source.h
@@ -0,0 +1,74 @@
+// Copyright (C) 2014 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// A mock implementation of the Source interface to be used in tests.
+
+#ifndef I18N_ADDRESSINPUT_TEST_MOCK_SOURCE_H_
+#define I18N_ADDRESSINPUT_TEST_MOCK_SOURCE_H_
+
+#include <libaddressinput/source.h>
+#include <libaddressinput/util/basictypes.h>
+
+#include <map>
+#include <string>
+
+namespace i18n {
+namespace addressinput {
+
+// Gets address metadata from a key-value map. Sample usage:
+//    class MyClass {
+//     public:
+//      MyClass() : source_(),
+//                  data_ready_(BuildCallback(this, &MyClass::OnDataReady)) {
+//        source_.data_.insert(
+//            std::make_pair("data/XA", "{\"id\":\"data/XA\"}"));
+//      }
+//
+//      ~MyClass() {}
+//
+//      void GetData(const std::string& key) {
+//        source_.Get(key, *data_ready_);
+//      }
+//
+//     private:
+//      void OnDataReady(bool success,
+//                       const std::string& key,
+//                       std::string* data) {
+//        ...
+//        delete data;
+//      }
+//
+//      MockSource source_;
+//      const scoped_ptr<const Source::Callback> data_ready_;
+//
+//      DISALLOW_COPY_AND_ASSIGN(MyClass);
+//    };
+class MockSource : public Source {
+ public:
+  MockSource();
+  virtual ~MockSource();
+
+  // Source implementation.
+  virtual void Get(const std::string& key, const Callback& data_ready) const;
+
+  std::map<std::string, std::string> data_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockSource);
+};
+
+}  // namespace addressinput
+}  // namespace i18n
+
+#endif  // I18N_ADDRESSINPUT_TEST_MOCK_SOURCE_H_
diff --git a/cpp/test/null_storage_test.cc b/cpp/test/null_storage_test.cc
index dca0803..3669ea9 100644
--- a/cpp/test/null_storage_test.cc
+++ b/cpp/test/null_storage_test.cc
@@ -12,8 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <libaddressinput/callback.h>
 #include <libaddressinput/null_storage.h>
+
+#include <libaddressinput/callback.h>
 #include <libaddressinput/storage.h>
 #include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
@@ -32,16 +33,14 @@
 
 class NullStorageTest : public testing::Test {
  protected:
-  NullStorageTest() {}
-
-  Storage::Callback* BuildCallback() {
-    return ::BuildCallback(this, &NullStorageTest::OnDataReady);
-  }
+  NullStorageTest()
+      : data_ready_(BuildCallback(this, &NullStorageTest::OnDataReady)) {}
 
   NullStorage storage_;
   bool success_;
   std::string key_;
   std::string data_;
+  const scoped_ptr<const Storage::Callback> data_ready_;
 
   static const char kKey[];
 
@@ -68,8 +67,7 @@
 }
 
 TEST_F(NullStorageTest, Get) {
-  const scoped_ptr<const Storage::Callback> callback(BuildCallback());
-  storage_.Get(kKey, *callback);
+  storage_.Get(kKey, *data_ready_);
   EXPECT_FALSE(success_);
   EXPECT_EQ(kKey, key_);
   EXPECT_TRUE(data_.empty());
diff --git a/cpp/test/ondemand_supply_task_test.cc b/cpp/test/ondemand_supply_task_test.cc
index 84b2f65..e15e997 100644
--- a/cpp/test/ondemand_supply_task_test.cc
+++ b/cpp/test/ondemand_supply_task_test.cc
@@ -29,7 +29,7 @@
 #include <gtest/gtest.h>
 
 #include "lookup_key.h"
-#include "mock_downloader.h"
+#include "mock_source.h"
 #include "retriever.h"
 #include "rule.h"
 
@@ -37,7 +37,7 @@
 
 using i18n::addressinput::BuildCallback;
 using i18n::addressinput::LookupKey;
-using i18n::addressinput::MockDownloader;
+using i18n::addressinput::MockSource;
 using i18n::addressinput::NullStorage;
 using i18n::addressinput::OndemandSupplyTask;
 using i18n::addressinput::Retriever;
@@ -52,11 +52,9 @@
         lookup_key_(),
         rule_(),
         called_(false),
-        downloader_(new MockDownloader),
+        source_(new MockSource),
         rule_cache_(),
-        retriever_(
-            new Retriever(
-                MockDownloader::kMockDataUrl, downloader_, new NullStorage)),
+        retriever_(new Retriever(source_, new NullStorage)),
         supplied_(BuildCallback(this, &OndemandSupplyTaskTest::Supplied)),
         task_(new OndemandSupplyTask(lookup_key_, &rule_cache_, *supplied_)) {}
 
@@ -67,19 +65,15 @@
     }
   }
 
-  void Queue(const std::string& key) {
-    task_->Queue(key);
-  }
+  void Queue(const std::string& key) { task_->Queue(key); }
 
-  void Retrieve() {
-    task_->Retrieve(*retriever_);
-  }
+  void Retrieve() { task_->Retrieve(*retriever_); }
 
-  bool success_;  // Expected status from MockDownloader.
+  bool success_;  // Expected status from MockSource.
   LookupKey lookup_key_;  // Stub.
   const Rule* rule_[arraysize(LookupKey::kHierarchy)];
   bool called_;
-  MockDownloader* const downloader_;
+  MockSource* const source_;
 
  private:
   void Supplied(bool success,
@@ -119,7 +113,7 @@
 }
 
 TEST_F(OndemandSupplyTaskTest, Valid) {
-  downloader_->data_.insert(std::make_pair("data/XA", "{\"id\":\"data/XA\"}"));
+  source_->data_.insert(std::make_pair("data/XA", "{\"id\":\"data/XA\"}"));
 
   Queue("data/XA");
 
@@ -139,13 +133,13 @@
 }
 
 TEST_F(OndemandSupplyTaskTest, ValidHierarchy) {
-  downloader_->data_.insert(
+  source_->data_.insert(
       std::make_pair("data/XA", "{\"id\":\"data/XA\"}"));
-  downloader_->data_.insert(
+  source_->data_.insert(
       std::make_pair("data/XA/aa", "{\"id\":\"data/XA/aa\"}"));
-  downloader_->data_.insert(
+  source_->data_.insert(
       std::make_pair("data/XA/aa/bb", "{\"id\":\"data/XA/aa/bb\"}"));
-  downloader_->data_.insert(
+  source_->data_.insert(
       std::make_pair("data/XA/aa/bb/cc", "{\"id\":\"data/XA/aa/bb/cc\"}"));
 
   Queue("data/XA");
@@ -179,7 +173,7 @@
 }
 
 TEST_F(OndemandSupplyTaskTest, InvalidJson1) {
-  downloader_->data_.insert(std::make_pair("data/XA", ":"));
+  source_->data_.insert(std::make_pair("data/XA", ":"));
 
   success_ = false;
 
@@ -190,8 +184,8 @@
 }
 
 TEST_F(OndemandSupplyTaskTest, InvalidJson2) {
-  downloader_->data_.insert(std::make_pair("data/XA", "{\"id\":\"data/XA\"}"));
-  downloader_->data_.insert(std::make_pair("data/XA/aa", ":"));
+  source_->data_.insert(std::make_pair("data/XA", "{\"id\":\"data/XA\"}"));
+  source_->data_.insert(std::make_pair("data/XA/aa", ":"));
 
   success_ = false;
 
@@ -203,8 +197,8 @@
 }
 
 TEST_F(OndemandSupplyTaskTest, EmptyJsonJustMeansServerKnowsNothingAboutKey) {
-  downloader_->data_.insert(std::make_pair("data/XA", "{\"id\":\"data/XA\"}"));
-  downloader_->data_.insert(std::make_pair("data/XA/aa", "{}"));
+  source_->data_.insert(std::make_pair("data/XA", "{\"id\":\"data/XA\"}"));
+  source_->data_.insert(std::make_pair("data/XA/aa", "{}"));
 
   Queue("data/XA");
   Queue("data/XA/aa");
@@ -220,7 +214,7 @@
 }
 
 TEST_F(OndemandSupplyTaskTest, IfCountryFailsAllFails) {
-  downloader_->data_.insert(
+  source_->data_.insert(
       std::make_pair("data/XA/aa", "{\"id\":\"data/XA/aa\"}"));
 
   success_ = false;
diff --git a/cpp/test/post_box_matchers_test.cc b/cpp/test/post_box_matchers_test.cc
index d89ee0b..8abd974 100644
--- a/cpp/test/post_box_matchers_test.cc
+++ b/cpp/test/post_box_matchers_test.cc
@@ -17,13 +17,13 @@
 #include <cstddef>
 #include <vector>
 
-#include "rule.h"
-
 #include <gtest/gtest.h>
 
+#include "rule.h"
+
 namespace i18n {
 namespace addressinput {
-class RE2ptr;
+struct RE2ptr;
 }  // namespace addressinput
 }  // namespace i18n
 
diff --git a/cpp/test/preload_supplier_test.cc b/cpp/test/preload_supplier_test.cc
index ab787d8..8612e98 100644
--- a/cpp/test/preload_supplier_test.cc
+++ b/cpp/test/preload_supplier_test.cc
@@ -20,38 +20,34 @@
 #include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
 
-#include "fake_downloader.h"
-#include "lookup_key.h"
-#include "rule.h"
-
 #include <cstddef>
 #include <string>
 
 #include <gtest/gtest.h>
 
+#include "lookup_key.h"
+#include "rule.h"
+#include "testdata_source.h"
+
 namespace {
 
 using i18n::addressinput::AddressData;
 using i18n::addressinput::BuildCallback;
-using i18n::addressinput::FakeDownloader;
 using i18n::addressinput::LookupKey;
 using i18n::addressinput::NullStorage;
 using i18n::addressinput::PreloadSupplier;
 using i18n::addressinput::Rule;
 using i18n::addressinput::scoped_ptr;
+using i18n::addressinput::TestdataSource;
 
 class PreloadSupplierTest : public testing::Test {
  protected:
   PreloadSupplierTest()
-      : supplier_(FakeDownloader::kFakeAggregateDataUrl,
-                  new FakeDownloader,
-                  new NullStorage),
+      : supplier_(new TestdataSource(true), new NullStorage),
         loaded_callback_(BuildCallback(this, &PreloadSupplierTest::OnLoaded)) {}
 
-  virtual ~PreloadSupplierTest() {}
-
   PreloadSupplier supplier_;
-  scoped_ptr<PreloadSupplier::Callback> loaded_callback_;
+  const scoped_ptr<const PreloadSupplier::Callback> loaded_callback_;
 
  private:
   void OnLoaded(bool success, const std::string& region_code, int num_rules) {
@@ -121,4 +117,12 @@
   EXPECT_TRUE(rule == NULL);
 }
 
+TEST_F(PreloadSupplierTest, GetRulesForRegion) {
+  supplier_.LoadRules("CN", *loaded_callback_);
+  const std::map<std::string, const Rule*>& rules =
+      supplier_.GetRulesForRegion("CN");
+  EXPECT_TRUE(rules.find("data/CN") != rules.end());
+  EXPECT_LT(1U, rules.size());
+}
+
 }  // namespace
diff --git a/cpp/test/region_data_builder_test.cc b/cpp/test/region_data_builder_test.cc
index 03b0981..fe2f2e1 100644
--- a/cpp/test/region_data_builder_test.cc
+++ b/cpp/test/region_data_builder_test.cc
@@ -21,37 +21,34 @@
 #include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
 
-#include "fake_downloader.h"
-
 #include <string>
 
 #include <gtest/gtest.h>
 
+#include "testdata_source.h"
+
 namespace {
 
 using i18n::addressinput::BuildCallback;
-using i18n::addressinput::FakeDownloader;
 using i18n::addressinput::NullStorage;
 using i18n::addressinput::PreloadSupplier;
 using i18n::addressinput::RegionData;
 using i18n::addressinput::RegionDataBuilder;
 using i18n::addressinput::scoped_ptr;
+using i18n::addressinput::TestdataSource;
 
 class RegionDataBuilderTest : public testing::Test {
  protected:
   RegionDataBuilderTest()
-      : supplier_(FakeDownloader::kFakeAggregateDataUrl,
-                  new FakeDownloader,
+      : supplier_(new TestdataSource(true),
                   new NullStorage),
         builder_(&supplier_),
         loaded_callback_(BuildCallback(this, &RegionDataBuilderTest::OnLoaded)),
         best_language_() {}
 
-  virtual ~RegionDataBuilderTest() {}
-
   PreloadSupplier supplier_;
   RegionDataBuilder builder_;
-  scoped_ptr<PreloadSupplier::Callback> loaded_callback_;
+  const scoped_ptr<const PreloadSupplier::Callback> loaded_callback_;
   std::string best_language_;
 
  private:
@@ -108,7 +105,9 @@
   const RegionData& tree = builder_.Build("KR", "ko-Latn", &best_language_);
   EXPECT_EQ("ko-Latn", best_language_);
   ASSERT_FALSE(tree.sub_regions().empty());
-  EXPECT_EQ("강원도", tree.sub_regions().front()->key());
+  EXPECT_EQ(
+      "\xEA\xB0\x95\xEC\x9B\x90\xEB\x8F\x84",  /* "강원도" */
+      tree.sub_regions().front()->key());
   EXPECT_EQ("Gangwon", tree.sub_regions().front()->name());
 }
 
@@ -117,8 +116,12 @@
   const RegionData& tree = builder_.Build("KR", "ko-KR", &best_language_);
   EXPECT_EQ("ko", best_language_);
   ASSERT_FALSE(tree.sub_regions().empty());
-  EXPECT_EQ("강원도", tree.sub_regions().front()->key());
-  EXPECT_EQ("강원", tree.sub_regions().front()->name());
+  EXPECT_EQ(
+      "\xEA\xB0\x95\xEC\x9B\x90\xEB\x8F\x84",  /* "강원도" */
+      tree.sub_regions().front()->key());
+  EXPECT_EQ(
+      "\xEA\xB0\x95\xEC\x9B\x90",  /* "강원" */
+      tree.sub_regions().front()->name());
 }
 
 }  // namespace
diff --git a/cpp/test/region_data_constants_test.cc b/cpp/test/region_data_constants_test.cc
index b407374..63e6ae2 100644
--- a/cpp/test/region_data_constants_test.cc
+++ b/cpp/test/region_data_constants_test.cc
@@ -14,8 +14,9 @@
 
 #include "region_data_constants.h"
 
+#include <libaddressinput/util/basictypes.h>
+
 #include <string>
-#include <vector>
 
 #include <gtest/gtest.h>
 
@@ -24,7 +25,13 @@
 using i18n::addressinput::RegionDataConstants;
 
 // Tests for region codes, for example "ZA".
-class RegionCodeTest : public testing::TestWithParam<std::string> {};
+class RegionCodeTest : public testing::TestWithParam<std::string> {
+ protected:
+  RegionCodeTest() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RegionCodeTest);
+};
 
 // Verifies that a region code consists of two characters, for example "ZA".
 TEST_P(RegionCodeTest, RegionCodeHasTwoCharacters) {
@@ -58,9 +65,14 @@
 // Tests for region data, for example "{\"fmt\":\"%C%S\"}".
 class RegionDataTest : public testing::TestWithParam<std::string> {
  protected:
+  RegionDataTest() {}
+
   const std::string& GetData() const {
     return RegionDataConstants::GetRegionData(GetParam());
   }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RegionDataTest);
 };
 
 // Verifies that a region data value begins with '{' and end with '}', for
diff --git a/cpp/test/region_data_test.cc b/cpp/test/region_data_test.cc
index 66d06c6..074d3a6 100644
--- a/cpp/test/region_data_test.cc
+++ b/cpp/test/region_data_test.cc
@@ -14,6 +14,7 @@
 
 #include <libaddressinput/region_data.h>
 
+#include <cstddef>
 #include <string>
 
 #include <gtest/gtest.h>
diff --git a/cpp/test/retriever_test.cc b/cpp/test/retriever_test.cc
index aff418c..00c2ea4 100644
--- a/cpp/test/retriever_test.cc
+++ b/cpp/test/retriever_test.cc
@@ -17,6 +17,7 @@
 #include <libaddressinput/callback.h>
 #include <libaddressinput/null_storage.h>
 #include <libaddressinput/storage.h>
+#include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
 
 #include <cstddef>
@@ -24,8 +25,8 @@
 
 #include <gtest/gtest.h>
 
-#include "fake_downloader.h"
-#include "mock_downloader.h"
+#include "mock_source.h"
+#include "testdata_source.h"
 
 #define CHECKSUM "dd63dafcbd4d5b28badfcaf86fb6fcdb"
 #define DATA "{'foo': 'bar'}"
@@ -34,16 +35,16 @@
 namespace {
 
 using i18n::addressinput::BuildCallback;
-using i18n::addressinput::FakeDownloader;
-using i18n::addressinput::MockDownloader;
+using i18n::addressinput::MockSource;
 using i18n::addressinput::NullStorage;
 using i18n::addressinput::Retriever;
-using i18n::addressinput::Storage;
 using i18n::addressinput::scoped_ptr;
+using i18n::addressinput::Storage;
+using i18n::addressinput::TestdataSource;
 
 const char kKey[] = "data/CA/AB--fr";
 
-// Empty data that the downloader can return.
+// Empty data that the source can return.
 const char kEmptyData[] = "{}";
 
 // The value of the data that the stale storage returns.
@@ -58,23 +59,17 @@
 class RetrieverTest : public testing::Test {
  protected:
   RetrieverTest()
-      : retriever_(FakeDownloader::kFakeDataUrl,
-                   new FakeDownloader,
-                   new NullStorage),
+      : retriever_(new TestdataSource(false), new NullStorage),
         success_(false),
         key_(),
-        data_() {}
-
-  virtual ~RetrieverTest() {}
-
-  Retriever::Callback* BuildCallback() {
-    return ::BuildCallback(this, &RetrieverTest::OnDataReady);
-  }
+        data_(),
+        data_ready_(BuildCallback(this, &RetrieverTest::OnDataReady)) {}
 
   Retriever retriever_;
   bool success_;
   std::string key_;
   std::string data_;
+  const scoped_ptr<const Retriever::Callback> data_ready_;
 
  private:
   void OnDataReady(bool success,
@@ -84,11 +79,12 @@
     key_ = key;
     data_ = data;
   }
+
+  DISALLOW_COPY_AND_ASSIGN(RetrieverTest);
 };
 
 TEST_F(RetrieverTest, RetrieveData) {
-  scoped_ptr<Retriever::Callback> callback(BuildCallback());
-  retriever_.Retrieve(kKey, *callback);
+  retriever_.Retrieve(kKey, *data_ready_);
 
   EXPECT_TRUE(success_);
   EXPECT_EQ(kKey, key_);
@@ -97,11 +93,8 @@
 }
 
 TEST_F(RetrieverTest, ReadDataFromStorage) {
-  scoped_ptr<Retriever::Callback> callback1(BuildCallback());
-  retriever_.Retrieve(kKey, *callback1);
-
-  scoped_ptr<Retriever::Callback> callback2(BuildCallback());
-  retriever_.Retrieve(kKey, *callback2);
+  retriever_.Retrieve(kKey, *data_ready_);
+  retriever_.Retrieve(kKey, *data_ready_);
 
   EXPECT_TRUE(success_);
   EXPECT_EQ(kKey, key_);
@@ -112,22 +105,18 @@
 TEST_F(RetrieverTest, MissingKeyReturnsEmptyData) {
   static const char kMissingKey[] = "junk";
 
-  scoped_ptr<Retriever::Callback> callback(BuildCallback());
-  retriever_.Retrieve(kMissingKey, *callback);
+  retriever_.Retrieve(kMissingKey, *data_ready_);
 
   EXPECT_TRUE(success_);
   EXPECT_EQ(kMissingKey, key_);
   EXPECT_EQ(kEmptyData, data_);
 }
 
-TEST_F(RetrieverTest, FaultyDownloader) {
-  // An empty MockDownloader will fail for any request.
-  Retriever bad_retriever(MockDownloader::kMockDataUrl,
-                          new MockDownloader,
-                          new NullStorage);
+TEST_F(RetrieverTest, FaultySource) {
+  // An empty MockSource will fail for any request.
+  Retriever bad_retriever(new MockSource, new NullStorage);
 
-  scoped_ptr<Retriever::Callback> callback(BuildCallback());
-  bad_retriever.Retrieve(kKey, *callback);
+  bad_retriever.Retrieve(kKey, *data_ready_);
 
   EXPECT_FALSE(success_);
   EXPECT_EQ(kKey, key_);
@@ -157,15 +146,13 @@
   DISALLOW_COPY_AND_ASSIGN(StaleStorage);
 };
 
-TEST_F(RetrieverTest, UseStaleDataWhenDownloaderFails) {
+TEST_F(RetrieverTest, UseStaleDataWhenSourceFails) {
   // Owned by |resilient_retriver|.
   StaleStorage* stale_storage = new StaleStorage;
-  // An empty MockDownloader will fail for any request.
-  Retriever resilient_retriever(
-      MockDownloader::kMockDataUrl, new MockDownloader, stale_storage);
+  // An empty MockSource will fail for any request.
+  Retriever resilient_retriever(new MockSource, stale_storage);
 
-  scoped_ptr<Retriever::Callback> callback(BuildCallback());
-  resilient_retriever.Retrieve(kKey, *callback);
+  resilient_retriever.Retrieve(kKey, *data_ready_);
 
   EXPECT_TRUE(success_);
   EXPECT_EQ(kKey, key_);
@@ -173,14 +160,12 @@
   EXPECT_FALSE(stale_storage->data_updated_);
 }
 
-TEST_F(RetrieverTest, DoNotUseStaleDataWhenDownloaderSucceeds) {
+TEST_F(RetrieverTest, DoNotUseStaleDataWhenSourceSucceeds) {
   // Owned by |resilient_retriver|.
   StaleStorage* stale_storage = new StaleStorage;
-  Retriever resilient_retriever(
-      FakeDownloader::kFakeDataUrl, new FakeDownloader, stale_storage);
+  Retriever resilient_retriever(new TestdataSource(false), stale_storage);
 
-  scoped_ptr<Retriever::Callback> callback(BuildCallback());
-  resilient_retriever.Retrieve(kKey, *callback);
+  resilient_retriever.Retrieve(kKey, *data_ready_);
 
   EXPECT_TRUE(success_);
   EXPECT_EQ(kKey, key_);
diff --git a/cpp/test/rule_retriever_test.cc b/cpp/test/rule_retriever_test.cc
index ecfb0c8..ecf3af7 100644
--- a/cpp/test/rule_retriever_test.cc
+++ b/cpp/test/rule_retriever_test.cc
@@ -16,47 +16,43 @@
 
 #include <libaddressinput/callback.h>
 #include <libaddressinput/null_storage.h>
+#include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
 
 #include <string>
 
 #include <gtest/gtest.h>
 
-#include "fake_downloader.h"
 #include "retriever.h"
 #include "rule.h"
+#include "testdata_source.h"
 
 namespace {
 
 using i18n::addressinput::BuildCallback;
-using i18n::addressinput::FakeDownloader;
 using i18n::addressinput::NullStorage;
 using i18n::addressinput::Retriever;
 using i18n::addressinput::Rule;
 using i18n::addressinput::RuleRetriever;
 using i18n::addressinput::scoped_ptr;
+using i18n::addressinput::TestdataSource;
 
 // Tests for RuleRetriever object.
 class RuleRetrieverTest : public testing::Test {
  protected:
   RuleRetrieverTest()
-      : rule_retriever_(new Retriever(FakeDownloader::kFakeDataUrl,
-                                      new FakeDownloader,
-                                      new NullStorage)),
+      : rule_retriever_(
+            new Retriever(new TestdataSource(false), new NullStorage)),
         success_(false),
         key_(),
-        rule_() {}
-
-  virtual ~RuleRetrieverTest() {}
-
-  RuleRetriever::Callback* BuildCallback() {
-    return ::BuildCallback(this, &RuleRetrieverTest::OnRuleReady);
-  }
+        rule_(),
+        rule_ready_(BuildCallback(this, &RuleRetrieverTest::OnRuleReady)) {}
 
   RuleRetriever rule_retriever_;
   bool success_;
   std::string key_;
   Rule rule_;
+  const scoped_ptr<const RuleRetriever::Callback> rule_ready_;
 
  private:
   void OnRuleReady(bool success,
@@ -66,13 +62,14 @@
     key_ = key;
     rule_.CopyFrom(rule);
   }
+
+  DISALLOW_COPY_AND_ASSIGN(RuleRetrieverTest);
 };
 
 TEST_F(RuleRetrieverTest, ExistingRule) {
   static const char kExistingKey[] = "data/CA";
 
-  scoped_ptr<RuleRetriever::Callback> callback(BuildCallback());
-  rule_retriever_.RetrieveRule(kExistingKey, *callback);
+  rule_retriever_.RetrieveRule(kExistingKey, *rule_ready_);
 
   EXPECT_TRUE(success_);
   EXPECT_EQ(kExistingKey, key_);
@@ -82,8 +79,7 @@
 TEST_F(RuleRetrieverTest, MissingRule) {
   static const char kMissingKey[] = "junk";
 
-  scoped_ptr<RuleRetriever::Callback> callback(BuildCallback());
-  rule_retriever_.RetrieveRule(kMissingKey, *callback);
+  rule_retriever_.RetrieveRule(kMissingKey, *rule_ready_);
 
   EXPECT_TRUE(success_);  // The server returns "{}" for bad keys.
   EXPECT_EQ(kMissingKey, key_);
diff --git a/cpp/test/rule_test.cc b/cpp/test/rule_test.cc
index 25426a2..7c5a0c5 100644
--- a/cpp/test/rule_test.cc
+++ b/cpp/test/rule_test.cc
@@ -16,6 +16,7 @@
 
 #include <libaddressinput/address_field.h>
 #include <libaddressinput/localization.h>
+#include <libaddressinput/util/basictypes.h>
 
 #include <cstddef>
 #include <string>
@@ -24,7 +25,6 @@
 
 #include <gtest/gtest.h>
 
-#include "address_field_util.h"
 #include "format_element.h"
 #include "grit.h"
 #include "messages.h"
@@ -242,7 +242,11 @@
 class PostalCodeNameParseTest
     : public testing::TestWithParam<std::pair<std::string, int> > {
  protected:
+  PostalCodeNameParseTest() {}
   Rule rule_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PostalCodeNameParseTest);
 };
 
 // Verifies that a postal code name is parsed correctly.
@@ -264,7 +268,11 @@
 class AdminAreaNameParseTest
     : public testing::TestWithParam<std::pair<std::string, int> > {
  protected:
+  AdminAreaNameParseTest() {}
   Rule rule_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AdminAreaNameParseTest);
 };
 
 // Verifies that an administrative area name is parsed correctly.
@@ -303,6 +311,8 @@
 // Tests for rule parsing.
 class RuleParseTest : public testing::TestWithParam<std::string> {
  protected:
+  RuleParseTest() {}
+
   const std::string& GetRegionData() const {
     // GetParam() is either a region code or the region data itself.
     // RegionDataContants::GetRegionData() returns an empty string for anything
@@ -313,6 +323,9 @@
 
   Rule rule_;
   Localization localization_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RuleParseTest);
 };
 
 // Verifies that a region data can be parsed successfully.
diff --git a/cpp/test/supplier_test.cc b/cpp/test/supplier_test.cc
index 13913c3..e55c0c1 100644
--- a/cpp/test/supplier_test.cc
+++ b/cpp/test/supplier_test.cc
@@ -16,11 +16,9 @@
 
 #include <libaddressinput/address_data.h>
 #include <libaddressinput/callback.h>
-#include <libaddressinput/downloader.h>
 #include <libaddressinput/null_storage.h>
 #include <libaddressinput/ondemand_supplier.h>
 #include <libaddressinput/preload_supplier.h>
-#include <libaddressinput/storage.h>
 #include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
 
@@ -30,9 +28,9 @@
 
 #include <gtest/gtest.h>
 
-#include "fake_downloader.h"
 #include "lookup_key.h"
 #include "rule.h"
+#include "testdata_source.h"
 
 namespace {
 
@@ -55,16 +53,14 @@
 
 using i18n::addressinput::AddressData;
 using i18n::addressinput::BuildCallback;
-using i18n::addressinput::Downloader;
-using i18n::addressinput::FakeDownloader;
 using i18n::addressinput::LookupKey;
 using i18n::addressinput::NullStorage;
 using i18n::addressinput::OndemandSupplier;
 using i18n::addressinput::PreloadSupplier;
 using i18n::addressinput::Rule;
 using i18n::addressinput::scoped_ptr;
-using i18n::addressinput::Storage;
 using i18n::addressinput::Supplier;
+using i18n::addressinput::TestdataSource;
 
 class SupplierWrapper {
  public:
@@ -77,8 +73,6 @@
  public:
   static SupplierWrapper* Build() { return new OndemandSupplierWrapper; }
 
-  virtual ~OndemandSupplierWrapper() {}
-
   virtual void Supply(const LookupKey& lookup_key,
                       const Supplier::Callback& supplied) {
     ondemand_supplier_.Supply(lookup_key, supplied);
@@ -86,9 +80,7 @@
 
  private:
   OndemandSupplierWrapper()
-      : ondemand_supplier_(FakeDownloader::kFakeDataUrl,
-                           new FakeDownloader,
-                           new NullStorage) {}
+      : ondemand_supplier_(new TestdataSource(false), new NullStorage) {}
 
   OndemandSupplier ondemand_supplier_;
   DISALLOW_COPY_AND_ASSIGN(OndemandSupplierWrapper);
@@ -98,8 +90,6 @@
  public:
   static SupplierWrapper* Build() { return new PreloadSupplierWrapper; }
 
-  virtual ~PreloadSupplierWrapper() {}
-
   virtual void Supply(const LookupKey& lookup_key,
                       const Supplier::Callback& supplied) {
     const std::string& region_code = lookup_key.GetRegionCode();
@@ -111,14 +101,10 @@
 
  private:
   PreloadSupplierWrapper()
-      : preload_supplier_(FakeDownloader::kFakeAggregateDataUrl,
-                          new FakeDownloader,
-                          new NullStorage),
+      : preload_supplier_(new TestdataSource(true), new NullStorage),
         loaded_(BuildCallback(this, &PreloadSupplierWrapper::Loaded)) {}
 
-  void Loaded(bool success, const std::string&, int) {
-    ASSERT_TRUE(success);
-  }
+  void Loaded(bool success, const std::string&, int) { ASSERT_TRUE(success); }
 
   PreloadSupplier preload_supplier_;
   const scoped_ptr<const PreloadSupplier::Callback> loaded_;
@@ -135,8 +121,6 @@
         supplier_wrapper_((*GetParam())()),
         supplied_(BuildCallback(this, &SupplierTest::Supplied)) {}
 
-  virtual ~SupplierTest() {}
-
   void Supply() {
     lookup_key_.FromAddress(address_);
     supplier_wrapper_->Supply(lookup_key_, *supplied_);
diff --git a/cpp/test/testdata_source.cc b/cpp/test/testdata_source.cc
new file mode 100644
index 0000000..d333cb0
--- /dev/null
+++ b/cpp/test/testdata_source.cc
@@ -0,0 +1,174 @@
+// Copyright (C) 2013 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "testdata_source.h"
+
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <map>
+#include <string>
+#include <utility>
+
+namespace i18n {
+namespace addressinput {
+
+namespace {
+
+// For historical reasons, normal and aggregated data is here stored in the
+// same data structure, differentiated by giving each key a prefix. It does
+// seem like a good idea to refactor this.
+const char kNormalPrefix = '-';
+const char kAggregatePrefix = '+';
+
+// The name of the test data file.
+const char kDataFileName[] = TEST_DATA_DIR "/countryinfo.txt";
+
+// Each data key begins with this string. Example of a data key:
+//     data/CH/AG
+const char kDataKeyPrefix[] = "data/";
+
+// The number of characters in the data key prefix.
+const size_t kDataKeyPrefixLength = sizeof kDataKeyPrefix - 1;
+
+// The number of characters in a CLDR region code, e.g. 'CH'.
+const size_t kCldrRegionCodeLength = 2;
+
+// The number of characters in an aggregate data key, e.g. 'data/CH'.
+const size_t kAggregateDataKeyLength =
+    kDataKeyPrefixLength + kCldrRegionCodeLength;
+
+std::map<std::string, std::string> InitData() {
+  std::map<std::string, std::string> data;
+  std::ifstream file(kDataFileName);
+  if (!file.is_open()) {
+    std::cerr << "Error opening \"" << kDataFileName << "\"." << std::endl;
+    std::exit(EXIT_FAILURE);
+  }
+
+  const std::string normal_prefix(1, kNormalPrefix);
+  const std::string aggregate_prefix(1, kAggregatePrefix);
+
+  std::string key;
+  std::string value;
+
+  std::map<std::string, std::string>::iterator last_data_it = data.end();
+  std::map<std::string, std::string>::iterator aggregate_data_it = data.end();
+
+  while (file.good()) {
+    // Example line from countryinfo.txt:
+    //     data/CH/AG={"name": "Aargau"}
+    // Example key:
+    //     data/CH/AG
+    std::getline(file, key, '=');
+
+    if (!key.empty()) {
+      // Example value:
+      //     {"name": "Aargau"}
+      std::getline(file, value, '\n');
+
+      // For example, map '-data/CH/AG' to '{"name": "Aargau"}'.
+      last_data_it = data.insert(
+          last_data_it,
+          std::make_pair(normal_prefix + key, value));
+
+      // Aggregate keys that begin with 'data/'. We don't aggregate keys that
+      // begin with 'example/' because example data is not used anywhere.
+      if (key.compare(0,
+                      kDataKeyPrefixLength,
+                      kDataKeyPrefix,
+                      kDataKeyPrefixLength) == 0) {
+        // If aggregate_data_it and key have the same prefix, e.g. "data/ZZ".
+        if (aggregate_data_it != data.end() &&
+            key.compare(0,
+                        kAggregateDataKeyLength,
+                        aggregate_data_it->first,
+                        sizeof kAggregatePrefix,
+                        kAggregateDataKeyLength) == 0) {
+          // Append more data to the aggregate string, for example:
+          //     , "data/CH/AG": {"name": "Aargau"}
+          aggregate_data_it->second.append(", \"" + key + "\": " + value);
+        } else {
+          // The countryinfo.txt file must be sorted so that subkey data
+          // follows directly after its parent key data.
+          assert(key.size() == kAggregateDataKeyLength);
+
+          // Make the aggregate data strings valid. For example, this incomplete
+          // JSON data:
+          //     {"data/CH/AG": {"name": "Aargau"},
+          //      "data/CH": {"name": "SWITZERLAND"}
+          //
+          // becomes valid JSON data like so:
+          //
+          //     {"data/CH/AG": {"name": "Aargau"},
+          //      "data/CH": {"name": "SWITZERLAND"}}
+          if (aggregate_data_it != data.end()) {
+            aggregate_data_it->second.push_back('}');
+          }
+
+          // Example aggregate prefixed key:
+          //     +data/CH
+          const std::string& aggregate_key =
+              aggregate_prefix + key.substr(0, kAggregateDataKeyLength);
+
+          // Begin a new aggregate string, for example:
+          //     {"data/CH/AG": {"name": "Aargau"}
+          aggregate_data_it = data.insert(
+              aggregate_data_it,
+              std::make_pair(aggregate_key, "{\"" + key + "\": " + value));
+        }
+      }
+    }
+  }
+
+  file.close();
+  return data;
+}
+
+const std::map<std::string, std::string>& GetData() {
+  static const std::map<std::string, std::string> kData(InitData());
+  return kData;
+}
+
+}  // namespace
+
+TestdataSource::TestdataSource(bool aggregate) : aggregate_(aggregate) {}
+
+TestdataSource::~TestdataSource() {}
+
+void TestdataSource::Get(const std::string& key,
+                         const Callback& data_ready) const {
+  std::string prefixed_key(1, aggregate_ ? kAggregatePrefix : kNormalPrefix);
+  prefixed_key += key;
+  std::map<std::string, std::string>::const_iterator data_it =
+      GetData().find(prefixed_key);
+  bool success = data_it != GetData().end();
+  std::string* data = NULL;
+  if (success) {
+    data = new std::string(data_it->second);
+  } else {
+    // URLs that start with "https://i18napis.appspot.com/ssl-address/" or
+    // "https://i18napis.appspot.com/ssl-aggregate-address/" prefix, but do not
+    // have associated data will always return "{}" with status code 200.
+    // TestdataSource imitates this behavior.
+    success = true;
+    data = new std::string("{}");
+  }
+  data_ready(success, key, data);
+}
+
+}  // namespace addressinput
+}  // namespace i18n
diff --git a/cpp/test/testdata_source.h b/cpp/test/testdata_source.h
new file mode 100644
index 0000000..626483e
--- /dev/null
+++ b/cpp/test/testdata_source.h
@@ -0,0 +1,71 @@
+// Copyright (C) 2013 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// An implementation of the Source interface, that reads address metadata from a
+// text file, to be used in tests.
+
+#ifndef I18N_ADDRESSINPUT_TEST_TESTDATA_SOURCE_H_
+#define I18N_ADDRESSINPUT_TEST_TESTDATA_SOURCE_H_
+
+#include <libaddressinput/source.h>
+#include <libaddressinput/util/basictypes.h>
+
+#include <string>
+
+namespace i18n {
+namespace addressinput {
+
+// Gets address metadata from a text file. Sample usage:
+//    class MyClass {
+//     public:
+//      MyClass() : source_(),
+//                  data_ready_(BuildCallback(this, &MyClass::OnDataReady)) {}
+//
+//      ~MyClass() {}
+//
+//      void GetData(const std::string& key) {
+//        source_.Get(key, *data_ready_);
+//      }
+//
+//     private:
+//      void OnDataReady(bool success,
+//                       const std::string& key,
+//                       std::string* data) {
+//        ...
+//        delete data;
+//      }
+//
+//      TestdataSource source_;
+//      const scoped_ptr<const Source::Callback> data_ready_;
+//
+//      DISALLOW_COPY_AND_ASSIGN(MyClass);
+//    };
+class TestdataSource : public Source {
+ public:
+  // Will return aggregate data if |aggregate| is set to true.
+  explicit TestdataSource(bool aggregate);
+  virtual ~TestdataSource();
+
+  // Source implementation.
+  virtual void Get(const std::string& key, const Callback& data_ready) const;
+
+ private:
+  const bool aggregate_;
+  DISALLOW_COPY_AND_ASSIGN(TestdataSource);
+};
+
+}  // namespace addressinput
+}  // namespace i18n
+
+#endif  // I18N_ADDRESSINPUT_TEST_TESTDATA_SOURCE_H_
diff --git a/cpp/test/testdata_source_test.cc b/cpp/test/testdata_source_test.cc
new file mode 100644
index 0000000..58468a9
--- /dev/null
+++ b/cpp/test/testdata_source_test.cc
@@ -0,0 +1,190 @@
+// Copyright (C) 2013 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "testdata_source.h"
+
+#include <libaddressinput/callback.h>
+#include <libaddressinput/source.h>
+#include <libaddressinput/util/basictypes.h>
+#include <libaddressinput/util/scoped_ptr.h>
+
+#include <cstddef>
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "region_data_constants.h"
+
+namespace {
+
+using i18n::addressinput::BuildCallback;
+using i18n::addressinput::RegionDataConstants;
+using i18n::addressinput::scoped_ptr;
+using i18n::addressinput::Source;
+using i18n::addressinput::TestdataSource;
+
+// Tests for TestdataSource object.
+class TestdataSourceTest : public testing::TestWithParam<std::string> {
+ protected:
+  TestdataSourceTest()
+      : source_(false),
+        aggregate_source_(true),
+        success_(false),
+        key_(),
+        data_(),
+        data_ready_(BuildCallback(this, &TestdataSourceTest::OnDataReady)) {}
+
+  TestdataSource source_;
+  TestdataSource aggregate_source_;
+  bool success_;
+  std::string key_;
+  std::string data_;
+  const scoped_ptr<const Source::Callback> data_ready_;
+
+ private:
+  void OnDataReady(bool success, const std::string& key, std::string* data) {
+    ASSERT_FALSE(success && data == NULL);
+    success_ = success;
+    key_ = key;
+    if (data != NULL) {
+      data_ = *data;
+      delete data;
+    }
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(TestdataSourceTest);
+};
+
+// Returns testing::AssertionSuccess if |data| is valid callback data for
+// |key|.
+testing::AssertionResult DataIsValid(const std::string& data,
+                                     const std::string& key) {
+  if (data.empty()) {
+    return testing::AssertionFailure() << "empty data";
+  }
+
+  std::string expected_data_begin = "{\"id\":\"" + key + "\"";
+  if (data.compare(0, expected_data_begin.length(), expected_data_begin) != 0) {
+    return testing::AssertionFailure() << data << " does not begin with "
+                                       << expected_data_begin;
+  }
+
+  // Verify that the data ends on "}.
+  static const char kDataEnd[] = "\"}";
+  static const size_t kDataEndLength = sizeof kDataEnd - 1;
+  if (data.compare(data.length() - kDataEndLength,
+                   kDataEndLength,
+                   kDataEnd,
+                   kDataEndLength) != 0) {
+    return testing::AssertionFailure() << data << " does not end with "
+                                       << kDataEnd;
+  }
+
+  return testing::AssertionSuccess();
+}
+
+// Verifies that TestdataSource gets valid data for a region code.
+TEST_P(TestdataSourceTest, TestdataSourceHasValidDataForRegion) {
+  std::string key = "data/" + GetParam();
+  source_.Get(key, *data_ready_);
+
+  EXPECT_TRUE(success_);
+  EXPECT_EQ(key, key_);
+  EXPECT_TRUE(DataIsValid(data_, key));
+};
+
+// Returns testing::AssertionSuccess if |data| is valid aggregated callback
+// data for |key|.
+testing::AssertionResult AggregateDataIsValid(const std::string& data,
+                                              const std::string& key) {
+  if (data.empty()) {
+    return testing::AssertionFailure() << "empty data";
+  }
+
+  std::string expected_data_begin = "{\"" + key;
+  if (data.compare(0, expected_data_begin.length(), expected_data_begin) != 0) {
+    return testing::AssertionFailure() << data << " does not begin with "
+                                       << expected_data_begin;
+  }
+
+  // Verify that the data ends on "}}.
+  static const char kDataEnd[] = "\"}}";
+  static const size_t kDataEndLength = sizeof kDataEnd - 1;
+  if (data.compare(data.length() - kDataEndLength,
+                   kDataEndLength,
+                   kDataEnd,
+                   kDataEndLength) != 0) {
+    return testing::AssertionFailure() << data << " does not end with "
+                                       << kDataEnd;
+  }
+
+  return testing::AssertionSuccess();
+}
+
+// Verifies that TestdataSource gets valid aggregated data for a region code.
+TEST_P(TestdataSourceTest, TestdataSourceHasValidAggregatedDataForRegion) {
+  std::string key = "data/" + GetParam();
+  aggregate_source_.Get(key, *data_ready_);
+
+  EXPECT_TRUE(success_);
+  EXPECT_EQ(key, key_);
+  EXPECT_TRUE(AggregateDataIsValid(data_, key));
+};
+
+// Test all region codes.
+INSTANTIATE_TEST_CASE_P(
+    AllRegions, TestdataSourceTest,
+    testing::ValuesIn(RegionDataConstants::GetRegionCodes()));
+
+// Verifies that the key "data" also contains valid data.
+TEST_F(TestdataSourceTest, GetExistingData) {
+  static const std::string kKey = "data";
+  source_.Get(kKey, *data_ready_);
+
+  EXPECT_TRUE(success_);
+  EXPECT_EQ(kKey, key_);
+  EXPECT_TRUE(DataIsValid(data_, kKey));
+}
+
+// Verifies that requesting a missing key will return "{}".
+TEST_F(TestdataSourceTest, GetMissingKeyReturnsEmptyDictionary) {
+  static const std::string kJunkKey = "junk";
+  source_.Get(kJunkKey, *data_ready_);
+
+  EXPECT_TRUE(success_);
+  EXPECT_EQ(kJunkKey, key_);
+  EXPECT_EQ("{}", data_);
+}
+
+// Verifies that aggregate requesting of a missing key will also return "{}".
+TEST_F(TestdataSourceTest, AggregateGetMissingKeyReturnsEmptyDictionary) {
+  static const std::string kJunkKey = "junk";
+  aggregate_source_.Get(kJunkKey, *data_ready_);
+
+  EXPECT_TRUE(success_);
+  EXPECT_EQ(kJunkKey, key_);
+  EXPECT_EQ("{}", data_);
+}
+
+// Verifies that requesting an empty key will return "{}".
+TEST_F(TestdataSourceTest, GetEmptyKeyReturnsEmptyDictionary) {
+  static const std::string kEmptyKey;
+  source_.Get(kEmptyKey, *data_ready_);
+
+  EXPECT_TRUE(success_);
+  EXPECT_EQ(kEmptyKey, key_);
+  EXPECT_EQ("{}", data_);
+}
+
+}  // namespace
diff --git a/cpp/test/util/json_test.cc b/cpp/test/util/json_test.cc
index f6eb389..594c341 100644
--- a/cpp/test/util/json_test.cc
+++ b/cpp/test/util/json_test.cc
@@ -22,7 +22,6 @@
 namespace {
 
 using i18n::addressinput::Json;
-using i18n::addressinput::scoped_ptr;
 
 TEST(JsonTest, EmptyStringIsNotValid) {
   Json json;
@@ -32,8 +31,9 @@
 TEST(JsonTest, EmptyDictionaryContainsNoKeys) {
   Json json;
   ASSERT_TRUE(json.ParseObject("{}"));
-  EXPECT_FALSE(json.HasStringValueForKey("key"));
-  EXPECT_FALSE(json.HasStringValueForKey(std::string()));
+  std::string not_checked;
+  EXPECT_FALSE(json.GetStringValueForKey("key", &not_checked));
+  EXPECT_FALSE(json.GetStringValueForKey(std::string(), &not_checked));
 }
 
 TEST(JsonTest, InvalidJsonIsNotValid) {
@@ -44,35 +44,40 @@
 TEST(JsonTest, OneKeyIsValid) {
   Json json;
   ASSERT_TRUE(json.ParseObject("{\"key\": \"value\"}"));
-  ASSERT_TRUE(json.HasStringValueForKey("key"));
-  EXPECT_EQ("value", json.GetStringValueForKey("key"));
+  std::string value;
+  EXPECT_TRUE(json.GetStringValueForKey("key", &value));
+  EXPECT_EQ("value", value);
 }
 
 TEST(JsonTest, EmptyStringKeyIsNotInObject) {
   Json json;
   ASSERT_TRUE(json.ParseObject("{\"key\": \"value\"}"));
-  EXPECT_FALSE(json.HasStringValueForKey(std::string()));
+  std::string not_checked;
+  EXPECT_FALSE(json.GetStringValueForKey(std::string(), &not_checked));
 }
 
 TEST(JsonTest, EmptyKeyIsValid) {
   Json json;
   ASSERT_TRUE(json.ParseObject("{\"\": \"value\"}"));
-  ASSERT_TRUE(json.HasStringValueForKey(std::string()));
-  EXPECT_EQ("value", json.GetStringValueForKey(std::string()));
+  std::string value;
+  EXPECT_TRUE(json.GetStringValueForKey(std::string(), &value));
+  EXPECT_EQ("value", value);
 }
 
 TEST(JsonTest, EmptyValueIsValid) {
   Json json;
   ASSERT_TRUE(json.ParseObject("{\"key\": \"\"}"));
-  ASSERT_TRUE(json.HasStringValueForKey("key"));
-  EXPECT_TRUE(json.GetStringValueForKey("key").empty());
+  std::string value;
+  EXPECT_TRUE(json.GetStringValueForKey("key", &value));
+  EXPECT_TRUE(value.empty());
 }
 
 TEST(JsonTest, Utf8EncodingIsValid) {
   Json json;
-  ASSERT_TRUE(json.ParseObject("{\"key\": \"Ü\"}"));
-  ASSERT_TRUE(json.HasStringValueForKey("key"));
-  EXPECT_EQ("Ü", json.GetStringValueForKey("key"));
+  ASSERT_TRUE(json.ParseObject("{\"key\": \"\xC3\x9C\"}"));  /* "Ü" */
+  std::string value;
+  EXPECT_TRUE(json.GetStringValueForKey("key", &value));
+  EXPECT_EQ("\xC3\x9C", value);  /* "Ü" */
 }
 
 TEST(JsonTest, InvalidUtf8IsNotValid) {
@@ -89,11 +94,12 @@
 TEST(JsonTest, TwoKeysAreValid) {
   Json json;
   ASSERT_TRUE(json.ParseObject("{\"key1\": \"value1\", \"key2\": \"value2\"}"));
-  ASSERT_TRUE(json.HasStringValueForKey("key1"));
-  EXPECT_EQ("value1", json.GetStringValueForKey("key1"));
+  std::string value;
+  EXPECT_TRUE(json.GetStringValueForKey("key1", &value));
+  EXPECT_EQ("value1", value);
 
-  ASSERT_TRUE(json.HasStringValueForKey("key2"));
-  EXPECT_EQ("value2", json.GetStringValueForKey("key2"));
+  EXPECT_TRUE(json.GetStringValueForKey("key2", &value));
+  EXPECT_EQ("value2", value);
 }
 
 TEST(JsonTest, ListIsNotValid) {
@@ -114,28 +120,35 @@
 TEST(JsonTest, NoDictionaryFound) {
   Json json;
   ASSERT_TRUE(json.ParseObject("{\"key\":\"value\"}"));
-  EXPECT_FALSE(json.HasDictionaryValueForKey("key"));
+  EXPECT_TRUE(json.GetSubDictionaries().empty());
 }
 
 TEST(JsonTest, DictionaryFound) {
   Json json;
   ASSERT_TRUE(json.ParseObject("{\"key\":{\"inner_key\":\"value\"}}"));
-  ASSERT_TRUE(json.HasDictionaryValueForKey("key"));
-  const Json& sub_json = json.GetDictionaryValueForKey("key");
-  ASSERT_TRUE(sub_json.HasStringValueForKey("inner_key"));
-  EXPECT_EQ("value", sub_json.GetStringValueForKey("inner_key"));
+  const std::vector<const Json*>& sub_dicts = json.GetSubDictionaries();
+  ASSERT_EQ(1U, sub_dicts.size());
+
+  std::string value;
+  EXPECT_TRUE(sub_dicts.front()->GetStringValueForKey("inner_key", &value));
+  EXPECT_EQ("value", value);
 }
 
-TEST(JsonTest, DictionariesHaveKeys) {
+TEST(JsonTest, DictionariesHaveSubDictionaries) {
   Json json;
-  ASSERT_TRUE(json.ParseObject("{\"key\":{\"inner_key\":\"value\"}}"));
-  std::vector<std::string> expected_keys(1, "key");
-  EXPECT_EQ(expected_keys, json.GetKeys());
+  ASSERT_TRUE(json.ParseObject(
+      "{\"key\":{\"inner_key\":{\"inner_inner_key\":\"value\"}}}"));
+  const std::vector<const Json*>& sub_dicts = json.GetSubDictionaries();
+  ASSERT_EQ(1U, sub_dicts.size());
 
-  ASSERT_TRUE(json.HasDictionaryValueForKey("key"));
-  const Json& sub_json = json.GetDictionaryValueForKey("key");
-  std::vector<std::string> expected_sub_keys(1, "inner_key");
-  EXPECT_EQ(expected_sub_keys, sub_json.GetKeys());
+  const std::vector<const Json*>& sub_sub_dicts =
+      sub_dicts.front()->GetSubDictionaries();
+  ASSERT_EQ(1U, sub_sub_dicts.size());
+
+  std::string value;
+  EXPECT_TRUE(
+      sub_sub_dicts.front()->GetStringValueForKey("inner_inner_key", &value));
+  EXPECT_EQ("value", value);
 }
 
 }  // namespace
diff --git a/cpp/test/util/scoped_ptr_unittest.cc b/cpp/test/util/scoped_ptr_unittest.cc
index 250ffca..633625c 100644
--- a/cpp/test/util/scoped_ptr_unittest.cc
+++ b/cpp/test/util/scoped_ptr_unittest.cc
@@ -9,6 +9,8 @@
 
 #include <libaddressinput/util/basictypes.h>
 
+#include <cstddef>
+
 #include <gtest/gtest.h>
 
 namespace {
diff --git a/cpp/test/util/string_compare_test.cc b/cpp/test/util/string_compare_test.cc
index 8f8d4d5..b35b7df 100644
--- a/cpp/test/util/string_compare_test.cc
+++ b/cpp/test/util/string_compare_test.cc
@@ -14,6 +14,8 @@
 
 #include "util/string_compare.h"
 
+#include <libaddressinput/util/basictypes.h>
+
 #include <string>
 
 #include <gtest/gtest.h>
@@ -42,7 +44,11 @@
 
 class StringCompareTest : public testing::TestWithParam<TestCase> {
  protected:
+  StringCompareTest() {}
   StringCompare compare_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StringCompareTest);
 };
 
 TEST_P(StringCompareTest, CorrectComparison) {
@@ -63,15 +69,39 @@
 
 INSTANTIATE_TEST_CASE_P(
     Comparisons, StringCompareTest,
-    testing::Values(TestCase("foo", "foo", true, false),
-                    TestCase("foo", "FOO", true, false),
-                    TestCase("bar", "foo", false, true),
-                    TestCase("강원도", "강원도", true, false),
-                    TestCase("강원도", "대구광역시", false, true),
-                    TestCase("ZÜRICH", "zürich", true, false),
-                    TestCase("абв", "где", false, true),
-                    TestCase("абв", "ГДЕ", false, true),
-                    TestCase("где", "абв", false, false),
-                    TestCase("где", "АБВ", false, false)));
+    testing::Values(
+        TestCase("foo", "foo", true, false),
+        TestCase("foo", "FOO", true, false),
+        TestCase("bar", "foo", false, true),
+        TestCase(
+            "\xEA\xB0\x95\xEC\x9B\x90\xEB\x8F\x84",  /* "강원도" */
+            "\xEA\xB0\x95\xEC\x9B\x90\xEB\x8F\x84",  /* "강원도" */
+            true, false),
+        TestCase(
+            /* "강원도" */
+            "\xEA\xB0\x95\xEC\x9B\x90\xEB\x8F\x84",
+            /* "대구광역시" */
+            "\xEB\x8C\x80\xEA\xB5\xAC\xEA\xB4\x91\xEC\x97\xAD\xEC\x8B\x9C",
+            false, true),
+        TestCase(
+            "Z\xC3\x9CRICH",  /* "ZÜRICH" */
+            "z\xC3\xBCrich",  /* "zürich" */
+            true, false),
+        TestCase(
+            "\xD0\xB0\xD0\xB1\xD0\xB2",  /* "абв" */
+            "\xD0\xB3\xD0\xB4\xD0\xB5",  /* "где" */
+            false, true),
+        TestCase(
+            "\xD0\xB0\xD0\xB1\xD0\xB2",  /* "абв" */
+            "\xD0\x93\xD0\x94\xD0\x95",  /* "ГДЕ" */
+            false, true),
+        TestCase(
+            "\xD0\xB3\xD0\xB4\xD0\xB5",  /* "где" */
+            "\xD0\xB0\xD0\xB1\xD0\xB2",  /* "абв" */
+            false, false),
+        TestCase(
+            "\xD0\xB3\xD0\xB4\xD0\xB5",  /* "где" */
+            "\xD0\x90\xD0\x91\xD0\x92",  /* "АБВ" */
+            false, false)));
 
 }  // namespace
diff --git a/cpp/test/util/string_util_test.cc b/cpp/test/util/string_util_test.cc
index 9933b31..e7de1fc 100644
--- a/cpp/test/util/string_util_test.cc
+++ b/cpp/test/util/string_util_test.cc
@@ -15,6 +15,7 @@
 #include "util/string_util.h"
 
 #include <string>
+#include <vector>
 
 #include <gtest/gtest.h>
 
diff --git a/cpp/test/validating_storage_test.cc b/cpp/test/validating_storage_test.cc
index ced22dc..3c8aa53 100644
--- a/cpp/test/validating_storage_test.cc
+++ b/cpp/test/validating_storage_test.cc
@@ -16,6 +16,7 @@
 
 #include <libaddressinput/callback.h>
 #include <libaddressinput/storage.h>
+#include <libaddressinput/util/basictypes.h>
 #include <libaddressinput/util/scoped_ptr.h>
 
 #include <cstddef>
@@ -45,26 +46,22 @@
 const char kEmptyData[] = "";
 
 // Tests for ValidatingStorage object.
-class ValidatingStorageTest : public testing::Test  {
+class ValidatingStorageTest : public testing::Test {
  protected:
   ValidatingStorageTest()
       : wrapped_storage_(new FakeStorage),
         storage_(wrapped_storage_),
         success_(false),
         key_(),
-        data_() {}
-
-  virtual ~ValidatingStorageTest() {}
-
-  ValidatingStorage::Callback* BuildCallback() {
-    return ::BuildCallback(this, &ValidatingStorageTest::OnDataReady);
-  }
+        data_(),
+        data_ready_(BuildCallback(this, &ValidatingStorageTest::OnDataReady)) {}
 
   Storage* const wrapped_storage_;  // Owned by |storage_|.
   ValidatingStorage storage_;
   bool success_;
   std::string key_;
   std::string data_;
+  const scoped_ptr<const ValidatingStorage::Callback> data_ready_;
 
  private:
   void OnDataReady(bool success, const std::string& key, std::string* data) {
@@ -76,13 +73,13 @@
       delete data;
     }
   }
+
+  DISALLOW_COPY_AND_ASSIGN(ValidatingStorageTest);
 };
 
 TEST_F(ValidatingStorageTest, GoodData) {
   storage_.Put(kKey, new std::string(kValidatedData));
-
-  scoped_ptr<ValidatingStorage::Callback> callback(BuildCallback());
-  storage_.Get(kKey, *callback);
+  storage_.Get(kKey, *data_ready_);
 
   EXPECT_TRUE(success_);
   EXPECT_EQ(kKey, key_);
@@ -91,9 +88,7 @@
 
 TEST_F(ValidatingStorageTest, EmptyData) {
   storage_.Put(kKey, new std::string(kEmptyData));
-
-  scoped_ptr<ValidatingStorage::Callback> callback(BuildCallback());
-  storage_.Get(kKey, *callback);
+  storage_.Get(kKey, *data_ready_);
 
   EXPECT_TRUE(success_);
   EXPECT_EQ(kKey, key_);
@@ -101,8 +96,7 @@
 }
 
 TEST_F(ValidatingStorageTest, MissingKey) {
-  scoped_ptr<ValidatingStorage::Callback> callback(BuildCallback());
-  storage_.Get(kKey, *callback);
+  storage_.Get(kKey, *data_ready_);
 
   EXPECT_FALSE(success_);
   EXPECT_EQ(kKey, key_);
@@ -112,9 +106,7 @@
 TEST_F(ValidatingStorageTest, GarbageData) {
   storage_.Put(kKey, new std::string(kValidatedData));
   wrapped_storage_->Put(kKey, new std::string("garbage"));
-
-  scoped_ptr<ValidatingStorage::Callback> callback(BuildCallback());
-  storage_.Get(kKey, *callback);
+  storage_.Get(kKey, *data_ready_);
 
   EXPECT_FALSE(success_);
   EXPECT_EQ(kKey, key_);
@@ -124,9 +116,7 @@
 TEST_F(ValidatingStorageTest, StaleData) {
   storage_.Put(kKey, new std::string(kValidatedData));
   wrapped_storage_->Put(kKey, new std::string(kStaleWrappedData));
-
-  scoped_ptr<ValidatingStorage::Callback> callback(BuildCallback());
-  storage_.Get(kKey, *callback);
+  storage_.Get(kKey, *data_ready_);
 
   EXPECT_FALSE(success_);
   EXPECT_EQ(kKey, key_);
diff --git a/cpp/test/validation_task_test.cc b/cpp/test/validation_task_test.cc
index 011a978..9caf996 100644
--- a/cpp/test/validation_task_test.cc
+++ b/cpp/test/validation_task_test.cc
@@ -34,8 +34,6 @@
 namespace i18n {
 namespace addressinput {
 
-class LookupKey;
-
 class ValidationTaskTest : public testing::Test {
  protected:
   ValidationTaskTest()
@@ -59,6 +57,7 @@
       SORTING_CODE,
       POSTAL_CODE,
       STREET_ADDRESS,
+      ORGANIZATION,
       RECIPIENT
     };
 
@@ -85,8 +84,6 @@
     filter_.insert(std::make_pair(RECIPIENT, MISSING_REQUIRED_FIELD));
   }
 
-  virtual ~ValidationTaskTest() {}
-
   void Validate() {
     Rule rule[arraysize(json_)];
 
@@ -217,12 +214,14 @@
   address_.locality = "ccc";
   address_.postal_code = "zzz";
   address_.address_line.push_back("aaa");
+  address_.organization = "ooo";
   address_.recipient = "nnn";
 
   filter_.insert(std::make_pair(ADMIN_AREA, MISSING_REQUIRED_FIELD));
   filter_.insert(std::make_pair(LOCALITY, MISSING_REQUIRED_FIELD));
   filter_.insert(std::make_pair(POSTAL_CODE, MISSING_REQUIRED_FIELD));
   filter_.insert(std::make_pair(STREET_ADDRESS, MISSING_REQUIRED_FIELD));
+  filter_.insert(std::make_pair(ORGANIZATION, MISSING_REQUIRED_FIELD));
 
   ASSERT_NO_FATAL_FAILURE(Validate());
   ASSERT_TRUE(called_);
diff --git a/java/res/values/address_strings.xml b/java/res/values/address_strings.xml
index 57b34c4..f12247a 100644
--- a/java/res/values/address_strings.xml
+++ b/java/res/values/address_strings.xml
@@ -80,6 +80,9 @@
     <!-- 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] -->
+    <string name="i18n_oblast">Oblast</string>
+
     <!-- Administrative Area for certain countries (e.g., Andorra's Canillo) [CHAR LIMIT=30] -->
     <string name="i18n_parish">Parish</string>
 
@@ -140,6 +143,10 @@
          (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>
diff --git a/java/src/com/android/i18n/addressinput/AddressDataKey.java b/java/src/com/android/i18n/addressinput/AddressDataKey.java
index 33ffd74..a4766af 100644
--- a/java/src/com/android/i18n/addressinput/AddressDataKey.java
+++ b/java/src/com/android/i18n/addressinput/AddressDataKey.java
@@ -56,11 +56,15 @@
      */
     LFMT,
     /**
+     * Indicates the type of the name used for the locality (city) field.
+     */
+    LOCALITY_NAME_TYPE,
+    /**
      * Indicates which fields must be present in a valid address.
      */
     REQUIRE,
     /**
-     * Indicates the name used for the admin areas for a particular region.
+     * Indicates the type of the name used for the state (administrative area) field.
      */
     STATE_NAME_TYPE,
     /**
@@ -90,7 +94,7 @@
      */
     ZIP,
     /**
-     * Indicates the name used for the postal code for a particular region.
+     * Indicates the type of the name used for the ZIP (postal code) field.
      */
     ZIP_NAME_TYPE;
 
diff --git a/java/src/com/android/i18n/addressinput/AddressField.java b/java/src/com/android/i18n/addressinput/AddressField.java
index b951021..17b1817 100644
--- a/java/src/com/android/i18n/addressinput/AddressField.java
+++ b/java/src/com/android/i18n/addressinput/AddressField.java
@@ -24,14 +24,14 @@
  * formatting. Note that the metadata also has a character for newlines, which is not defined here.
  */
 public enum AddressField {
-    ADMIN_AREA('S', "state"),
-    LOCALITY('C', "city"),
-    RECIPIENT('N', "name"),
-    ORGANIZATION('O', "organization"),
+    ADMIN_AREA('S'),
+    LOCALITY('C'),
+    RECIPIENT('N'),
+    ORGANIZATION('O'),
     // Deprecated - use A instead.
-    ADDRESS_LINE_1('1', "street1"),
+    ADDRESS_LINE_1('1'),
     // Deprecated - use A instead.
-    ADDRESS_LINE_2('2', "street2"),
+    ADDRESS_LINE_2('2'),
     DEPENDENT_LOCALITY('D'),
     POSTAL_CODE('Z'),
     SORTING_CODE('X'),
@@ -58,15 +58,8 @@
 
     private final char mField;
 
-    private final String mAttributeName;
-
-    private AddressField(char field, String attributeName) {
-        mField = field;
-        mAttributeName = attributeName;
-    }
-
     private AddressField(char field) {
-        this(field, null);
+        mField = field;
     }
 
     /**
@@ -78,17 +71,6 @@
     }
 
     /**
-     * Gets attribute name. Attribute names are used as keys to JSON address data returned from the
-     * server. Returns null if the field does not have a corresponding attribute name.
-     *
-     * Note: Not all address fields have attribute names. Fields like postal code, country, sorting
-     * code, or street address do not have attribute names.
-     */
-    String getAttributeName() {
-        return mAttributeName;
-    }
-
-    /**
      * Gets the field's identification character, as used in the metadata.
      *
      * @return identification char.
diff --git a/java/src/com/android/i18n/addressinput/AddressWidget.java b/java/src/com/android/i18n/addressinput/AddressWidget.java
index 2ebfeef..c377e2c 100644
--- a/java/src/com/android/i18n/addressinput/AddressWidget.java
+++ b/java/src/com/android/i18n/addressinput/AddressWidget.java
@@ -81,11 +81,16 @@
 
     private ScriptType mScript;
 
+    // The appropriate label that should be applied to the locality (city) field of the current
+    // country.  Examples include "city" or "district".
+    private String mLocalityLabel;
+
     // 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 Map<String, Integer> ADMIN_LABELS;
+    private static final Map<String, Integer> LOCALITY_LABELS;
     private static final Map<String, Integer> ADMIN_ERROR_MESSAGES;
 
     private static final FormOptions SHOW_ALL_FIELDS = new FormOptions.Builder().build();
@@ -107,12 +112,18 @@
         adminLabelMap.put("do_si", R.string.i18n_do_si);
         adminLabelMap.put("emirate", R.string.i18n_emirate);
         adminLabelMap.put("island", R.string.i18n_island);
+        adminLabelMap.put("oblast", R.string.i18n_oblast);
         adminLabelMap.put("parish", R.string.i18n_parish);
         adminLabelMap.put("prefecture", R.string.i18n_prefecture);
         adminLabelMap.put("province", R.string.i18n_province);
         adminLabelMap.put("state", R.string.i18n_state_label);
         ADMIN_LABELS = Collections.unmodifiableMap(adminLabelMap);
 
+        Map<String, Integer> 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);
+
         Map<String, Integer> adminErrorMap = new HashMap<String, Integer>(15);
         adminErrorMap.put("area", R.string.invalid_area);
         adminErrorMap.put("county", R.string.invalid_county_label);
@@ -121,6 +132,7 @@
         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);
@@ -266,7 +278,7 @@
 
         // Set up AddressField.LOCALITY
         AddressUiComponent localityUi = new AddressUiComponent(AddressField.LOCALITY);
-        localityUi.setFieldName(mContext.getString(R.string.i18n_locality_label));
+        localityUi.setFieldName(getLocalityFieldName(countryNode));
         mInputWidgets.put(AddressField.LOCALITY, localityUi);
 
         // Set up AddressField.DEPENDENT_LOCALITY
@@ -330,6 +342,17 @@
         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;
diff --git a/java/src/com/android/i18n/addressinput/FormatInterpreter.java b/java/src/com/android/i18n/addressinput/FormatInterpreter.java
index ffd19b1..ed7b2ac 100644
--- a/java/src/com/android/i18n/addressinput/FormatInterpreter.java
+++ b/java/src/com/android/i18n/addressinput/FormatInterpreter.java
@@ -155,15 +155,16 @@
 
         List<String> lines = new ArrayList<String>();
         StringBuilder currentLine = new StringBuilder();
-        for (String substr : getFormatSubStrings(scriptType, regionCode)) {
-            if (substr.equals(NEW_LINE)) {
-                String normalizedStr = removeAllRedundantSpaces(currentLine.toString());
+        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 (substr.startsWith("%")) {
-                char c = substr.charAt(1);
+            } else if (formatSymbol.startsWith("%")) {
+                char c = formatSymbol.charAt(1);
                 AddressField field = AddressField.of(c);
                 Util.checkNotNull(field, "null address field for character " + c);
 
@@ -203,10 +204,10 @@
                     currentLine.append(value);
                 }
             } else {
-                currentLine.append(substr);
+                currentLine.append(formatSymbol);
             }
         }
-        String normalizedStr = removeAllRedundantSpaces(currentLine.toString());
+        String normalizedStr = removeRedundantSpacesAndLeadingPunctuation(currentLine.toString());
         if (normalizedStr.length() > 0) {
             lines.add(normalizedStr);
         }
@@ -242,13 +243,16 @@
         return parts;
     }
 
-    private String removeAllRedundantSpaces(String str) {
+    private static String removeRedundantSpacesAndLeadingPunctuation(String str) {
+        // Remove leading commas and other punctuation that might have been added by the formatter
+        // in the case of missing data.
+        str = str.replaceFirst("^[-,\\s]+", "");
         str = str.trim();
         str = str.replaceAll(" +", " ");
         return str;
     }
 
-    private String getFormatString(ScriptType scriptType, String regionCode) {
+    private static String getFormatString(ScriptType scriptType, String regionCode) {
         String format = (scriptType == ScriptType.LOCAL)
                 ? getJsonValue(regionCode, AddressDataKey.FMT)
                 : getJsonValue(regionCode, AddressDataKey.LFMT);
@@ -258,7 +262,7 @@
         return format;
     }
 
-    private String getJsonValue(String regionCode, AddressDataKey key) {
+    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);
diff --git a/java/src/com/android/i18n/addressinput/RegionDataConstants.java b/java/src/com/android/i18n/addressinput/RegionDataConstants.java
index 48affab..4f4c5b7 100644
--- a/java/src/com/android/i18n/addressinput/RegionDataConstants.java
+++ b/java/src/com/android/i18n/addressinput/RegionDataConstants.java
@@ -41,10 +41,8 @@
                 "name", "ANDORRA",
                 "lang", "ca",
                 "languages", "ca",
-                "fmt", "%N%n%O%n%A%n%Z %S",
-                "require", "AS",
-                "upper", "S",
-                "state_name_type", "parish",
+                "fmt", "%N%n%O%n%A%n%Z %C",
+                "require", "A",
         }),
         AE(new String[]{
                 "name", "UNITED ARAB EMIRATES",
@@ -311,7 +309,7 @@
         }),
         DK(new String[]{
                 "name", "DENMARK",
-                "fmt", "%O%n%N%n%A%n%Z %C",
+                "fmt", "%N%n%O%n%A%n%Z %C",
                 "require", "ACZ",
         }),
         DM(new String[]{
@@ -977,8 +975,9 @@
         }),
         RU(new String[]{
                 "name", "RUSSIAN FEDERATION",
-                "fmt", "%Z %C  %n%A%n%O%n%N",
+                "fmt", "%N%n%O%n%A%n%C%n%S%n%Z",
                 "require", "ACZ",
+                "state_name_type", "oblast",
                 "upper", "AC",
         }),
         RW(new String[]{
@@ -1124,6 +1123,7 @@
                 "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",
@@ -1167,7 +1167,7 @@
                 "name", "UNITED STATES",
                 "lang", "en",
                 "languages", "en",
-                "fmt", "%N%n%O%n%A%n%C %S %Z",
+                "fmt", "%N%n%O%n%A%n%C, %S %Z",
                 "require", "ACSZ",
                 "upper", "CS",
                 "zip_name_type", "zip",
@@ -1269,6 +1269,7 @@
                 "upper", "C",
                 "zip_name_type", "postal",
                 "state_name_type", "province",
+                "locality_name_type", "city",
         });
 
         private String jsonString;
diff --git a/java/test/com/android/i18n/addressinput/AddressFieldTest.java b/java/test/com/android/i18n/addressinput/AddressFieldTest.java
index 3419097..aa0a741 100644
--- a/java/test/com/android/i18n/addressinput/AddressFieldTest.java
+++ b/java/test/com/android/i18n/addressinput/AddressFieldTest.java
@@ -30,8 +30,4 @@
     public void testGetChar() throws Exception {
         assertEquals('R', AddressField.COUNTRY.getChar());
     }
-
-    public void testGetAttributeName() throws Exception {
-        assertEquals("name", AddressField.RECIPIENT.getAttributeName());
-    }
 }
diff --git a/java/test/com/android/i18n/addressinput/ClientDataTest.java b/java/test/com/android/i18n/addressinput/ClientDataTest.java
index 570434e..b18d726 100644
--- a/java/test/com/android/i18n/addressinput/ClientDataTest.java
+++ b/java/test/com/android/i18n/addressinput/ClientDataTest.java
@@ -78,6 +78,6 @@
         // data from there.
         assertNotNull(data);
         String unitedStatesFormatInfo = data.get(AddressDataKey.FMT);
-        assertEquals("%N%n%O%n%A%n%C %S %Z", unitedStatesFormatInfo);
+        assertEquals("%N%n%O%n%A%n%C, %S %Z", unitedStatesFormatInfo);
     }
 }
diff --git a/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java b/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java
index 50372ed..f5bac79 100644
--- a/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java
+++ b/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java
@@ -147,7 +147,7 @@
     public void testUsEnvelopeAddress() {
         List<String> expected = new ArrayList<String>();
         expected.add("1098 Alta Ave");
-        expected.add("Mt View CA 94043");
+        expected.add("Mt View, CA 94043");
 
         List<String> real = formatInterpreter.getEnvelopeAddress(US_CA_ADDRESS);
 
@@ -189,4 +189,44 @@
         List<String> real = formatInterpreter.getEnvelopeAddress(address);
         assertEquals(expected, real);
     }
+
+  public void testEnvelopeAddressLeadingPostPrefix() {
+      List<String> expected = new ArrayList<String>();
+      expected.add("CH-8047 Herrliberg");
+      AddressData address = new AddressData.Builder().setCountry("CH")
+              .setPostalCode("8047")
+              .setLocality("Herrliberg")
+              .build();
+
+      List<String> real = formatInterpreter.getEnvelopeAddress(address);
+      assertEquals(expected, real);
+  }
+
+  public void testSvAddress() {
+      final AddressData svAddress = new AddressData.Builder().setCountry("SV")
+              .setAdminArea("Ahuachapán")
+              .setLocality("Ahuachapán")
+              .setAddressLine1("Some Street 12")
+              .build();
+
+      List<String> expected = new ArrayList<String>();
+      expected.add("Some Street 12");
+      expected.add("Ahuachapán");
+      expected.add("Ahuachapán");
+
+      List<String> real = formatInterpreter.getEnvelopeAddress(svAddress);
+      assertEquals(expected, real);
+
+      final AddressData svAddressWithPostCode = new AddressData.Builder(svAddress)
+              .setPostalCode("CP 2101")
+              .build();
+
+      expected = new ArrayList<String>();
+      expected.add("Some Street 12");
+      expected.add("CP 2101-Ahuachapán");
+      expected.add("Ahuachapán");
+
+      real = formatInterpreter.getEnvelopeAddress(svAddressWithPostCode);
+      assertEquals(expected, real);
+  }
 }