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 #ifndef I18N_ADDRESSINPUT_RULESET_H_ 16 #define I18N_ADDRESSINPUT_RULESET_H_ 17 18 #include <libaddressinput/address_field.h> 19 #include <libaddressinput/util/basictypes.h> 20 #include <libaddressinput/util/scoped_ptr.h> 21 22 #include <map> 23 #include <set> 24 #include <string> 25 26 #include "rule.h" 27 #include "util/canonicalize_string.h" 28 #include "util/trie.h" 29 30 namespace i18n { 31 namespace addressinput { 32 33 // A recursive data structure that stores a set of rules for a region. Can store 34 // the rules for a country, its administrative areas, localities, and dependent 35 // localities, in addition to the language-specific rules. 36 // 37 // Example for Canada and some of its provinces: 38 // CA-->fr 39 // | 40 // ------------------------------------- 41 // | | | | | 42 // v v v v v 43 // AB-->fr BC-->fr MB-->fr NB-->fr NL-->fr 44 // 45 // The rules in Canada are in English by default. Each rule also has a French 46 // language version. 47 class Ruleset { 48 public: 49 // Builds a ruleset for |field| with a region-wide |rule| in the default 50 // language of the country. The |field| should be between COUNTRY and 51 // DEPENDENT_LOCALITY (inclusively). The |rule| should not be NULL. 52 Ruleset(AddressField field, scoped_ptr<Rule> rule); 53 54 ~Ruleset(); 55 56 // Returns the parent ruleset. This is NULL until this ruleset has been passed 57 // into a AddSubRegionRuleset() method. Consequently, this is always NULL for 58 // a country-level ruleset. 59 Ruleset* parent() const { return parent_; } 60 61 // Returns the field type for this ruleset. 62 AddressField field() const { return field_; } 63 64 // Returns the region-wide rule for this ruleset in the default language of 65 // the country. 66 const Rule& rule() const { return *rule_; } 67 68 // Adds the |ruleset| for |sub_region| and sets this to be its parent. A 69 // |sub_region| should be added at most once. The |ruleset| should not be 70 // NULL. 71 // 72 // The field of the |ruleset| parameter must be exactly one smaller than the 73 // field of this ruleset. For example, a COUNTRY ruleset can contain 74 // ADMIN_AREA rulesets, but should not contain COUNTRY or LOCALITY rulesets. 75 void AddSubRegionRuleset(const std::string& sub_region, 76 scoped_ptr<Ruleset> ruleset); 77 78 // Adds a language-specific |rule| for |language_code| for this region. A 79 // |language_code| should be added at most once. The |rule| should not be 80 // NULL. 81 void AddLanguageCodeRule(const std::string& language_code, 82 scoped_ptr<Rule> rule); 83 84 // Returns the set of rules for |sub_region|. The result is NULL if there's no 85 // such |sub_region|. The caller does not own the result. 86 Ruleset* GetSubRegionRuleset(const std::string& sub_region) const; 87 88 // If there's a language-specific rule for |language_code|, then returns this 89 // rule. Otherwise returns the rule in the default language of the country. 90 const Rule& GetLanguageCodeRule(const std::string& language_code) const; 91 92 // Returns a mapping of sub-region keys to rulesets. The caller does now own 93 // the result. The values are not NULL. 94 const std::map<std::string, Ruleset*>& GetSubRegionRulesets() const { 95 return sub_regions_; 96 } 97 98 // Enables using FindRulesetsByPrefix() method. Should be called only once and 99 // on a COUNTRY level ruleset. 100 void BuildPrefixSearchIndex(); 101 102 // Returns true if BuildPrefixSearchIndex() has been called. 103 bool prefix_search_index_ready() const { return !tries_.empty(); } 104 105 // Returns the deepest possible ruleset level for this country. Must be called 106 // on a COUNTRY level ruleset. Must be called after BuildPrefixSearchIndex() 107 // has been called. 108 AddressField deepest_ruleset_level() const { return deepest_ruleset_level_; } 109 110 // Finds all rulesets at |ruleset_level| where the rule for |language_code| 111 // has the |identity_field| that starts with |prefix|. Ignores diacritics and 112 // capitalization differences between the rule data and |prefix|. 113 // 114 // If there're no rules for |language_code| (or |language_code| is an empty 115 // string), then the default language code is used. 116 // 117 // Should be called only on a COUNTRY level ruleset. Should be called only 118 // after BuildPrefixSearchIndex() has been called. 119 // 120 // The |field| parameter should be only ADMIN_AREA, LOCALITY, or 121 // DEPENDENT_LOCALITY. The result parameter should not be NULL. 122 void FindRulesetsByPrefix(const std::string& language_code, 123 AddressField ruleset_level, 124 Rule::IdentityField identity_field, 125 const std::string& prefix, 126 std::set<const Ruleset*>* result) const; 127 128 private: 129 // The type that maps rule identity field to tries of rulesets. 130 typedef std::map<Rule::IdentityField, Trie<const Ruleset*>*> 131 IdentityFieldTries; 132 133 // The type that maps address field to IdentityFieldTries. 134 typedef std::map<AddressField, IdentityFieldTries*> AddressFieldTries; 135 136 // The type that maps language code to AddressFieldTries. 137 typedef std::map<std::string, AddressFieldTries*> LanguageCodeTries; 138 139 // Adds all children of |parent_ruleset| into |tries_| of this ruleset. Should 140 // be called only on a COUNTRY level ruleset. 141 void AddSubRegionRulesetsToTrie(const Ruleset& parent_ruleset); 142 143 // The tries to lookup rulesets by a prefix of key, name, or latin-name in a 144 // rule. Has data only in a COUNTRY level ruleset. Owns the map and trie 145 // objects. Does not own the ruleset objects. 146 LanguageCodeTries tries_; 147 148 // Canonicalizes region keys, names, and latin names when building a trie. 149 scoped_ptr<StringCanonicalizer> canonicalizer_; 150 151 // The parent ruleset of this object. The parent ruleset owns this object. 152 Ruleset* parent_; 153 154 // The field of this ruleset. 155 const AddressField field_; 156 157 // The deepest possible ruleset level for this country. Set in 158 // BuildPrefixSearchIndex() method and, therefore, meaningful only on a 159 // COUNTRY level ruleset. 160 AddressField deepest_ruleset_level_; 161 162 // The region-wide rule in the default language of the country. 163 const scoped_ptr<const Rule> rule_; 164 165 // Owned rulesets for sub-regions. 166 std::map<std::string, Ruleset*> sub_regions_; 167 168 // Owned language-specific rules for the region. 169 std::map<std::string, const Rule*> language_codes_; 170 171 DISALLOW_COPY_AND_ASSIGN(Ruleset); 172 }; 173 174 } // namespace addressinput 175 } // namespace i18n 176 177 #endif // I18N_ADDRESSINPUT_RULESET_H_ 178