1bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// Copyright (C) 2014 Google Inc. 2bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// 3bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// Licensed under the Apache License, Version 2.0 (the "License"); 4bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// you may not use this file except in compliance with the License. 5bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// You may obtain a copy of the License at 6bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// 7bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// http://www.apache.org/licenses/LICENSE-2.0 8bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// 9bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// Unless required by applicable law or agreed to in writing, software 10bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// distributed under the License is distributed on an "AS IS" BASIS, 11bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// See the License for the specific language governing permissions and 13bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// limitations under the License. 14bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 15bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include "validation_task.h" 16bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 17bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include <libaddressinput/address_data.h> 18bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include <libaddressinput/address_field.h> 19b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com#include <libaddressinput/address_metadata.h> 20bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include <libaddressinput/address_problem.h> 21bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include <libaddressinput/address_validator.h> 229f47fe3ed525accac995b095d408a825673a2ee1roubert@google.com#include <libaddressinput/callback.h> 239693f6426f3500db74dcfc766a130a747a571e5eroubert@google.com#include <libaddressinput/supplier.h> 24bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include <libaddressinput/util/basictypes.h> 25bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 26bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include <algorithm> 27bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include <cassert> 28bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include <cstddef> 29bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include <string> 30bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include <utility> 31bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include <vector> 32bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 339f47fe3ed525accac995b095d408a825673a2ee1roubert@google.com#include <re2/re2.h> 349f47fe3ed525accac995b095d408a825673a2ee1roubert@google.com 35bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include "lookup_key.h" 36bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include "post_box_matchers.h" 37bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com#include "rule.h" 38ea5e77397b59d94af3591644c3dc23dc6f9ba22eroubert@google.com#include "util/re2ptr.h" 39ea5e77397b59d94af3591644c3dc23dc6f9ba22eroubert@google.com 40bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comnamespace i18n { 41bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comnamespace addressinput { 42bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 43bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comValidationTask::ValidationTask(const AddressData& address, 44bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com bool allow_postal, 45bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com bool require_name, 46bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com const FieldProblemMap* filter, 47bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com FieldProblemMap* problems, 48bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com const AddressValidator::Callback& validated) 49bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com : address_(address), 50bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com allow_postal_(allow_postal), 51bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com require_name_(require_name), 52bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com filter_(filter), 53bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com problems_(problems), 54bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com validated_(validated), 559693f6426f3500db74dcfc766a130a747a571e5eroubert@google.com supplied_(BuildCallback(this, &ValidationTask::Validate)), 56bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com lookup_key_(new LookupKey) { 57bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com assert(problems_ != NULL); 589693f6426f3500db74dcfc766a130a747a571e5eroubert@google.com assert(supplied_ != NULL); 59bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com assert(lookup_key_ != NULL); 60bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 61bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 62bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comValidationTask::~ValidationTask() { 63bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 64bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 659693f6426f3500db74dcfc766a130a747a571e5eroubert@google.comvoid ValidationTask::Run(Supplier* supplier) const { 669693f6426f3500db74dcfc766a130a747a571e5eroubert@google.com assert(supplier != NULL); 67bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com problems_->clear(); 68bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com lookup_key_->FromAddress(address_); 699693f6426f3500db74dcfc766a130a747a571e5eroubert@google.com supplier->Supply(*lookup_key_, *supplied_); 70bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 71bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 72bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comvoid ValidationTask::Validate(bool success, 73bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com const LookupKey& lookup_key, 749693f6426f3500db74dcfc766a130a747a571e5eroubert@google.com const Supplier::RuleHierarchy& hierarchy) { 75bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com assert(&lookup_key == lookup_key_.get()); // Sanity check. 76bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 77bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (success) { 78bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (address_.IsFieldEmpty(COUNTRY)) { 79bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ReportProblemMaybe(COUNTRY, MISSING_REQUIRED_FIELD); 8017471f7b69a94f92480650b06721e698204be3c0roubert@google.com } else if (hierarchy.rule[0] == NULL) { 81bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ReportProblemMaybe(COUNTRY, UNKNOWN_VALUE); 82bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } else { 83b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com // Checks which use statically linked metadata. 84b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com const std::string& region_code = address_.region_code; 85b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com CheckUnexpectedField(region_code); 86b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com CheckMissingRequiredField(region_code); 87b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com 88b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com // Checks which use data from the metadata server. Note that 89b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com // CheckPostalCodeFormatAndValue assumes CheckUnexpectedField has already 90b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com // been called. 91bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com CheckUnknownValue(hierarchy); 92bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com CheckPostalCodeFormatAndValue(hierarchy); 93bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com CheckUsesPoBox(hierarchy); 94bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 95bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 96bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 97bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com validated_(success, address_, *problems_); 98bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com delete this; 99bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 100bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 101b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com// A field will return an UNEXPECTED_FIELD problem type if the current value of 102b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com// that field is not empty and the field should not be used by that region. 103bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comvoid ValidationTask::CheckUnexpectedField( 104b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com const std::string& region_code) const { 105bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com static const AddressField kFields[] = { 106bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com // COUNTRY is never unexpected. 107bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ADMIN_AREA, 108bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com LOCALITY, 109bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com DEPENDENT_LOCALITY, 110bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com SORTING_CODE, 111bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com POSTAL_CODE, 112bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com STREET_ADDRESS, 113b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org ORGANIZATION, 114bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com RECIPIENT 115bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com }; 116bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 117bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com for (size_t i = 0; i < arraysize(kFields); ++i) { 118bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com AddressField field = kFields[i]; 119b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com if (!address_.IsFieldEmpty(field) && !IsFieldUsed(field, region_code)) { 120bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ReportProblemMaybe(field, UNEXPECTED_FIELD); 121bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 122bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 123bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 124bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 125b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com// A field will return an MISSING_REQUIRED_FIELD problem type if the current 126b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com// value of that field is empty and the field is required by that region. 127bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comvoid ValidationTask::CheckMissingRequiredField( 128b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com const std::string& region_code) const { 129b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com static const AddressField kFields[] = { 130b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com // COUNTRY is assumed to have already been checked. 131b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com ADMIN_AREA, 132b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com LOCALITY, 133b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com DEPENDENT_LOCALITY, 134b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com SORTING_CODE, 135b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com POSTAL_CODE, 136b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org STREET_ADDRESS 137b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org // ORGANIZATION is never required. 138b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com // RECIPIENT is handled separately. 139b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com }; 140bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 141b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com for (size_t i = 0; i < arraysize(kFields); ++i) { 142b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com AddressField field = kFields[i]; 143b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com if (address_.IsFieldEmpty(field) && IsFieldRequired(field, region_code)) { 144b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com ReportProblemMaybe(field, MISSING_REQUIRED_FIELD); 145bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 146bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 147bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 148bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (require_name_ && address_.IsFieldEmpty(RECIPIENT)) { 149bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ReportProblemMaybe(RECIPIENT, MISSING_REQUIRED_FIELD); 150bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 151bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 152bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 153bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// A field is UNKNOWN_VALUE if the metadata contains a list of possible values 154bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// for the field and the address data server could not match the current value 155bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com// of that field to one of those possible values, therefore returning NULL. 156bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comvoid ValidationTask::CheckUnknownValue( 1579693f6426f3500db74dcfc766a130a747a571e5eroubert@google.com const Supplier::RuleHierarchy& hierarchy) const { 158bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com for (size_t depth = 1; depth < arraysize(LookupKey::kHierarchy); ++depth) { 159bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com AddressField field = LookupKey::kHierarchy[depth]; 160bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (!(address_.IsFieldEmpty(field) || 16117471f7b69a94f92480650b06721e698204be3c0roubert@google.com hierarchy.rule[depth - 1] == NULL || 16217471f7b69a94f92480650b06721e698204be3c0roubert@google.com hierarchy.rule[depth - 1]->GetSubKeys().empty() || 16317471f7b69a94f92480650b06721e698204be3c0roubert@google.com hierarchy.rule[depth] != NULL)) { 164bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ReportProblemMaybe(field, UNKNOWN_VALUE); 165bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 166bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 167bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 168bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 169b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com// Note that it is assumed that CheckUnexpectedField has already been called. 170bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comvoid ValidationTask::CheckPostalCodeFormatAndValue( 1719693f6426f3500db74dcfc766a130a747a571e5eroubert@google.com const Supplier::RuleHierarchy& hierarchy) const { 17217471f7b69a94f92480650b06721e698204be3c0roubert@google.com assert(hierarchy.rule[0] != NULL); 17317471f7b69a94f92480650b06721e698204be3c0roubert@google.com const Rule& country_rule = *hierarchy.rule[0]; 174bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 175bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (!(ShouldReport(POSTAL_CODE, INVALID_FORMAT) || 176bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ShouldReport(POSTAL_CODE, MISMATCHING_VALUE))) { 177bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com return; 178bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 179bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 180bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (address_.IsFieldEmpty(POSTAL_CODE)) { 181bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com return; 182b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com } else if (std::find(problems_->begin(), problems_->end(), 183b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com FieldProblemMap::value_type(POSTAL_CODE, 184b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com UNEXPECTED_FIELD)) 185b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com != problems_->end()) { 186b1b5b1fcaaaa95129f1f351641dd20d14bc667e3roubert@google.com return; // Problem already reported. 187bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 188bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 189bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com // Validate general postal code format. A country-level rule specifies the 190bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com // regular expression for the whole postal code. 191bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com const RE2ptr* format_ptr = country_rule.GetPostalCodeMatcher(); 192bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (format_ptr != NULL && 193bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com !RE2::FullMatch(address_.postal_code, *format_ptr->ptr) && 194bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ShouldReport(POSTAL_CODE, INVALID_FORMAT)) { 195bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ReportProblem(POSTAL_CODE, INVALID_FORMAT); 196bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com return; 197bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 198bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 199bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (!ShouldReport(POSTAL_CODE, MISMATCHING_VALUE)) { 200bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com return; 201bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 202bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 203bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com for (size_t depth = arraysize(LookupKey::kHierarchy) - 1; 204bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com depth > 0; --depth) { 20517471f7b69a94f92480650b06721e698204be3c0roubert@google.com if (hierarchy.rule[depth] != NULL) { 206bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com // Validate sub-region specific postal code format. A sub-region specifies 207bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com // the regular expression for a prefix of the postal code. 20817471f7b69a94f92480650b06721e698204be3c0roubert@google.com const RE2ptr* prefix_ptr = hierarchy.rule[depth]->GetPostalCodeMatcher(); 209bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (prefix_ptr != NULL) { 210bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (!RE2::PartialMatch(address_.postal_code, *prefix_ptr->ptr)) { 211bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ReportProblem(POSTAL_CODE, MISMATCHING_VALUE); 212bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 213bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com return; 214bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 215bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 216bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 217bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 218bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 219bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comvoid ValidationTask::CheckUsesPoBox( 2209693f6426f3500db74dcfc766a130a747a571e5eroubert@google.com const Supplier::RuleHierarchy& hierarchy) const { 22117471f7b69a94f92480650b06721e698204be3c0roubert@google.com assert(hierarchy.rule[0] != NULL); 22217471f7b69a94f92480650b06721e698204be3c0roubert@google.com const Rule& country_rule = *hierarchy.rule[0]; 223bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 224bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (allow_postal_ || 225bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com !ShouldReport(STREET_ADDRESS, USES_P_O_BOX) || 226bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com address_.IsFieldEmpty(STREET_ADDRESS)) { 227bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com return; 228bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 229bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 230bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com std::vector<const RE2ptr*> matchers = 231bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com PostBoxMatchers::GetMatchers(country_rule); 232bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com for (std::vector<std::string>::const_iterator 233bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com line = address_.address_line.begin(); 234bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com line != address_.address_line.end(); ++line) { 235bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com for (std::vector<const RE2ptr*>::const_iterator 236bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com matcher = matchers.begin(); 237bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com matcher != matchers.end(); ++matcher) { 238bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (RE2::PartialMatch(*line, *(*matcher)->ptr)) { 239bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ReportProblem(STREET_ADDRESS, USES_P_O_BOX); 240bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com return; 241bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 242bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 243bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 244bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 245bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 246bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comvoid ValidationTask::ReportProblem(AddressField field, 247bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com AddressProblem problem) const { 248bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com problems_->insert(std::make_pair(field, problem)); 249bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 250bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 251bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.comvoid ValidationTask::ReportProblemMaybe(AddressField field, 252bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com AddressProblem problem) const { 253bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com if (ShouldReport(field, problem)) { 254bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com ReportProblem(field, problem); 255bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com } 256bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 257bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 258bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.combool ValidationTask::ShouldReport(AddressField field, 259bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com AddressProblem problem) const { 260bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com return filter_ == NULL || filter_->empty() || 261000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com std::find(filter_->begin(), 262000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com filter_->end(), 263bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com FieldProblemMap::value_type(field, problem)) != 264000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com filter_->end(); 265bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} 266bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com 267bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} // namespace addressinput 268bb96489d0f6066c96a5388a2a91d30ca6bc87ba8roubert@google.com} // namespace i18n 269