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

Side by Side Diff: third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.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: Address data 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_aggregator.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 CountryRulesAggregator::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 assert(parent != NULL || level == COUNTRY);
50 }
51
52 ~RequestData() {}
53
54 // The parent ruleset of the data being downloaded. If NULL, then this is the
55 // root ruleset at the COUNTRY level. The language-specific and sub-region
56 // rules are added to this ruleset. Owned by |CountryRulesRetriever|.
57 Ruleset* parent;
58
59 // The level of the data being requested. Ranges from COUNTRY to
60 // DEPENDENT_LOCALITY. If COUNTRY, then the rule should use default rules from
61 // Rule::GetDefault().
62 AddressField level;
63
64 // If true, then |id| is a language. The data received for this request should
65 // be placed into a language-specific rule.
66 bool is_language_code;
67
68 // Can be a region name (e.g. "CA") or a language (e.g. "fr"). Used to add a
69 // sub-region or a language-specific rule to |parent|.
70 std::string id;
71 };
72
73 CountryRulesAggregator::CountryRulesAggregator(scoped_ptr<Retriever> retriever)
74 : retriever_(retriever.Pass()),
75 requests_(),
76 country_code_(),
77 rules_ready_(),
78 root_(),
79 default_language_(),
80 languages_() {
81 assert(retriever_ != NULL);
82 }
83
84 CountryRulesAggregator::~CountryRulesAggregator() {}
85
86 void CountryRulesAggregator::AggregateRules(const std::string& country_code,
87 scoped_ptr<Callback> rules_ready) {
88 Reset();
89 country_code_ = country_code;
90 rules_ready_.reset(rules_ready.release());
91
92 // Key construction:
93 // https://code.google.com/p/libaddressinput/wiki/AddressValidationMetadata
94 // Example of a country-level key: "data/CA".
95 std::string key = "data/" + country_code_;
96 requests_.insert(std::make_pair(
97 key, RequestData(NULL, COUNTRY, false, std::string())));
98
99 retriever_->Retrieve(
100 key, BuildCallback(this, &CountryRulesAggregator::OnDataReady));
101 }
102
103 void CountryRulesAggregator::OnDataReady(bool success,
104 const std::string& key,
105 const std::string& data) {
106 std::map<std::string, RequestData>::iterator request_it =
107 requests_.find(key);
108 if (request_it == requests_.end()) {
109 return; // An abandoned request.
110 }
111
112 if (!success) {
113 (*rules_ready_)(false, country_code_, scoped_ptr<Ruleset>());
114 Reset();
115 return;
116 }
117
118 RequestData request = request_it->second;
119 requests_.erase(request_it);
120
121 // All country-level rules are based on the default rule.
122 scoped_ptr<Rule> rule(new Rule);
123 if (request.level == COUNTRY) {
124 rule->CopyFrom(Rule::GetDefault());
125 }
126
127 if (!rule->ParseSerializedRule(data)) {
128 (*rules_ready_)(false, country_code_, scoped_ptr<Ruleset>());
129 Reset();
130 return;
131 }
132
133 // Place the rule in the correct location in the ruleset.
134 Ruleset* ruleset = NULL;
135 if (request.is_language_code) {
136 assert(request.parent != NULL);
137 request.parent->AddLanguageCodeRule(request.id, rule.Pass());
138 ruleset = request.parent;
139 } else if (request.level == COUNTRY) {
140 // The default language and all supported languages for the country code are
141 // in the country-level rule without a language code identifier. For
142 // example: "data/CA".
143 default_language_ = rule->GetLanguage();
144 languages_ = rule->GetLanguages();
145
146 root_.reset(new Ruleset(rule.Pass()));
147 ruleset = root_.get();
148 } else {
149 assert(request.parent != NULL);
150 ruleset = request.parent->AddSubRegionRuleset(request.id, rule.Pass());
151 }
152
153 if (!request.is_language_code) {
154 // Retrieve the language-specific rules for this region.
155 for (std::vector<std::string>::const_iterator
156 lang_it = languages_.begin();
157 lang_it != languages_.end();
158 ++lang_it) {
159 if (*lang_it == default_language_) {
160 continue;
161 }
162 // Example of a language-specific key: "data/CA--fr".
163 std::string language_code_key = key + "--" + *lang_it;
164 requests_.insert(std::make_pair(
165 key, RequestData(ruleset, request.level, true, *lang_it)));
166 retriever_->Retrieve(
167 language_code_key,
168 BuildCallback(this, &CountryRulesAggregator::OnDataReady));
169 }
170
171 if (request.level < DEPENDENT_LOCALITY) {
172 // Retrieve the sub-region rules for this region.
173 for (std::vector<std::string>::const_iterator
174 subkey_it = ruleset->rule().GetSubKeys().begin();
175 subkey_it != ruleset->rule().GetSubKeys().end();
176 ++subkey_it) {
177 // Example of a sub-region key: "data/CA/AB".
178 std::string sub_region_key = key + "/" + *subkey_it;
179 requests_.insert(std::make_pair(
180 key,
181 RequestData(ruleset,
182 static_cast<AddressField>(request.level + 1),
183 false,
184 *subkey_it)));
185 retriever_->Retrieve(
186 sub_region_key,
187 BuildCallback(this, &CountryRulesAggregator::OnDataReady));
188 }
189 }
190 }
191
192 if (requests_.empty()) {
193 (*rules_ready_)(true, country_code_, root_.Pass());
194 Reset();
195 }
196 }
197
198 void CountryRulesAggregator::Reset() {
199 requests_.clear();
200 country_code_.clear();
201 rules_ready_.reset();
202 root_.reset();
203 default_language_.clear();
204 languages_.clear();
205 }
206
207 } // namespace addressinput
208 } // namespace i18n
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698