OLD | NEW |
1 // Copyright (C) 2013 Google Inc. | 1 // Copyright (C) 2013 Google Inc. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 #include <libaddressinput/address_validator.h> | 15 #include <libaddressinput/address_validator.h> |
16 | 16 |
| 17 #include <libaddressinput/address_data.h> |
17 #include <libaddressinput/downloader.h> | 18 #include <libaddressinput/downloader.h> |
18 #include <libaddressinput/load_rules_delegate.h> | 19 #include <libaddressinput/load_rules_delegate.h> |
19 #include <libaddressinput/localization.h> | 20 #include <libaddressinput/localization.h> |
20 #include <libaddressinput/storage.h> | 21 #include <libaddressinput/storage.h> |
21 #include <libaddressinput/util/basictypes.h> | 22 #include <libaddressinput/util/basictypes.h> |
22 #include <libaddressinput/util/scoped_ptr.h> | 23 #include <libaddressinput/util/scoped_ptr.h> |
23 | 24 |
| 25 #include <algorithm> |
24 #include <cassert> | 26 #include <cassert> |
| 27 #include <cstddef> |
25 #include <map> | 28 #include <map> |
26 #include <string> | 29 #include <string> |
27 #include <utility> | 30 #include <utility> |
28 | 31 |
| 32 #include <re2/re2.h> |
| 33 |
29 #include "country_rules_retriever.h" | 34 #include "country_rules_retriever.h" |
| 35 #include "messages.h" |
30 #include "retriever.h" | 36 #include "retriever.h" |
| 37 #include "rule.h" |
31 #include "ruleset.h" | 38 #include "ruleset.h" |
32 #include "util/stl_util.h" | 39 #include "util/stl_util.h" |
33 #include "validating_storage.h" | 40 #include "validating_storage.h" |
34 | 41 |
35 namespace i18n { | 42 namespace i18n { |
36 namespace addressinput { | 43 namespace addressinput { |
37 | 44 |
38 namespace { | 45 namespace { |
39 | 46 |
| 47 // Returns true if the filter is empty (all problems allowed) or contains the |
| 48 // |field|->|problem| mapping (explicitly allowed). |
| 49 bool FilterAllows(const AddressProblemFilter& filter, |
| 50 AddressField field, |
| 51 AddressProblem::Type problem) { |
| 52 if (filter.empty()) { |
| 53 return true; |
| 54 } |
| 55 |
| 56 for (AddressProblemFilter::const_iterator it = filter.begin(); |
| 57 it != filter.end(); ++it) { |
| 58 if (it->first == field && it->second == problem) { |
| 59 return true; |
| 60 } |
| 61 } |
| 62 |
| 63 return false; |
| 64 } |
| 65 |
40 // Validates AddressData structure. | 66 // Validates AddressData structure. |
41 class AddressValidatorImpl : public AddressValidator { | 67 class AddressValidatorImpl : public AddressValidator { |
42 public: | 68 public: |
43 // Takes ownership of |downloader| and |storage|. Does not take ownership of | 69 // Takes ownership of |downloader| and |storage|. Does not take ownership of |
44 // |load_rules_delegate|. | 70 // |load_rules_delegate|. |
45 AddressValidatorImpl(scoped_ptr<const Downloader> downloader, | 71 AddressValidatorImpl(scoped_ptr<const Downloader> downloader, |
46 scoped_ptr<Storage> storage, | 72 scoped_ptr<Storage> storage, |
47 LoadRulesDelegate* load_rules_delegate) | 73 LoadRulesDelegate* load_rules_delegate) |
48 : retriever_(scoped_ptr<Retriever>(new Retriever( | 74 : retriever_(scoped_ptr<Retriever>(new Retriever( |
49 VALIDATION_DATA_URL, | 75 VALIDATION_DATA_URL, |
(...skipping 19 matching lines...) Expand all Loading... |
69 BuildScopedPtrCallback(this, &AddressValidatorImpl::OnRulesLoaded)); | 95 BuildScopedPtrCallback(this, &AddressValidatorImpl::OnRulesLoaded)); |
70 } | 96 } |
71 } | 97 } |
72 | 98 |
73 // AddressValidator implementation. | 99 // AddressValidator implementation. |
74 virtual Status ValidateAddress( | 100 virtual Status ValidateAddress( |
75 const AddressData& address, | 101 const AddressData& address, |
76 const AddressProblemFilter& filter, | 102 const AddressProblemFilter& filter, |
77 const Localization& localization, | 103 const Localization& localization, |
78 AddressProblems* problems) const { | 104 AddressProblems* problems) const { |
79 return RULES_UNAVAILABLE; | 105 std::map<std::string, Status>::const_iterator status_it = |
| 106 status_.find(address.country_code); |
| 107 if (status_it == status_.end()) { |
| 108 return RULES_UNAVAILABLE; |
| 109 } else if (status_it->second == RULES_NOT_READY) { |
| 110 return RULES_NOT_READY; |
| 111 } |
| 112 |
| 113 std::map<std::string, Ruleset*>::const_iterator ruleset_it = |
| 114 rules_.find(address.country_code); |
| 115 assert(ruleset_it != rules_.end()); |
| 116 Ruleset* ruleset = ruleset_it->second; |
| 117 assert(ruleset != NULL); |
| 118 |
| 119 std::map<AddressField, const Rule*> rules = |
| 120 ruleset->BuildRulesForAddress(address); |
| 121 const Rule& country_rule = *rules[COUNTRY]; |
| 122 |
| 123 // Validate required fields. |
| 124 for (std::vector<AddressField>::const_iterator |
| 125 field_it = country_rule.GetRequired().begin(); |
| 126 field_it != country_rule.GetRequired().end(); |
| 127 ++field_it) { |
| 128 if (address.GetField(*field_it).empty() && |
| 129 FilterAllows( |
| 130 filter, *field_it, AddressProblem::MISSING_REQUIRED_FIELD)) { |
| 131 problems->push_back(AddressProblem( |
| 132 *field_it, |
| 133 AddressProblem::MISSING_REQUIRED_FIELD, |
| 134 localization.GetString( |
| 135 IDS_LIBADDRESSINPUT_I18N_MISSING_REQUIRED_FIELD))); |
| 136 } |
| 137 } |
| 138 |
| 139 // Validate general postal code format. A country-level rule specifies the |
| 140 // regular expression for the whole postal code. |
| 141 if (!address.postal_code.empty() && |
| 142 !country_rule.GetPostalCodeFormat().empty() && |
| 143 FilterAllows(filter, |
| 144 POSTAL_CODE, |
| 145 AddressProblem::UNRECOGNIZED_FORMAT) && |
| 146 !RE2::FullMatch( |
| 147 address.postal_code, country_rule.GetPostalCodeFormat())) { |
| 148 problems->push_back(AddressProblem( |
| 149 POSTAL_CODE, |
| 150 AddressProblem::UNRECOGNIZED_FORMAT, |
| 151 localization.GetString( |
| 152 country_rule.GetInvalidPostalCodeMessageId()))); |
| 153 } |
| 154 |
| 155 for (std::map<AddressField, const Rule*>::const_iterator |
| 156 rule_it = rules.begin(); |
| 157 rule_it != rules.end(); |
| 158 ++rule_it) { |
| 159 AddressField field_type = rule_it->first; |
| 160 const Rule* rule = rule_it->second; |
| 161 assert(rule != NULL); |
| 162 |
| 163 // Validate the field values, e.g. state names in US. |
| 164 AddressField sub_field_type = static_cast<AddressField>(field_type + 1); |
| 165 const std::string& sub_field = address.GetField(sub_field_type); |
| 166 const std::vector<std::string>& sub_keys = rule->GetSubKeys(); |
| 167 if (!sub_field.empty() && |
| 168 !sub_keys.empty() && |
| 169 FilterAllows(filter, sub_field_type, AddressProblem::UNKNOWN_VALUE) && |
| 170 std::find(sub_keys.begin(), sub_keys.end(), sub_field) == |
| 171 sub_keys.end()) { |
| 172 problems->push_back(AddressProblem( |
| 173 sub_field_type, |
| 174 AddressProblem::UNKNOWN_VALUE, |
| 175 localization.GetString( |
| 176 country_rule.GetInvalidFieldMessageId(sub_field_type)))); |
| 177 } |
| 178 |
| 179 // Validate sub-region specific postal code format. A sub-region specifies |
| 180 // the regular expression for a prefix of the postal code. |
| 181 int match_position = -1; |
| 182 if (field_type > COUNTRY && |
| 183 !address.postal_code.empty() && |
| 184 !rule->GetPostalCodeFormat().empty() && |
| 185 FilterAllows(filter, |
| 186 POSTAL_CODE, |
| 187 AddressProblem::MISMATCHING_VALUE) && |
| 188 (!RE2::PartialMatch(address.postal_code, |
| 189 rule->GetPostalCodeFormat(), |
| 190 &match_position) || |
| 191 match_position != 0)) { |
| 192 problems->push_back(AddressProblem( |
| 193 POSTAL_CODE, |
| 194 AddressProblem::MISMATCHING_VALUE, |
| 195 localization.GetString( |
| 196 country_rule.GetInvalidPostalCodeMessageId()))); |
| 197 } |
| 198 } |
| 199 |
| 200 return SUCCESS; |
80 } | 201 } |
81 | 202 |
82 private: | 203 private: |
83 // Called when CountryRulesRetriever::RetrieveRules finishes loading all rules | 204 // Called when CountryRulesRetriever::RetrieveRules finishes loading all rules |
84 // for the |country_code|. | 205 // for the |country_code|. |
85 void OnRulesLoaded(bool success, | 206 void OnRulesLoaded(bool success, |
86 const std::string& country_code, | 207 const std::string& country_code, |
87 scoped_ptr<Ruleset> ruleset) { | 208 scoped_ptr<Ruleset> ruleset) { |
88 assert(rules_.find(country_code) == rules_.end()); | 209 assert(rules_.find(country_code) == rules_.end()); |
89 if (success) { | 210 if (success) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 scoped_ptr<AddressValidator> AddressValidator::Build( | 243 scoped_ptr<AddressValidator> AddressValidator::Build( |
123 scoped_ptr<const Downloader> downloader, | 244 scoped_ptr<const Downloader> downloader, |
124 scoped_ptr<Storage> storage, | 245 scoped_ptr<Storage> storage, |
125 LoadRulesDelegate* load_rules_delegate) { | 246 LoadRulesDelegate* load_rules_delegate) { |
126 return scoped_ptr<AddressValidator>(new AddressValidatorImpl( | 247 return scoped_ptr<AddressValidator>(new AddressValidatorImpl( |
127 downloader.Pass(), storage.Pass(), load_rules_delegate)); | 248 downloader.Pass(), storage.Pass(), load_rules_delegate)); |
128 } | 249 } |
129 | 250 |
130 } // namespace addressinput | 251 } // namespace addressinput |
131 } // namespace i18n | 252 } // namespace i18n |
OLD | NEW |