diff options
author | rouslan@chromium.org <rouslan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-10 02:24:24 +0000 |
---|---|---|
committer | rouslan@chromium.org <rouslan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-10 02:24:24 +0000 |
commit | b1d6cbf2e9125f7eb874a25056cdf7e036f52c3a (patch) | |
tree | 9e13cbbffe3df4018b81472becca9f87a0f5de79 /third_party/libaddressinput | |
parent | e9149ab55ec7676aa4813a8b19772fadb4e6cdcb (diff) | |
download | chromium_src-b1d6cbf2e9125f7eb874a25056cdf7e036f52c3a.zip chromium_src-b1d6cbf2e9125f7eb874a25056cdf7e036f52c3a.tar.gz chromium_src-b1d6cbf2e9125f7eb874a25056cdf7e036f52c3a.tar.bz2 |
[rac] Validate an address.
BUG=327046
Review URL: https://codereview.chromium.org/116363003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244046 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party/libaddressinput')
13 files changed, 388 insertions, 69 deletions
diff --git a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h index d6ae6c0..8c8b75e 100644 --- a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h +++ b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h @@ -19,6 +19,8 @@ #ifndef I18N_ADDRESSINPUT_ADDRESS_DATA_H_ #define I18N_ADDRESSINPUT_ADDRESS_DATA_H_ +#include <libaddressinput/address_field.h> + #include <string> #include <vector> @@ -31,14 +33,16 @@ namespace addressinput { // address.address_lines.push_back("1098 Alta Ave"); // address.administrative_area = "CA"; // address.locality = "Mountain View"; -// address.dependent_locality = ""; // address.postal_code = "94043"; -// address.sorting_code = ""; // address.organization = "Google"; // address.recipient = "Chen-Kang Yang"; // address.language_code = "en"; // Process(address); struct AddressData { + // Returns the value of the |field|. The parameter should not be + // STREET_ADDRESS, which comprises multiple fields. + const std::string& GetField(AddressField field) const; + // The BCP 47 language code used to guide how the address is formatted for // display. The same address may have different representations in different // languages. diff --git a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_problem.h b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_problem.h index 559fcfd..841f8d1 100644 --- a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_problem.h +++ b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_problem.h @@ -59,6 +59,9 @@ struct AddressProblem { MISMATCHING_VALUE }; + AddressProblem(AddressField field, Type type, const std::string& description); + ~AddressProblem(); + // The address field that has the problem. AddressField field; diff --git a/third_party/libaddressinput/chromium/cpp/libaddressinput.gyp b/third_party/libaddressinput/chromium/cpp/libaddressinput.gyp index 0cac4cb..0c59994 100644 --- a/third_party/libaddressinput/chromium/cpp/libaddressinput.gyp +++ b/third_party/libaddressinput/chromium/cpp/libaddressinput.gyp @@ -31,6 +31,7 @@ 'target_name': 'libaddressinput', 'type': '<(component)', 'sources': [ + 'src/address_data.cc', 'src/address_field.cc', 'src/address_problem.cc', 'src/address_ui.cc', diff --git a/third_party/libaddressinput/chromium/cpp/src/address_data.cc b/third_party/libaddressinput/chromium/cpp/src/address_data.cc new file mode 100644 index 0000000..9b86cc8 --- /dev/null +++ b/third_party/libaddressinput/chromium/cpp/src/address_data.cc @@ -0,0 +1,50 @@ +// 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 <libaddressinput/address_data.h> + +#include <libaddressinput/address_field.h> + +#include <cassert> +#include <string> + +namespace i18n { +namespace addressinput { + +const std::string& AddressData::GetField(AddressField field) const { + switch (field) { + case COUNTRY: + return country_code; + case ADMIN_AREA: + return administrative_area; + case LOCALITY: + return locality; + case DEPENDENT_LOCALITY: + return dependent_locality; + case SORTING_CODE: + return sorting_code; + case POSTAL_CODE: + return postal_code; + case ORGANIZATION: + return organization; + case RECIPIENT: + return recipient; + default: + assert(false); + return recipient; + } +} + +} // namespace addressinput +} // namespace i18n diff --git a/third_party/libaddressinput/chromium/cpp/src/address_problem.cc b/third_party/libaddressinput/chromium/cpp/src/address_problem.cc index 14a0030..d823e11 100644 --- a/third_party/libaddressinput/chromium/cpp/src/address_problem.cc +++ b/third_party/libaddressinput/chromium/cpp/src/address_problem.cc @@ -15,10 +15,18 @@ #include <libaddressinput/address_problem.h> #include <ostream> +#include <string> namespace i18n { namespace addressinput { +AddressProblem::AddressProblem(AddressField field, + Type type, + const std::string& description) + : field(field), type(type), description(description) {} + +AddressProblem::~AddressProblem() {} + std::ostream& operator<<(std::ostream& o, AddressProblem::Type problem_type) { switch (problem_type) { case AddressProblem::MISSING_REQUIRED_FIELD: diff --git a/third_party/libaddressinput/chromium/cpp/src/address_validator.cc b/third_party/libaddressinput/chromium/cpp/src/address_validator.cc index 04163a6..fdb4113 100644 --- a/third_party/libaddressinput/chromium/cpp/src/address_validator.cc +++ b/third_party/libaddressinput/chromium/cpp/src/address_validator.cc @@ -14,6 +14,7 @@ #include <libaddressinput/address_validator.h> +#include <libaddressinput/address_data.h> #include <libaddressinput/downloader.h> #include <libaddressinput/load_rules_delegate.h> #include <libaddressinput/localization.h> @@ -21,14 +22,19 @@ #include <libaddressinput/util/basictypes.h> #include <libaddressinput/util/scoped_ptr.h> +#include <algorithm> #include <cassert> #include <cstddef> #include <map> #include <set> #include <string> +#include <re2/re2.h> + #include "country_rules_aggregator.h" +#include "messages.h" #include "retriever.h" +#include "rule.h" #include "ruleset.h" #include "util/stl_util.h" @@ -37,6 +43,25 @@ namespace addressinput { namespace { +// Returns true if the filter is empty (all problems allowed) or contains the +// |field|->|problem| mapping (explicitly allowed). +bool FilterAllows(const AddressProblemFilter& filter, + AddressField field, + AddressProblem::Type problem) { + if (filter.empty()) { + return true; + } + + for (AddressProblemFilter::const_iterator it = filter.begin(); + it != filter.end(); ++it) { + if (it->first == field && it->second == problem) { + return true; + } + } + + return false; +} + // Validates AddressData structure. class AddressValidatorImpl : public AddressValidator { public: @@ -74,8 +99,95 @@ class AddressValidatorImpl : public AddressValidator { const AddressProblemFilter& filter, const Localization& localization, AddressProblems* problems) const { - // TODO(rouslan): Validate the address. - return RULES_UNAVAILABLE; + std::map<std::string, const Ruleset*>::const_iterator ruleset_it = + rules_.find(address.country_code); + if (ruleset_it == rules_.end()) { + return loading_rules_.find(address.country_code) != loading_rules_.end() + ? RULES_NOT_READY + : RULES_UNAVAILABLE; + } + + const Ruleset* ruleset = ruleset_it->second; + assert(ruleset != NULL); + const Rule& country_rule = + ruleset->GetLanguageCodeRule(address.language_code); + + // Validate required fields. + for (std::vector<AddressField>::const_iterator + field_it = country_rule.GetRequired().begin(); + field_it != country_rule.GetRequired().end(); + ++field_it) { + if (address.GetField(*field_it).empty() && + FilterAllows( + filter, *field_it, AddressProblem::MISSING_REQUIRED_FIELD)) { + problems->push_back(AddressProblem( + *field_it, + AddressProblem::MISSING_REQUIRED_FIELD, + localization.GetString( + IDS_LIBADDRESSINPUT_I18N_MISSING_REQUIRED_FIELD))); + } + } + + // Validate general postal code format. A country-level rule specifies the + // regular expression for the whole postal code. + if (!address.postal_code.empty() && + !country_rule.GetPostalCodeFormat().empty() && + FilterAllows(filter, + POSTAL_CODE, + AddressProblem::UNRECOGNIZED_FORMAT) && + !RE2::FullMatch( + address.postal_code, country_rule.GetPostalCodeFormat())) { + problems->push_back(AddressProblem( + POSTAL_CODE, + AddressProblem::UNRECOGNIZED_FORMAT, + localization.GetString( + country_rule.GetInvalidPostalCodeMessageId()))); + } + + while (ruleset != NULL) { + const Rule& rule = ruleset->GetLanguageCodeRule(address.language_code); + + // Validate the field values, e.g. state names in US. + AddressField sub_field_type = + static_cast<AddressField>(ruleset->field() + 1); + const std::string& sub_field = address.GetField(sub_field_type); + const std::vector<std::string>& sub_keys = rule.GetSubKeys(); + if (!sub_field.empty() && + !sub_keys.empty() && + FilterAllows(filter, sub_field_type, AddressProblem::UNKNOWN_VALUE) && + std::find(sub_keys.begin(), sub_keys.end(), sub_field) == + sub_keys.end()) { + problems->push_back(AddressProblem( + sub_field_type, + AddressProblem::UNKNOWN_VALUE, + localization.GetString( + country_rule.GetInvalidFieldMessageId(sub_field_type)))); + } + + // Validate sub-region specific postal code format. A sub-region specifies + // the regular expression for a prefix of the postal code. + int match_position = -1; + if (ruleset->field() > COUNTRY && + !address.postal_code.empty() && + !rule.GetPostalCodeFormat().empty() && + FilterAllows(filter, + POSTAL_CODE, + AddressProblem::MISMATCHING_VALUE) && + (!RE2::PartialMatch(address.postal_code, + rule.GetPostalCodeFormat(), + &match_position) || + match_position != 0)) { + problems->push_back(AddressProblem( + POSTAL_CODE, + AddressProblem::MISMATCHING_VALUE, + localization.GetString( + country_rule.GetInvalidPostalCodeMessageId()))); + } + + ruleset = ruleset->GetSubRegionRuleset(sub_field); + } + + return SUCCESS; } private: @@ -87,6 +199,8 @@ class AddressValidatorImpl : public AddressValidator { assert(rules_.find(country_code) == rules_.end()); loading_rules_.erase(country_code); if (success) { + assert(ruleset != NULL); + assert(ruleset->field() == COUNTRY); rules_[country_code] = ruleset.release(); } if (load_rules_delegate_ != NULL) { @@ -105,7 +219,7 @@ class AddressValidatorImpl : public AddressValidator { std::set<std::string> loading_rules_; // A mapping of a country code to the owned ruleset for that country code. - std::map<std::string, Ruleset*> rules_; + std::map<std::string, const Ruleset*> rules_; DISALLOW_COPY_AND_ASSIGN(AddressValidatorImpl); }; diff --git a/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc b/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc index 991a6e0..e268f86 100644 --- a/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc +++ b/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc @@ -143,11 +143,11 @@ void CountryRulesAggregator::OnDataReady(bool success, default_language_ = rule->GetLanguage(); languages_ = rule->GetLanguages(); - root_.reset(new Ruleset(rule.Pass())); + root_.reset(new Ruleset(request.level, rule.Pass())); ruleset = root_.get(); } else { assert(request.parent != NULL); - ruleset = new Ruleset(rule.Pass()); + ruleset = new Ruleset(request.level, rule.Pass()); request.parent->AddSubRegionRuleset( request.id, scoped_ptr<Ruleset>(ruleset)); } diff --git a/third_party/libaddressinput/chromium/cpp/src/rule.cc b/third_party/libaddressinput/chromium/cpp/src/rule.cc index 43d5c43..006ea58 100644 --- a/third_party/libaddressinput/chromium/cpp/src/rule.cc +++ b/third_party/libaddressinput/chromium/cpp/src/rule.cc @@ -111,49 +111,62 @@ void ParseAddressFieldsRequired(const std::string& required, } } -int GetAdminAreaMessageId(const std::string& admin_area_type) { +int GetAdminAreaMessageId(const std::string& admin_area_type, bool error) { if (admin_area_type == "area") { - return IDS_LIBADDRESSINPUT_I18N_AREA; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_AREA + : IDS_LIBADDRESSINPUT_I18N_AREA; } if (admin_area_type == "county") { - return IDS_LIBADDRESSINPUT_I18N_COUNTY_LABEL; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_COUNTY_LABEL + : IDS_LIBADDRESSINPUT_I18N_COUNTY_LABEL; } if (admin_area_type == "department") { - return IDS_LIBADDRESSINPUT_I18N_DEPARTMENT; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_DEPARTMENT + : IDS_LIBADDRESSINPUT_I18N_DEPARTMENT; } if (admin_area_type == "district") { - return IDS_LIBADDRESSINPUT_I18N_DEPENDENT_LOCALITY_LABEL; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_DEPENDENT_LOCALITY_LABEL + : IDS_LIBADDRESSINPUT_I18N_DEPENDENT_LOCALITY_LABEL; } if (admin_area_type == "do_si") { - return IDS_LIBADDRESSINPUT_I18N_DO_SI; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_DO_SI + : IDS_LIBADDRESSINPUT_I18N_DO_SI; } if (admin_area_type == "emirate") { - return IDS_LIBADDRESSINPUT_I18N_EMIRATE; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_EMIRATE + : IDS_LIBADDRESSINPUT_I18N_EMIRATE; } if (admin_area_type == "island") { - return IDS_LIBADDRESSINPUT_I18N_ISLAND; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_ISLAND + : IDS_LIBADDRESSINPUT_I18N_ISLAND; } if (admin_area_type == "parish") { - return IDS_LIBADDRESSINPUT_I18N_PARISH; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_PARISH + : IDS_LIBADDRESSINPUT_I18N_PARISH; } if (admin_area_type == "prefecture") { - return IDS_LIBADDRESSINPUT_I18N_PREFECTURE; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_PREFECTURE + : IDS_LIBADDRESSINPUT_I18N_PREFECTURE; } if (admin_area_type == "province") { - return IDS_LIBADDRESSINPUT_I18N_PROVINCE; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_PROVINCE + : IDS_LIBADDRESSINPUT_I18N_PROVINCE; } if (admin_area_type == "state") { - return IDS_LIBADDRESSINPUT_I18N_STATE_LABEL; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_STATE_LABEL + : IDS_LIBADDRESSINPUT_I18N_STATE_LABEL; } return INVALID_MESSAGE_ID; } -int GetPostalCodeMessageId(const std::string& postal_code_type) { +int GetPostalCodeMessageId(const std::string& postal_code_type, bool error) { if (postal_code_type == "postal") { - return IDS_LIBADDRESSINPUT_I18N_POSTAL_CODE_LABEL; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_POSTAL_CODE_LABEL + : IDS_LIBADDRESSINPUT_I18N_POSTAL_CODE_LABEL; } if (postal_code_type == "zip") { - return IDS_LIBADDRESSINPUT_I18N_ZIP_CODE_LABEL; + return error ? IDS_LIBADDRESSINPUT_I18N_INVALID_ZIP_CODE_LABEL + : IDS_LIBADDRESSINPUT_I18N_ZIP_CODE_LABEL; } return INVALID_MESSAGE_ID; } @@ -192,7 +205,9 @@ void Rule::CopyFrom(const Rule& rule) { language_ = rule.language_; postal_code_format_ = rule.postal_code_format_; admin_area_name_message_id_ = rule.admin_area_name_message_id_; + invalid_admin_area_message_id_ = rule.invalid_admin_area_message_id_; postal_code_name_message_id_ = rule.postal_code_name_message_id_; + invalid_postal_code_message_id_ = rule.invalid_postal_code_message_id_; } bool Rule::ParseSerializedRule(const std::string& serialized_rule) { @@ -230,15 +245,32 @@ bool Rule::ParseSerializedRule(const std::string& serialized_rule) { } if (json->GetStringValueForKey("state_name_type", &value)) { - admin_area_name_message_id_ = GetAdminAreaMessageId(value); + admin_area_name_message_id_ = GetAdminAreaMessageId(value, false); + invalid_admin_area_message_id_ = GetAdminAreaMessageId(value, true); } if (json->GetStringValueForKey("zip_name_type", &value)) { - postal_code_name_message_id_ = GetPostalCodeMessageId(value); + postal_code_name_message_id_ = GetPostalCodeMessageId(value, false); + invalid_postal_code_message_id_ = GetPostalCodeMessageId(value, true); } return true; } +int Rule::GetInvalidFieldMessageId(AddressField field) const { + switch (field) { + case ADMIN_AREA: + return invalid_admin_area_message_id_; + case LOCALITY: + return IDS_LIBADDRESSINPUT_I18N_INVALID_LOCALITY_LABEL; + case DEPENDENT_LOCALITY: + return IDS_LIBADDRESSINPUT_I18N_INVALID_DEPENDENT_LOCALITY_LABEL; + case POSTAL_CODE: + return invalid_postal_code_message_id_; + default: + return IDS_LIBADDRESSINPUT_I18N_INVALID_ENTRY; + } +} + } // namespace addressinput } // namespace i18n diff --git a/third_party/libaddressinput/chromium/cpp/src/rule.h b/third_party/libaddressinput/chromium/cpp/src/rule.h index eab1de7..9e6fa09 100644 --- a/third_party/libaddressinput/chromium/cpp/src/rule.h +++ b/third_party/libaddressinput/chromium/cpp/src/rule.h @@ -76,12 +76,27 @@ class Rule { // INVALID_MESSAGE_ID. int GetAdminAreaNameMessageId() const { return admin_area_name_message_id_; } + // The error message string identifier for an invalid admin area. If not set, + // then INVALID_MESSAGE_ID. + int GetInvalidAdminAreaMessageId() const { + return invalid_admin_area_message_id_; + } + // The message string identifier for postal code name. If not set, then // INVALID_MESSAGE_ID. int GetPostalCodeNameMessageId() const { return postal_code_name_message_id_; } + // The error message string identifier for an invalid postal code. If not set, + // then INVALID_MESSAGE_ID. + int GetInvalidPostalCodeMessageId() const { + return invalid_postal_code_message_id_; + } + + // Returns the error message string identifier for an invalid |field|. + int GetInvalidFieldMessageId(AddressField field) const; + private: std::vector<std::vector<AddressField> > format_; std::vector<AddressField> required_; @@ -90,7 +105,9 @@ class Rule { std::string language_; std::string postal_code_format_; int admin_area_name_message_id_; + int invalid_admin_area_message_id_; int postal_code_name_message_id_; + int invalid_postal_code_message_id_; DISALLOW_COPY_AND_ASSIGN(Rule); }; diff --git a/third_party/libaddressinput/chromium/cpp/src/ruleset.cc b/third_party/libaddressinput/chromium/cpp/src/ruleset.cc index 3201750..a3eca96 100644 --- a/third_party/libaddressinput/chromium/cpp/src/ruleset.cc +++ b/third_party/libaddressinput/chromium/cpp/src/ruleset.cc @@ -14,13 +14,13 @@ #include "ruleset.h" +#include <libaddressinput/address_field.h> #include <libaddressinput/util/scoped_ptr.h> #include <cassert> #include <cstddef> #include <map> #include <string> -#include <utility> #include "rule.h" #include "util/stl_util.h" @@ -28,10 +28,13 @@ namespace i18n { namespace addressinput { -Ruleset::Ruleset(scoped_ptr<Rule> rule) - : rule_(rule.Pass()), +Ruleset::Ruleset(AddressField field, scoped_ptr<Rule> rule) + : field_(field), + rule_(rule.Pass()), sub_regions_(), language_codes_() { + assert(field_ >= COUNTRY); + assert(field_ <= DEPENDENT_LOCALITY); assert(rule_ != NULL); } @@ -43,14 +46,30 @@ Ruleset::~Ruleset() { void Ruleset::AddSubRegionRuleset(const std::string& sub_region, scoped_ptr<Ruleset> ruleset) { assert(sub_regions_.find(sub_region) == sub_regions_.end()); + assert(ruleset != NULL); + assert(ruleset->field() == static_cast<AddressField>(field() + 1)); sub_regions_[sub_region] = ruleset.release(); } void Ruleset::AddLanguageCodeRule(const std::string& language_code, scoped_ptr<Rule> rule) { assert(language_codes_.find(language_code) == language_codes_.end()); + assert(rule != NULL); language_codes_[language_code] = rule.release(); } +Ruleset* Ruleset::GetSubRegionRuleset(const std::string& sub_region) const { + std::map<std::string, Ruleset*>::const_iterator it = + sub_regions_.find(sub_region); + return it != sub_regions_.end() ? it->second : NULL; +} + +const Rule& Ruleset::GetLanguageCodeRule( + const std::string& language_code) const { + std::map<std::string, const Rule*>::const_iterator it = + language_codes_.find(language_code); + return it != language_codes_.end() ? *it->second : *rule_; +} + } // namespace addressinput } // namespace i18n diff --git a/third_party/libaddressinput/chromium/cpp/src/ruleset.h b/third_party/libaddressinput/chromium/cpp/src/ruleset.h index 224d8e9..2e5dbbe 100644 --- a/third_party/libaddressinput/chromium/cpp/src/ruleset.h +++ b/third_party/libaddressinput/chromium/cpp/src/ruleset.h @@ -15,6 +15,7 @@ #ifndef I18N_ADDRESSINPUT_RULESET_H_ #define I18N_ADDRESSINPUT_RULESET_H_ +#include <libaddressinput/address_field.h> #include <libaddressinput/util/basictypes.h> #include <libaddressinput/util/scoped_ptr.h> @@ -42,26 +43,49 @@ class Rule; // language version. class Ruleset { public: - // Builds a ruleset with a region-wide |rule| in the default language of the - // country. The |rule| should not be NULL. - explicit Ruleset(scoped_ptr<Rule> rule); + // Builds a ruleset for |field| with a region-wide |rule| in the default + // language of the country. The |field| should be between COUNTRY and + // DEPENDENT_LOCALITY (inclusively). The |rule| should not be NULL. + Ruleset(AddressField field, scoped_ptr<Rule> rule); ~Ruleset(); - // Returns the region-wide rule in the default language of the country. - const Rule& rule() const { return *rule_.get(); } + // Returns the field type for this ruleset. + AddressField field() const { return field_; } - // Adds and the |ruleset| for |sub_region|. + // Returns the region-wide rule for this ruleset in the default language of + // the country. + const Rule& rule() const { return *rule_; } + + // Adds the |ruleset| for |sub_region|. A |sub_region| should be added at most + // once. The |ruleset| should not be NULL. + // + // The field of the |ruleset| parameter must be exactly one smaller than the + // field of this ruleset. For example, a COUNTRY ruleset can contain + // ADMIN_AREA rulesets, but should not contain COUNTRY or LOCALITY rulesets. void AddSubRegionRuleset(const std::string& sub_region, scoped_ptr<Ruleset> ruleset); - // Adds a language-specific |rule| for |language_code| for this region. + // Adds a language-specific |rule| for |language_code| for this region. A + // |language_code| should be added at most once. The |rule| should not be + // NULL. void AddLanguageCodeRule(const std::string& language_code, scoped_ptr<Rule> rule); + // Returns the set of rules for |sub_region|. The result is NULL if there's no + // such |sub_region|. The caller does not own the result. + Ruleset* GetSubRegionRuleset(const std::string& sub_region) const; + + // If there's a language-specific rule for |language_code|, then returns this + // rule. Otherwise returns the rule in the default language of the country. + const Rule& GetLanguageCodeRule(const std::string& language_code) const; + private: + // The field of this ruleset. + const AddressField field_; + // The region-wide rule in the default language of the country. - scoped_ptr<const Rule> rule_; + const scoped_ptr<const Rule> rule_; // Owned rulesets for sub-regions. std::map<std::string, Ruleset*> sub_regions_; diff --git a/third_party/libaddressinput/chromium/cpp/test/rule_test.cc b/third_party/libaddressinput/chromium/cpp/test/rule_test.cc index b484555..da10680 100644 --- a/third_party/libaddressinput/chromium/cpp/test/rule_test.cc +++ b/third_party/libaddressinput/chromium/cpp/test/rule_test.cc @@ -71,8 +71,12 @@ TEST(RuleTest, CopyOverwritesRule) { EXPECT_NE(rule.GetPostalCodeFormat(), copy.GetPostalCodeFormat()); EXPECT_NE(rule.GetAdminAreaNameMessageId(), copy.GetAdminAreaNameMessageId()); + EXPECT_NE(rule.GetInvalidAdminAreaMessageId(), + copy.GetInvalidAdminAreaMessageId()); EXPECT_NE(rule.GetPostalCodeNameMessageId(), copy.GetPostalCodeNameMessageId()); + EXPECT_NE(rule.GetInvalidPostalCodeMessageId(), + copy.GetInvalidPostalCodeMessageId()); copy.CopyFrom(rule); EXPECT_EQ(rule.GetFormat(), copy.GetFormat()); @@ -83,8 +87,12 @@ TEST(RuleTest, CopyOverwritesRule) { EXPECT_EQ(rule.GetPostalCodeFormat(), copy.GetPostalCodeFormat()); EXPECT_EQ(rule.GetAdminAreaNameMessageId(), copy.GetAdminAreaNameMessageId()); + EXPECT_EQ(rule.GetInvalidAdminAreaMessageId(), + copy.GetInvalidAdminAreaMessageId()); EXPECT_EQ(rule.GetPostalCodeNameMessageId(), copy.GetPostalCodeNameMessageId()); + EXPECT_EQ(rule.GetInvalidPostalCodeMessageId(), + copy.GetInvalidPostalCodeMessageId()); } TEST(RuleTest, ParseOverwritesRule) { @@ -108,8 +116,12 @@ TEST(RuleTest, ParseOverwritesRule) { EXPECT_FALSE(rule.GetPostalCodeFormat().empty()); EXPECT_EQ(IDS_LIBADDRESSINPUT_I18N_AREA, rule.GetAdminAreaNameMessageId()); + EXPECT_EQ(IDS_LIBADDRESSINPUT_I18N_INVALID_AREA, + rule.GetInvalidAdminAreaMessageId()); EXPECT_EQ(IDS_LIBADDRESSINPUT_I18N_POSTAL_CODE_LABEL, rule.GetPostalCodeNameMessageId()); + EXPECT_EQ(IDS_LIBADDRESSINPUT_I18N_INVALID_POSTAL_CODE_LABEL, + rule.GetInvalidPostalCodeMessageId()); ASSERT_TRUE(rule.ParseSerializedRule( "{" @@ -130,8 +142,12 @@ TEST(RuleTest, ParseOverwritesRule) { EXPECT_TRUE(rule.GetPostalCodeFormat().empty()); EXPECT_EQ(IDS_LIBADDRESSINPUT_I18N_DO_SI, rule.GetAdminAreaNameMessageId()); + EXPECT_EQ(IDS_LIBADDRESSINPUT_I18N_INVALID_DO_SI, + rule.GetInvalidAdminAreaMessageId()); EXPECT_EQ(IDS_LIBADDRESSINPUT_I18N_ZIP_CODE_LABEL, rule.GetPostalCodeNameMessageId()); + EXPECT_EQ(IDS_LIBADDRESSINPUT_I18N_INVALID_ZIP_CODE_LABEL, + rule.GetInvalidPostalCodeMessageId()); } TEST(RuleTest, ParseEmptyDataDoesNotOverwriteRule) { @@ -160,8 +176,12 @@ TEST(RuleTest, ParseEmptyDataDoesNotOverwriteRule) { EXPECT_EQ(rule.GetPostalCodeFormat(), copy.GetPostalCodeFormat()); EXPECT_EQ(rule.GetAdminAreaNameMessageId(), copy.GetAdminAreaNameMessageId()); + EXPECT_EQ(rule.GetInvalidAdminAreaMessageId(), + copy.GetInvalidAdminAreaMessageId()); EXPECT_EQ(rule.GetPostalCodeNameMessageId(), copy.GetPostalCodeNameMessageId()); + EXPECT_EQ(rule.GetInvalidPostalCodeMessageId(), + copy.GetInvalidPostalCodeMessageId()); } TEST(RuleTest, ParseFormatWithNewLines) { @@ -288,67 +308,93 @@ TEST(RuleTest, EmptyDictionaryIsValid) { EXPECT_TRUE(rule.ParseSerializedRule("{}")); } +struct LabelData { + LabelData(const std::string& data, int name_id, int error_id) + : data(data), name_id(name_id), error_id(error_id) {} + + ~LabelData() {} + + std::string data; + int name_id; + int error_id; +}; + // Tests for parsing the postal code name. -class PostalCodeNameParseTest - : public testing::TestWithParam<std::pair<std::string, int> > { +class PostalCodeNameParseTest : public testing::TestWithParam<LabelData> { protected: Rule rule_; }; // Verifies that a postal code name is parsed correctly. TEST_P(PostalCodeNameParseTest, ParsedCorrectly) { - ASSERT_TRUE(rule_.ParseSerializedRule(GetParam().first)); - EXPECT_EQ(GetParam().second, rule_.GetPostalCodeNameMessageId()); + ASSERT_TRUE(rule_.ParseSerializedRule(GetParam().data)); + EXPECT_EQ(GetParam().name_id, rule_.GetPostalCodeNameMessageId()); + EXPECT_EQ(GetParam().error_id, rule_.GetInvalidPostalCodeMessageId()); + EXPECT_EQ(GetParam().error_id, rule_.GetInvalidFieldMessageId(POSTAL_CODE)); } // Test parsing all postal code names. INSTANTIATE_TEST_CASE_P( AllPostalCodeNames, PostalCodeNameParseTest, testing::Values( - std::make_pair("{\"zip_name_type\":\"postal\"}", - IDS_LIBADDRESSINPUT_I18N_POSTAL_CODE_LABEL), - std::make_pair("{\"zip_name_type\":\"zip\"}", - IDS_LIBADDRESSINPUT_I18N_ZIP_CODE_LABEL))); + LabelData("{\"zip_name_type\":\"postal\"}", + IDS_LIBADDRESSINPUT_I18N_POSTAL_CODE_LABEL, + IDS_LIBADDRESSINPUT_I18N_INVALID_POSTAL_CODE_LABEL), + LabelData("{\"zip_name_type\":\"zip\"}", + IDS_LIBADDRESSINPUT_I18N_ZIP_CODE_LABEL, + IDS_LIBADDRESSINPUT_I18N_INVALID_ZIP_CODE_LABEL))); // Tests for parsing the administrative area name. -class AdminAreaNameParseTest - : public testing::TestWithParam<std::pair<std::string, int> > { +class AdminAreaNameParseTest : public testing::TestWithParam<LabelData> { protected: Rule rule_; }; // Verifies that an administrative area name is parsed correctly. TEST_P(AdminAreaNameParseTest, ParsedCorrectly) { - ASSERT_TRUE(rule_.ParseSerializedRule(GetParam().first)); - EXPECT_EQ(GetParam().second, rule_.GetAdminAreaNameMessageId()); + ASSERT_TRUE(rule_.ParseSerializedRule(GetParam().data)); + EXPECT_EQ(GetParam().name_id, rule_.GetAdminAreaNameMessageId()); + EXPECT_EQ(GetParam().error_id, rule_.GetInvalidAdminAreaMessageId()); + EXPECT_EQ(GetParam().error_id, rule_.GetInvalidFieldMessageId(ADMIN_AREA)); } // Test parsing all administrative area names. INSTANTIATE_TEST_CASE_P( AllAdminAreaNames, AdminAreaNameParseTest, testing::Values( - std::make_pair("{\"state_name_type\":\"area\"}", - IDS_LIBADDRESSINPUT_I18N_AREA), - std::make_pair("{\"state_name_type\":\"county\"}", - IDS_LIBADDRESSINPUT_I18N_COUNTY_LABEL), - std::make_pair("{\"state_name_type\":\"department\"}", - IDS_LIBADDRESSINPUT_I18N_DEPARTMENT), - std::make_pair("{\"state_name_type\":\"district\"}", - IDS_LIBADDRESSINPUT_I18N_DEPENDENT_LOCALITY_LABEL), - std::make_pair("{\"state_name_type\":\"do_si\"}", - IDS_LIBADDRESSINPUT_I18N_DO_SI), - std::make_pair("{\"state_name_type\":\"emirate\"}", - IDS_LIBADDRESSINPUT_I18N_EMIRATE), - std::make_pair("{\"state_name_type\":\"island\"}", - IDS_LIBADDRESSINPUT_I18N_ISLAND), - std::make_pair("{\"state_name_type\":\"parish\"}", - IDS_LIBADDRESSINPUT_I18N_PARISH), - std::make_pair("{\"state_name_type\":\"prefecture\"}", - IDS_LIBADDRESSINPUT_I18N_PREFECTURE), - std::make_pair("{\"state_name_type\":\"province\"}", - IDS_LIBADDRESSINPUT_I18N_PROVINCE), - std::make_pair("{\"state_name_type\":\"state\"}", - IDS_LIBADDRESSINPUT_I18N_STATE_LABEL))); + LabelData("{\"state_name_type\":\"area\"}", + IDS_LIBADDRESSINPUT_I18N_AREA, + IDS_LIBADDRESSINPUT_I18N_INVALID_AREA), + LabelData("{\"state_name_type\":\"county\"}", + IDS_LIBADDRESSINPUT_I18N_COUNTY_LABEL, + IDS_LIBADDRESSINPUT_I18N_INVALID_COUNTY_LABEL), + LabelData("{\"state_name_type\":\"department\"}", + IDS_LIBADDRESSINPUT_I18N_DEPARTMENT, + IDS_LIBADDRESSINPUT_I18N_INVALID_DEPARTMENT), + LabelData("{\"state_name_type\":\"district\"}", + IDS_LIBADDRESSINPUT_I18N_DEPENDENT_LOCALITY_LABEL, + IDS_LIBADDRESSINPUT_I18N_INVALID_DEPENDENT_LOCALITY_LABEL), + LabelData("{\"state_name_type\":\"do_si\"}", + IDS_LIBADDRESSINPUT_I18N_DO_SI, + IDS_LIBADDRESSINPUT_I18N_INVALID_DO_SI), + LabelData("{\"state_name_type\":\"emirate\"}", + IDS_LIBADDRESSINPUT_I18N_EMIRATE, + IDS_LIBADDRESSINPUT_I18N_INVALID_EMIRATE), + LabelData("{\"state_name_type\":\"island\"}", + IDS_LIBADDRESSINPUT_I18N_ISLAND, + IDS_LIBADDRESSINPUT_I18N_INVALID_ISLAND), + LabelData("{\"state_name_type\":\"parish\"}", + IDS_LIBADDRESSINPUT_I18N_PARISH, + IDS_LIBADDRESSINPUT_I18N_INVALID_PARISH), + LabelData("{\"state_name_type\":\"prefecture\"}", + IDS_LIBADDRESSINPUT_I18N_PREFECTURE, + IDS_LIBADDRESSINPUT_I18N_INVALID_PREFECTURE), + LabelData("{\"state_name_type\":\"province\"}", + IDS_LIBADDRESSINPUT_I18N_PROVINCE, + IDS_LIBADDRESSINPUT_I18N_INVALID_PROVINCE), + LabelData("{\"state_name_type\":\"state\"}", + IDS_LIBADDRESSINPUT_I18N_STATE_LABEL, + IDS_LIBADDRESSINPUT_I18N_INVALID_STATE_LABEL))); // Tests for rule parsing. class RuleParseTest : public testing::TestWithParam<std::string> { diff --git a/third_party/libaddressinput/libaddressinput.gyp b/third_party/libaddressinput/libaddressinput.gyp index d3f94999..ee1c673 100644 --- a/third_party/libaddressinput/libaddressinput.gyp +++ b/third_party/libaddressinput/libaddressinput.gyp @@ -68,6 +68,7 @@ '<(libaddressinput_dir)/cpp/include/libaddressinput/util/internal/scoped_ptr.h', '<(libaddressinput_dir)/cpp/include/libaddressinput/util/internal/template_util.h', '<(libaddressinput_dir)/cpp/include/libaddressinput/util/scoped_ptr.h', + '<(libaddressinput_dir)/cpp/src/address_data.cc', '<(libaddressinput_dir)/cpp/src/address_field.cc', '<(libaddressinput_dir)/cpp/src/address_problem.cc', '<(libaddressinput_dir)/cpp/src/address_ui.cc', |