Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / libaddressinput / src / cpp / src / rule.cc
1 // Copyright (C) 2013 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 "rule.h"
16
17 #include <cassert>
18 #include <cstddef>
19 #include <map>
20 #include <string>
21 #include <utility>
22
23 #include <re2/re2.h>
24
25 #include "address_field_util.h"
26 #include "format_element.h"
27 #include "grit.h"
28 #include "messages.h"
29 #include "region_data_constants.h"
30 #include "util/json.h"
31 #include "util/re2ptr.h"
32 #include "util/string_split.h"
33
34 namespace i18n {
35 namespace addressinput {
36
37 namespace {
38
39 typedef std::map<std::string, int> NameMessageIdMap;
40
41 // Used as a separator in a list of items. For example, the list of supported
42 // languages can be "de~fr~it".
43 const char kSeparator = '~';
44
45 NameMessageIdMap InitAdminAreaMessageIds() {
46   NameMessageIdMap message_ids;
47   message_ids.insert(std::make_pair(
48       "area", IDS_LIBADDRESSINPUT_AREA));
49   message_ids.insert(std::make_pair(
50       "county", IDS_LIBADDRESSINPUT_COUNTY));
51   message_ids.insert(std::make_pair(
52       "department", IDS_LIBADDRESSINPUT_DEPARTMENT));
53   message_ids.insert(std::make_pair(
54       "district", IDS_LIBADDRESSINPUT_DISTRICT));
55   message_ids.insert(std::make_pair(
56       "do_si", IDS_LIBADDRESSINPUT_DO_SI));
57   message_ids.insert(std::make_pair(
58       "emirate", IDS_LIBADDRESSINPUT_EMIRATE));
59   message_ids.insert(std::make_pair(
60       "island", IDS_LIBADDRESSINPUT_ISLAND));
61   message_ids.insert(std::make_pair(
62       "oblast", IDS_LIBADDRESSINPUT_OBLAST));
63   message_ids.insert(std::make_pair(
64       "parish", IDS_LIBADDRESSINPUT_PARISH));
65   message_ids.insert(std::make_pair(
66       "prefecture", IDS_LIBADDRESSINPUT_PREFECTURE));
67   message_ids.insert(std::make_pair(
68       "province", IDS_LIBADDRESSINPUT_PROVINCE));
69   message_ids.insert(std::make_pair(
70       "state", IDS_LIBADDRESSINPUT_STATE));
71   return message_ids;
72 }
73
74 const NameMessageIdMap& GetAdminAreaMessageIds() {
75   static const NameMessageIdMap kAdminAreaMessageIds(InitAdminAreaMessageIds());
76   return kAdminAreaMessageIds;
77 }
78
79 NameMessageIdMap InitPostalCodeMessageIds() {
80   NameMessageIdMap message_ids;
81   message_ids.insert(std::make_pair(
82       "postal", IDS_LIBADDRESSINPUT_POSTAL_CODE_LABEL));
83   message_ids.insert(std::make_pair(
84       "zip", IDS_LIBADDRESSINPUT_ZIP_CODE_LABEL));
85   return message_ids;
86 }
87
88 const NameMessageIdMap& GetPostalCodeMessageIds() {
89   static const NameMessageIdMap kPostalCodeMessageIds(
90       InitPostalCodeMessageIds());
91   return kPostalCodeMessageIds;
92 }
93
94 NameMessageIdMap InitLocalityMessageIds() {
95   NameMessageIdMap message_ids;
96   message_ids.insert(std::make_pair(
97       "city", IDS_LIBADDRESSINPUT_LOCALITY_LABEL));
98   message_ids.insert(std::make_pair(
99       "post_town", IDS_LIBADDRESSINPUT_POST_TOWN));
100   message_ids.insert(std::make_pair(
101       "district", IDS_LIBADDRESSINPUT_DISTRICT));
102   return message_ids;
103 }
104
105 const NameMessageIdMap& GetLocalityMessageIds() {
106   static const NameMessageIdMap kLocalityMessageIds(
107       InitLocalityMessageIds());
108   return kLocalityMessageIds;
109 }
110
111 NameMessageIdMap InitSublocalityMessageIds() {
112   NameMessageIdMap message_ids;
113   message_ids.insert(std::make_pair(
114       "suburb", IDS_LIBADDRESSINPUT_SUBURB));
115   message_ids.insert(std::make_pair(
116       "district", IDS_LIBADDRESSINPUT_DISTRICT));
117   message_ids.insert(std::make_pair(
118       "neighborhood", IDS_LIBADDRESSINPUT_NEIGHBORHOOD));
119   message_ids.insert(std::make_pair(
120       "village_township", IDS_LIBADDRESSINPUT_VILLAGE_TOWNSHIP));
121   return message_ids;
122 }
123
124 const NameMessageIdMap& GetSublocalityMessageIds() {
125   static const NameMessageIdMap kSublocalityMessageIds(
126       InitSublocalityMessageIds());
127   return kSublocalityMessageIds;
128 }
129
130 int GetMessageIdFromName(const std::string& name,
131                          const NameMessageIdMap& message_ids) {
132   NameMessageIdMap::const_iterator it = message_ids.find(name);
133   return it != message_ids.end() ? it->second : INVALID_MESSAGE_ID;
134 }
135
136 // Determines whether a given string is a reg-exp or a string. We consider a
137 // string to be anything that doesn't contain characters with special meanings
138 // in regular expressions - (, [, \, {, ?. These special characters are all the
139 // ones that appear in the postal code regular expressions.
140 bool ContainsRegExSpecialCharacters(const std::string& input) {
141   return input.find_first_of("([\\{?") != std::string::npos;
142 }
143
144 }  // namespace
145
146 Rule::Rule()
147     : id_(),
148       format_(),
149       latin_format_(),
150       required_(),
151       sub_keys_(),
152       languages_(),
153       postal_code_matcher_(NULL),
154       sole_postal_code_(),
155       admin_area_name_message_id_(INVALID_MESSAGE_ID),
156       postal_code_name_message_id_(INVALID_MESSAGE_ID),
157       locality_name_message_id_(INVALID_MESSAGE_ID),
158       sublocality_name_message_id_(INVALID_MESSAGE_ID),
159       name_(),
160       latin_name_(),
161       postal_code_example_(),
162       post_service_url_() {}
163
164 Rule::~Rule() {}
165
166 // static
167 const Rule& Rule::GetDefault() {
168   // Allocated once and leaked on shutdown.
169   static Rule* default_rule = NULL;
170   if (default_rule == NULL) {
171     default_rule = new Rule;
172     default_rule->ParseSerializedRule(
173         RegionDataConstants::GetDefaultRegionData());
174   }
175   return *default_rule;
176 }
177
178 void Rule::CopyFrom(const Rule& rule) {
179   assert(this != &rule);
180   id_ = rule.id_;
181   format_ = rule.format_;
182   latin_format_ = rule.latin_format_;
183   required_ = rule.required_;
184   sub_keys_ = rule.sub_keys_;
185   languages_ = rule.languages_;
186   postal_code_matcher_.reset(
187       rule.postal_code_matcher_ == NULL
188           ? NULL
189           : new RE2ptr(new RE2(rule.postal_code_matcher_->ptr->pattern(),
190                                rule.postal_code_matcher_->ptr->options())));
191   sole_postal_code_ = rule.sole_postal_code_;
192   admin_area_name_message_id_ = rule.admin_area_name_message_id_;
193   postal_code_name_message_id_ = rule.postal_code_name_message_id_;
194   locality_name_message_id_ = rule.locality_name_message_id_;
195   sublocality_name_message_id_ = rule.sublocality_name_message_id_;
196   name_ = rule.name_;
197   latin_name_ = rule.latin_name_;
198   postal_code_example_ = rule.postal_code_example_;
199   post_service_url_ = rule.post_service_url_;
200 }
201
202 bool Rule::ParseSerializedRule(const std::string& serialized_rule) {
203   Json json;
204   if (!json.ParseObject(serialized_rule)) {
205     return false;
206   }
207   ParseJsonRule(json);
208   return true;
209 }
210
211 void Rule::ParseJsonRule(const Json& json) {
212   std::string value;
213   if (json.GetStringValueForKey("id", &value)) {
214     id_.swap(value);
215   }
216
217   if (json.GetStringValueForKey("fmt", &value)) {
218     ParseFormatRule(value, &format_);
219   }
220
221   if (json.GetStringValueForKey("lfmt", &value)) {
222     ParseFormatRule(value, &latin_format_);
223   }
224
225   if (json.GetStringValueForKey("require", &value)) {
226     ParseAddressFieldsRequired(value, &required_);
227   }
228
229   if (json.GetStringValueForKey("sub_keys", &value)) {
230     SplitString(value, kSeparator, &sub_keys_);
231   }
232
233   if (json.GetStringValueForKey("languages", &value)) {
234     SplitString(value, kSeparator, &languages_);
235   }
236
237   sole_postal_code_.clear();
238   if (json.GetStringValueForKey("zip", &value)) {
239     // The "zip" field in the JSON data is used in two different ways to
240     // validate the postal code. At the country level, the "zip" field indicates
241     // a Java compatible regular expression corresponding to all postal codes in
242     // the country. At other levels, the regular expression indicates the postal
243     // code prefix expected for addresses in that region.
244     //
245     // In order to make the RE2 object created from the "zip" field useable for
246     // both these purposes, the pattern string is here prefixed with "^" to
247     // anchor it at the beginning of the string so that it can be used with
248     // RE2::PartialMatch() to perform prefix matching or else with
249     // RE2::FullMatch() to perform matching against the entire string.
250     RE2::Options options;
251     options.set_never_capture(true);
252     RE2* matcher = new RE2("^(" + value + ")", options);
253     if (matcher->ok()) {
254       postal_code_matcher_.reset(new RE2ptr(matcher));
255     } else {
256       postal_code_matcher_.reset(NULL);
257       delete matcher;
258     }
259     // If the "zip" field is not a regular expression, then it is the sole
260     // postal code for this rule.
261     if (!ContainsRegExSpecialCharacters(value)) {
262       sole_postal_code_.swap(value);
263     }
264   }
265
266   if (json.GetStringValueForKey("state_name_type", &value)) {
267     admin_area_name_message_id_ =
268         GetMessageIdFromName(value, GetAdminAreaMessageIds());
269   }
270
271   if (json.GetStringValueForKey("zip_name_type", &value)) {
272     postal_code_name_message_id_ =
273         GetMessageIdFromName(value, GetPostalCodeMessageIds());
274   }
275
276   if (json.GetStringValueForKey("locality_name_type", &value)) {
277     locality_name_message_id_ =
278         GetMessageIdFromName(value, GetLocalityMessageIds());
279   }
280
281   if (json.GetStringValueForKey("sublocality_name_type", &value)) {
282     sublocality_name_message_id_ =
283         GetMessageIdFromName(value, GetSublocalityMessageIds());
284   }
285
286   if (json.GetStringValueForKey("name", &value)) {
287     name_.swap(value);
288   }
289
290   if (json.GetStringValueForKey("lname", &value)) {
291     latin_name_.swap(value);
292   }
293
294   if (json.GetStringValueForKey("zipex", &value)) {
295     postal_code_example_.swap(value);
296   }
297
298   if (json.GetStringValueForKey("posturl", &value)) {
299     post_service_url_.swap(value);
300   }
301 }
302
303 }  // namespace addressinput
304 }  // namespace i18n