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

Unified Diff: third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc

Issue 140823005: [rac] Download country code data in a single HTTP request. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Temporarily switch to staging URL. 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 side-by-side diff with in-line comments
Download patch
Index: third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc
diff --git a/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc b/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc
index e268f86dd3722544f90612b76d3d1a6e6c36e0d8..8135b3be2d7fb463f19b47fe1f38f0b74b500543 100644
--- a/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc
@@ -16,68 +16,29 @@
#include <libaddressinput/address_field.h>
#include <libaddressinput/callback.h>
-#include <libaddressinput/util/basictypes.h>
#include <libaddressinput/util/scoped_ptr.h>
+#include <algorithm>
#include <cassert>
#include <cstddef>
-#include <map>
#include <string>
-#include <utility>
+#include <vector>
#include "retriever.h"
#include "rule.h"
#include "ruleset.h"
-#include "util/stl_util.h"
+#include "util/json.h"
namespace i18n {
namespace addressinput {
-// Information about data requests sent to Retriever. This data is not returned
-// as part of the ruleset, but is useful in constructing the ruleset
-// asynchronously.
-struct CountryRulesAggregator::RequestData {
- // Does not take ownership of |parent|.
- RequestData(Ruleset* parent,
- AddressField level,
- bool is_language_code,
- const std::string& id)
- : parent(parent),
- level(level),
- is_language_code(is_language_code),
- id(id) {
- assert(parent != NULL || level == COUNTRY);
- }
-
- ~RequestData() {}
-
- // The parent ruleset of the data being downloaded. If NULL, then this is the
- // root ruleset at the COUNTRY level. The language-specific and sub-region
- // rules are added to this ruleset. Owned by |CountryRulesRetriever|.
- Ruleset* parent;
-
- // The level of the data being requested. Ranges from COUNTRY to
- // DEPENDENT_LOCALITY. If COUNTRY, then the rule should use default rules from
- // Rule::GetDefault().
- AddressField level;
-
- // If true, then |id| is a language. The data received for this request should
- // be placed into a language-specific rule.
- bool is_language_code;
-
- // Can be a region name (e.g. "CA") or a language (e.g. "fr"). Used to add a
- // sub-region or a language-specific rule to |parent|.
- std::string id;
-};
-
CountryRulesAggregator::CountryRulesAggregator(scoped_ptr<Retriever> retriever)
: retriever_(retriever.Pass()),
- requests_(),
country_code_(),
+ key_(),
rules_ready_(),
- root_(),
- default_language_(),
- languages_() {
+ json_(),
+ non_default_languages_() {
assert(retriever_ != NULL);
}
@@ -92,118 +53,101 @@ void CountryRulesAggregator::AggregateRules(const std::string& country_code,
// Key construction:
// https://code.google.com/p/libaddressinput/wiki/AddressValidationMetadata
// Example of a country-level key: "data/CA".
- std::string key = "data/" + country_code_;
- requests_.insert(std::make_pair(
- key, RequestData(NULL, COUNTRY, false, std::string())));
-
+ key_ = "data/" + country_code_;
retriever_->Retrieve(
- key, BuildCallback(this, &CountryRulesAggregator::OnDataReady));
+ key_, BuildCallback(this, &CountryRulesAggregator::OnDataReady));
}
void CountryRulesAggregator::OnDataReady(bool success,
const std::string& key,
const std::string& data) {
- std::map<std::string, RequestData>::iterator request_it =
- requests_.find(key);
- if (request_it == requests_.end()) {
+ if (key != key_) {
return; // An abandoned request.
}
- if (!success) {
+ json_ = Json::Build().Pass();
+ if (!success || !json_->ParseObject(data)) {
(*rules_ready_)(false, country_code_, scoped_ptr<Ruleset>());
Reset();
return;
}
- RequestData request = request_it->second;
- requests_.erase(request_it);
+ scoped_ptr<Ruleset> ruleset = Build(key_, COUNTRY);
+ (*rules_ready_)(ruleset != NULL, country_code_, ruleset.Pass());
+ Reset();
+}
- // All country-level rules are based on the default rule.
- scoped_ptr<Rule> rule(new Rule);
- if (request.level == COUNTRY) {
- rule->CopyFrom(Rule::GetDefault());
+scoped_ptr<Ruleset> CountryRulesAggregator::Build(const std::string& key,
+ AddressField field) {
+ scoped_ptr<Rule> rule = ParseRule(key, field);
+ if (rule == NULL) {
+ return scoped_ptr<Ruleset>();
}
- if (!rule->ParseSerializedRule(data)) {
- (*rules_ready_)(false, country_code_, scoped_ptr<Ruleset>());
- Reset();
- return;
+ // Determine the languages that have language-specific rules. For example,
+ // the default language in Switzerland is "de", but "fr" and "it" have
+ // language specific rules.
+ if (field == COUNTRY) {
+ non_default_languages_ = rule->GetLanguages();
+ std::vector<std::string>::iterator default_language_it =
+ std::find(non_default_languages_.begin(),
+ non_default_languages_.end(),
+ rule->GetLanguage());
+ if (default_language_it != non_default_languages_.end()) {
+ non_default_languages_.erase(default_language_it);
+ }
}
- // Place the rule in the correct location in the ruleset.
- Ruleset* ruleset = NULL;
- if (request.is_language_code) {
- assert(request.parent != NULL);
- request.parent->AddLanguageCodeRule(request.id, rule.Pass());
- ruleset = request.parent;
- } else if (request.level == COUNTRY) {
- // The default language and all supported languages for the country code are
- // in the country-level rule without a language code identifier. For
- // example: "data/CA".
- default_language_ = rule->GetLanguage();
- languages_ = rule->GetLanguages();
-
- root_.reset(new Ruleset(request.level, rule.Pass()));
- ruleset = root_.get();
- } else {
- assert(request.parent != NULL);
- ruleset = new Ruleset(request.level, rule.Pass());
- request.parent->AddSubRegionRuleset(
- request.id, scoped_ptr<Ruleset>(ruleset));
- }
+ scoped_ptr<Ruleset> ruleset(new Ruleset(field, rule.Pass()));
- if (!request.is_language_code) {
- // Retrieve the language-specific rules for this region.
- for (std::vector<std::string>::const_iterator
- lang_it = languages_.begin();
- lang_it != languages_.end();
- ++lang_it) {
- if (*lang_it == default_language_) {
- continue;
- }
- // Example of a language-specific key: "data/CA--fr".
- std::string language_code_key = key + "--" + *lang_it;
- requests_.insert(std::make_pair(
- key, RequestData(ruleset, request.level, true, *lang_it)));
- retriever_->Retrieve(
- language_code_key,
- BuildCallback(this, &CountryRulesAggregator::OnDataReady));
+ // Parse the language-specific rules. For example, parse the rules for "fr"
+ // and "it" languages in Switzerland.
+ for (std::vector<std::string>::const_iterator
+ lang_it = non_default_languages_.begin();
+ lang_it != non_default_languages_.end(); ++lang_it) {
+ scoped_ptr<Rule> lang_rule = ParseRule(key + "--" + *lang_it, field);
+ if (lang_rule == NULL) {
+ return scoped_ptr<Ruleset>();
}
+ ruleset->AddLanguageCodeRule(*lang_it, lang_rule.Pass());
+ }
- if (request.level < DEPENDENT_LOCALITY) {
- // Retrieve the sub-region rules for this region.
- for (std::vector<std::string>::const_iterator
- subkey_it = ruleset->rule().GetSubKeys().begin();
- subkey_it != ruleset->rule().GetSubKeys().end();
- ++subkey_it) {
- // Example of a sub-region key: "data/CA/AB".
- std::string sub_region_key = key + "/" + *subkey_it;
- requests_.insert(std::make_pair(
- key,
- RequestData(ruleset,
- static_cast<AddressField>(request.level + 1),
- false,
- *subkey_it)));
- retriever_->Retrieve(
- sub_region_key,
- BuildCallback(this, &CountryRulesAggregator::OnDataReady));
- }
+ // Parse the sub-keys. For example, parse the rules for all of the states in
+ // US: "CA", "TX", "NY", etc.
+ for (std::vector<std::string>::const_iterator
+ subkey_it = ruleset->rule().GetSubKeys().begin();
+ subkey_it != ruleset->rule().GetSubKeys().end(); ++subkey_it) {
+ scoped_ptr<Ruleset> sub_ruleset =
+ Build(key + "/" + *subkey_it, static_cast<AddressField>(field + 1));
+ if (sub_ruleset == NULL) {
+ return scoped_ptr<Ruleset>();
}
+ ruleset->AddSubRegionRuleset(*subkey_it, sub_ruleset.Pass());
}
- if (requests_.empty()) {
- (*rules_ready_)(true, country_code_, root_.Pass());
- Reset();
+ return ruleset.Pass();
+}
+
+scoped_ptr<Rule> CountryRulesAggregator::ParseRule(const std::string& key,
+ AddressField field) const {
+ scoped_ptr<Json> value;
+ if (!json_->GetJsonValueForKey(key, &value) || value == NULL) {
+ return scoped_ptr<Rule>();
+ }
+ scoped_ptr<Rule> rule(new Rule);
+ if (field == COUNTRY) {
+ rule->CopyFrom(Rule::GetDefault());
}
+ rule->ParseJsonRule(*value);
+ return rule.Pass();
}
void CountryRulesAggregator::Reset() {
- requests_.clear();
country_code_.clear();
+ key_.clear();
rules_ready_.reset();
- root_.reset();
- default_language_.clear();
- languages_.clear();
+ json_.reset();
+ non_default_languages_.clear();
}
} // namespace addressinput

Powered by Google App Engine
This is Rietveld 408576698