Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: third_party/libaddressinput/chromium/cpp/src/country_rules_retriever.cc

Issue 109323011: [rac] Download all rules for a country code in libaddressinput. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Abandon in-progress requests upon new requests. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (C) 2014 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "country_rules_retriever.h"
16
17 #include <libaddressinput/address_field.h>
18 #include <libaddressinput/callback.h>
19 #include <libaddressinput/util/basictypes.h>
20 #include <libaddressinput/util/scoped_ptr.h>
21
22 #include <cassert>
23 #include <cstddef>
24 #include <map>
25 #include <string>
26 #include <utility>
27
28 #include "retriever.h"
29 #include "rule.h"
30 #include "ruleset.h"
31 #include "util/stl_util.h"
32
33 namespace i18n {
34 namespace addressinput {
35
36 // Information about data requests sent to Retriever. This data is not returned
37 // as part of the ruleset, but is useful in constructing the ruleset
38 // asynchronously.
39 struct CountryRulesRetriever::RequestData {
40 // Does not take ownership of |parent|.
41 RequestData(Ruleset* parent,
42 AddressField level,
43 bool is_language_code,
44 const std::string& id)
45 : parent(parent),
46 level(level),
47 is_language_code(is_language_code),
48 id(id) {}
49
50 ~RequestData() {}
51
52 // The parent ruleset of the data being downloaded. If NULL, then this is the
53 // root ruleset at the COUNTRY level. The language-specific and sub-region
54 // rules are added to this ruleset. Owned by |CountryRulesRetriever|.
55 Ruleset* parent;
56
57 // The level of the data being requested. Ranges from COUNTRY to
58 // DEPENDENT_LOCALITY. If COUNTRY, then the rule should use default rules from
59 // Rule::GetDefault().
60 AddressField level;
61
62 // If true, then |id| is a language. The data received for this request should
63 // be placed into a language-specific rule.
64 bool is_language_code;
65
66 // Can be a region name (e.g. "CA") or a language (e.g. "fr"). Used to add a
67 // sub-region or a language-specific rule to |parent|.
68 std::string id;
69 };
70
71 CountryRulesRetriever::CountryRulesRetriever(scoped_ptr<Retriever> retriever)
72 : retriever_(retriever.Pass()),
73 requests_(),
74 country_code_(),
75 rules_ready_(),
76 root_(),
77 success_(true),
78 default_language_(),
79 languages_() {
80 assert(retriever_ != NULL);
81 }
82
83 void CountryRulesRetriever::RetrieveRules(const std::string& country_code,
84 scoped_ptr<Callback> rules_ready) {
85 Reset();
86 country_code_ = country_code;
87 rules_ready_.reset(rules_ready.release());
88
89 // Key construction:
90 // https://code.google.com/p/libaddressinput/wiki/AddressValidationMetadata
91 // Example of a country-level key: "data/CA".
92 std::string key = "data/" + country_code_;
93 requests_.insert(std::make_pair(
94 key, RequestData(NULL, COUNTRY, false, std::string())));
95
96 retriever_->Retrieve(
97 key, BuildCallback(this, &CountryRulesRetriever::OnDataReady));
98 }
99
100 void CountryRulesRetriever::OnDataReady(bool success,
101 const std::string& key,
102 const std::string& data) {
103 std::map<std::string, RequestData>::iterator request_it =
104 requests_.find(key);
105 if (request_it == requests_.end()) {
106 return; // An abandoned request.
107 }
108
109 RequestData request = request_it->second;
110 requests_.erase(request_it);
111
112 success_ &= success;
113
114 // All country-level rules are based on the default rule.
115 scoped_ptr<Rule> rule(new Rule);
116 if (request.level == COUNTRY) {
117 rule->CopyFrom(Rule::GetDefault());
118 }
119
120 success_ &= rule->ParseSerializedRule(data);
121
122 // Place the rule in the correct location in the ruleset.
123 Ruleset* ruleset = NULL;
124 if (request.is_language_code) {
125 assert(request.parent != NULL);
126 request.parent->AddLanguageCode(request.id, rule.Pass());
127 ruleset = request.parent;
128 } else if (request.level == COUNTRY) {
129 // The default language and all supported languages for the country code are
130 // in the country-level rule without a language code identifier. For
131 // example: "data/CA".
132 default_language_ = rule->GetLanguage();
133 languages_ = rule->GetLanguages();
134
135 root_.reset(new Ruleset(rule.Pass()));
136 ruleset = root_.get();
137 } else {
138 assert(request.parent != NULL);
139 ruleset = request.parent->AddSubRegion(request.id, rule.Pass());
140 }
141
142 if (!request.is_language_code) {
143 // Retrieve the language-specific rules for this region.
144 for (std::vector<std::string>::const_iterator
145 lang_it = languages_.begin();
146 lang_it != languages_.end();
147 ++lang_it) {
148 if (*lang_it == default_language_) {
149 continue;
150 }
151 // Example of a language-specific key: "data/CA--fr".
152 std::string language_code_key = key + "--" + *lang_it;
153 requests_.insert(std::make_pair(
154 key, RequestData(ruleset, request.level, true, *lang_it)));
155 retriever_->Retrieve(
156 language_code_key,
157 BuildCallback(this, &CountryRulesRetriever::OnDataReady));
158 }
159
160 if (request.level < DEPENDENT_LOCALITY) {
161 // Retrieve the sub-region rules for this region.
162 for (std::vector<std::string>::const_iterator
163 subkey_it = ruleset->rule().GetSubKeys().begin();
164 subkey_it != ruleset->rule().GetSubKeys().end();
165 ++subkey_it) {
166 // Example of a sub-region key: "data/CA/AB".
167 std::string sub_region_key = key + "/" + *subkey_it;
168 requests_.insert(std::make_pair(
169 key,
170 RequestData(ruleset,
171 static_cast<AddressField>(request.level + 1),
172 false,
173 *subkey_it)));
174 retriever_->Retrieve(
175 sub_region_key,
176 BuildCallback(this, &CountryRulesRetriever::OnDataReady));
177 }
178 }
179 }
180
181 if (requests_.empty()) {
182 (*rules_ready_)(success_, country_code_, root_.Pass());
183 Reset();
184 }
185 }
186
187 void CountryRulesRetriever::Reset() {
188 requests_.clear();
189 country_code_.clear();
190 rules_ready_.reset();
191 root_.reset();
192 success_ = true;
193 default_language_.clear();
194 languages_.clear();
195 rules_ready_.reset();
196 default_language_.clear();
197 languages_.clear();
please use gerrit instead 2014/01/07 23:00:42 Err, copy-paste error. Fix incoming.
please use gerrit instead 2014/01/07 23:03:42 Done.
198 }
199
200 } // namespace addressinput
201 } // namespace i18n
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698