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

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: Fix windows build. 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 CountryRulesRetriever::~CountryRulesRetriever() {}
84
85 void CountryRulesRetriever::RetrieveRules(const std::string& country_code,
86 scoped_ptr<Callback> rules_ready) {
87 Reset();
88 country_code_ = country_code;
89 rules_ready_.reset(rules_ready.release());
90
91 // Key construction:
92 // https://code.google.com/p/libaddressinput/wiki/AddressValidationMetadata
93 // Example of a country-level key: "data/CA".
94 std::string key = "data/" + country_code_;
95 requests_.insert(std::make_pair(
96 key, RequestData(NULL, COUNTRY, false, std::string())));
97
98 retriever_->Retrieve(
99 key, BuildCallback(this, &CountryRulesRetriever::OnDataReady));
100 }
101
102 void CountryRulesRetriever::OnDataReady(bool success,
103 const std::string& key,
104 const std::string& data) {
105 std::map<std::string, RequestData>::iterator request_it =
106 requests_.find(key);
107 if (request_it == requests_.end()) {
108 return; // An abandoned request.
109 }
110
111 RequestData request = request_it->second;
112 requests_.erase(request_it);
113
114 success_ &= success;
Evan Stade 2014/01/08 01:22:46 it seems that if success is false, we should aband
please use gerrit instead 2014/01/08 02:04:40 Done.
115
116 // All country-level rules are based on the default rule.
117 scoped_ptr<Rule> rule(new Rule);
118 if (request.level == COUNTRY) {
119 rule->CopyFrom(Rule::GetDefault());
120 }
121
122 success_ &= rule->ParseSerializedRule(data);
123
124 // Place the rule in the correct location in the ruleset.
125 Ruleset* ruleset = NULL;
126 if (request.is_language_code) {
127 assert(request.parent != NULL);
128 request.parent->AddLanguageCode(request.id, rule.Pass());
129 ruleset = request.parent;
130 } else if (request.level == COUNTRY) {
131 // The default language and all supported languages for the country code are
132 // in the country-level rule without a language code identifier. For
133 // example: "data/CA".
134 default_language_ = rule->GetLanguage();
135 languages_ = rule->GetLanguages();
136
137 root_.reset(new Ruleset(rule.Pass()));
138 ruleset = root_.get();
139 } else {
140 assert(request.parent != NULL);
141 ruleset = request.parent->AddSubRegion(request.id, rule.Pass());
142 }
143
144 if (!request.is_language_code) {
145 // Retrieve the language-specific rules for this region.
146 for (std::vector<std::string>::const_iterator
147 lang_it = languages_.begin();
148 lang_it != languages_.end();
149 ++lang_it) {
150 if (*lang_it == default_language_) {
151 continue;
152 }
153 // Example of a language-specific key: "data/CA--fr".
154 std::string language_code_key = key + "--" + *lang_it;
155 requests_.insert(std::make_pair(
156 key, RequestData(ruleset, request.level, true, *lang_it)));
157 retriever_->Retrieve(
158 language_code_key,
159 BuildCallback(this, &CountryRulesRetriever::OnDataReady));
160 }
161
162 if (request.level < DEPENDENT_LOCALITY) {
163 // Retrieve the sub-region rules for this region.
164 for (std::vector<std::string>::const_iterator
165 subkey_it = ruleset->rule().GetSubKeys().begin();
166 subkey_it != ruleset->rule().GetSubKeys().end();
167 ++subkey_it) {
168 // Example of a sub-region key: "data/CA/AB".
169 std::string sub_region_key = key + "/" + *subkey_it;
170 requests_.insert(std::make_pair(
171 key,
172 RequestData(ruleset,
173 static_cast<AddressField>(request.level + 1),
174 false,
175 *subkey_it)));
176 retriever_->Retrieve(
177 sub_region_key,
178 BuildCallback(this, &CountryRulesRetriever::OnDataReady));
179 }
180 }
181 }
182
183 if (requests_.empty()) {
184 (*rules_ready_)(success_, country_code_, root_.Pass());
185 Reset();
186 }
187 }
188
189 void CountryRulesRetriever::Reset() {
190 requests_.clear();
191 country_code_.clear();
192 rules_ready_.reset();
193 root_.reset();
194 success_ = true;
Evan Stade 2014/01/08 01:22:46 this is surprising.
please use gerrit instead 2014/01/08 02:04:40 Changed the variable description to "False if at l
195 default_language_.clear();
196 languages_.clear();
197 }
198
199 } // namespace addressinput
200 } // namespace i18n
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698