#include "country_rules_aggregator.h"
#include "grit/libaddressinput_strings.h"
+#include "region_data_constants.h"
#include "retriever.h"
#include "rule.h"
#include "ruleset.h"
AddressProblems* problems) const {
std::map<std::string, const Ruleset*>::const_iterator ruleset_it =
rules_.find(address.country_code);
+
+ // We can still validate the required fields even if the full ruleset isn't
+ // ready.
if (ruleset_it == rules_.end()) {
+ if (problems != NULL) {
+ Rule rule;
+ rule.CopyFrom(Rule::GetDefault());
+ if (rule.ParseSerializedRule(
+ RegionDataConstants::GetRegionData(address.country_code))) {
+ EnforceRequiredFields(rule, address, filter, problems);
+ }
+ }
+
return loading_rules_.find(address.country_code) != loading_rules_.end()
? RULES_NOT_READY
: RULES_UNAVAILABLE;
}
+ if (problems == NULL)
+ return SUCCESS;
+
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) {
- bool field_empty = *field_it != STREET_ADDRESS
- ? address.GetFieldValue(*field_it).empty()
- : IsEmptyStreetAddress(address.address_lines);
- if (field_empty &&
- FilterAllows(
- filter, *field_it, AddressProblem::MISSING_REQUIRED_FIELD)) {
- problems->push_back(AddressProblem(
- *field_it,
- AddressProblem::MISSING_REQUIRED_FIELD,
- IDS_LIBADDRESSINPUT_I18N_MISSING_REQUIRED_FIELD));
- }
- }
+ EnforceRequiredFields(country_rule, address, filter, problems);
// Validate general postal code format. A country-level rule specifies the
// regular expression for the whole postal 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.GetFieldValue(sub_field_type);
- const std::vector<std::string>& sub_keys = rule.GetSubKeys();
- if (!sub_field.empty() &&
- !sub_keys.empty() &&
+ std::string sub_key;
+ const std::string& user_input = address.GetFieldValue(sub_field_type);
+ if (!user_input.empty() &&
FilterAllows(filter, sub_field_type, AddressProblem::UNKNOWN_VALUE) &&
- std::find(sub_keys.begin(), sub_keys.end(), sub_field) ==
- sub_keys.end()) {
+ !rule.CanonicalizeSubKey(user_input, &sub_key)) {
problems->push_back(AddressProblem(
sub_field_type,
AddressProblem::UNKNOWN_VALUE,
// 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)) {
+ !RE2::FullMatch(address.postal_code,
+ "^(" + rule.GetPostalCodeFormat() + ").*")) {
problems->push_back(AddressProblem(
POSTAL_CODE,
AddressProblem::MISMATCHING_VALUE,
country_rule.GetInvalidPostalCodeMessageId()));
}
- ruleset = ruleset->GetSubRegionRuleset(sub_field);
+ ruleset = ruleset->GetSubRegionRuleset(sub_key);
}
return SUCCESS;
}
+ virtual bool CanonicalizeAdministrativeArea(AddressData* address_data) const {
+ std::map<std::string, const Ruleset*>::const_iterator ruleset_it =
+ rules_.find(address_data->country_code);
+ if (ruleset_it == rules_.end()) {
+ return false;
+ }
+ const Rule& rule =
+ ruleset_it->second->GetLanguageCodeRule(address_data->language_code);
+
+ return rule.CanonicalizeSubKey(address_data->administrative_area,
+ &address_data->administrative_area);
+ }
+
private:
// Called when CountryRulesAggregator::AggregateRules loads the |ruleset| for
// the |country_code|.
}
}
+ // Adds problems for just the required fields portion of |country_rule|.
+ void EnforceRequiredFields(const Rule& country_rule,
+ const AddressData& address,
+ const AddressProblemFilter& filter,
+ AddressProblems* problems) const {
+ assert(problems != NULL);
+ for (std::vector<AddressField>::const_iterator
+ field_it = country_rule.GetRequired().begin();
+ field_it != country_rule.GetRequired().end();
+ ++field_it) {
+ bool field_empty = *field_it != STREET_ADDRESS
+ ? address.GetFieldValue(*field_it).empty()
+ : IsEmptyStreetAddress(address.address_lines);
+ if (field_empty &&
+ FilterAllows(
+ filter, *field_it, AddressProblem::MISSING_REQUIRED_FIELD)) {
+ problems->push_back(AddressProblem(
+ *field_it,
+ AddressProblem::MISSING_REQUIRED_FIELD,
+ IDS_LIBADDRESSINPUT_I18N_MISSING_REQUIRED_FIELD));
+ }
+ }
+ }
+
// Loads the ruleset for a country code.
CountryRulesAggregator aggregator_;