1 // Copyright (C) 2012 The Libphonenumber Authors
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 // Library for obtaining information about international short phone numbers,
16 // such as short codes and emergency numbers. Note most commercial short
17 // numbers are not handled here, but by the phonenumberutil.
18 
19 #ifndef I18N_PHONENUMBERS_SHORTNUMBERINFO_H_
20 #define I18N_PHONENUMBERS_SHORTNUMBERINFO_H_
21 
22 #include <list>
23 #include <map>
24 #include <set>
25 #include <string>
26 
27 #include "phonenumbers/base/basictypes.h"
28 #include "phonenumbers/base/memory/scoped_ptr.h"
29 
30 namespace i18n {
31 namespace phonenumbers {
32 
33 using std::list;
34 using std::map;
35 using std::set;
36 using std::string;
37 
38 class MatcherApi;
39 class PhoneMetadata;
40 class PhoneNumber;
41 class PhoneNumberUtil;
42 
43 class ShortNumberInfo {
44  public:
45   ShortNumberInfo();
46 
47   // This type is neither copyable nor movable.
48   ShortNumberInfo(const ShortNumberInfo&) = delete;
49   ShortNumberInfo& operator=(const ShortNumberInfo&) = delete;
50 
51   ~ShortNumberInfo();
52 
53   // Cost categories of short numbers.
54   enum ShortNumberCost {
55     TOLL_FREE,
56     STANDARD_RATE,
57     PREMIUM_RATE,
58     UNKNOWN_COST
59   };
60 
61   // Check whether a short number is a possible number when dialled from a
62   // region, given the number in the form of a string, and the region where the
63   // number is dialed from.  This provides a more lenient check than
64   // IsValidShortNumberForRegion.
65   bool IsPossibleShortNumberForRegion(
66       const PhoneNumber& short_number,
67       const string& region_dialing_from) const;
68 
69   // Check whether a short number is a possible number. If a country calling
70   // code is shared by multiple regions, this returns true if it's possible in
71   // any of them. This provides a more lenient check than IsValidShortNumber.
72   // See IsPossibleShortNumberForRegion for details.
73   bool IsPossibleShortNumber(const PhoneNumber& number) const;
74 
75   // Tests whether a short number matches a valid pattern in a region. Note
76   // that this doesn't verify the number is actually in use, which is
77   // impossible to tell by just looking at the number itself.
78   bool IsValidShortNumberForRegion(
79       const PhoneNumber& short_number,
80       const string& region_dialing_from) const;
81 
82   // Tests whether a short number matches a valid pattern. If a country calling
83   // code is shared by multiple regions, this returns true if it's valid in any
84   // of them. Note that this doesn't verify the number is actually in use,
85   // which is impossible to tell by just looking at the number itself. See
86   // IsValidShortNumberForRegion for details.
87   bool IsValidShortNumber(const PhoneNumber& number) const;
88 
89   // Gets the expected cost category of a short number when dialled from a
90   // region (however, nothing is implied about its validity). If it is
91   // important that the number is valid, then its validity must first be
92   // checked using IsValidShortNumberForRegion. Note that emergency numbers are
93   // always considered toll-free. Example usage:
94   //
95   // PhoneNumber number;
96   // phone_util.Parse("110", "US", &number);
97   // ...
98   // string region_code("CA");
99   // ShortNumberInfo short_info;
100   // if (short_info.IsValidShortNumberForRegion(number, region_code)) {
101   //   ShortNumberInfo::ShortNumberCost cost =
102   //       short_info.GetExpectedCostForRegion(number, region_code);
103   //   // Do something with the cost information here.
104   // }
105   ShortNumberCost GetExpectedCostForRegion(
106       const PhoneNumber& short_number,
107       const string& region_dialing_from) const;
108 
109   // Gets the expected cost category of a short number (however, nothing is
110   // implied about its validity). If the country calling code is unique to a
111   // region, this method behaves exactly the same as GetExpectedCostForRegion.
112   // However, if the country calling code is shared by multiple regions, then
113   // it returns the highest cost in the sequence PREMIUM_RATE, UNKNOWN_COST,
114   // STANDARD_RATE, TOLL_FREE. The reason for the position of UNKNOWN_COST in
115   // this order is that if a number is UNKNOWN_COST in one region but
116   // STANDARD_RATE or TOLL_FREE in another, its expected cost cannot be
117   // estimated as one of the latter since it might be a PREMIUM_RATE number.
118   //
119   // For example, if a number is STANDARD_RATE in the US, but TOLL_FREE in
120   // Canada, the expected cost returned by this method will be STANDARD_RATE,
121   // since the NANPA countries share the same country calling code.
122   //
123   // Note: If the region from which the number is dialed is known, it is highly
124   // preferable to call GetExpectedCostForRegion instead.
125   ShortNumberCost GetExpectedCost(const PhoneNumber& number) const;
126 
127   // Gets a valid short number for the specified region.
128   string GetExampleShortNumber(const string& region_code) const;
129 
130   // Gets a valid short number for the specified cost category.
131   string GetExampleShortNumberForCost(const string& region_code,
132                                       ShortNumberCost cost) const;
133 
134   // Returns true if the number might be used to connect to an emergency service
135   // in the given region.
136   //
137   // This method takes into account cases where the number might contain
138   // formatting, or might have additional digits appended (when it is okay to do
139   // that in the region specified).
140   bool ConnectsToEmergencyNumber(const string& number,
141                                  const string& region_code) const;
142 
143   // Returns true if the number exactly matches an emergency service number in
144   // the given region.
145   //
146   // This method takes into account cases where the number might contain
147   // formatting, but doesn't allow additional digits to be appended.
148   bool IsEmergencyNumber(const string& number,
149                          const string& region_code) const;
150 
151   // Given a valid short number, determines whether it is carrier-specific
152   // (however, nothing is implied about its validity). Carrier-specific numbers
153   // may connect to a different end-point, or not connect at all, depending on
154   // the user's carrier. If it is important that the number is valid, then its
155   // validity must first be checked using IsValidShortNumber or
156   // IsValidShortNumberForRegion.
157   bool IsCarrierSpecific(const PhoneNumber& number) const;
158 
159   // Given a valid short number, determines whether it is carrier-specific when
160   // dialed from the given region (however, nothing is implied about its
161   // validity). Carrier-specific numbers may connect to a different end-point,
162   // or not connect at all, depending on the user's carrier. If it is important
163   // that the number is valid, then its validity must first be checked using
164   // IsValidShortNumber or IsValidShortNumberForRegion. Returns false if the
165   // number doesn't match the region provided.
166   bool IsCarrierSpecificForRegion(
167       const PhoneNumber& number,
168       const string& region_dialing_from) const;
169 
170   // Given a valid short number, determines whether it is an SMS service
171   // (however, nothing is implied about its validity). An SMS service is where
172   // the primary or only intended usage is to receive and/or send text messages
173   // (SMSs). This includes MMS as MMS numbers downgrade to SMS if the other
174   // party isn't MMS-capable. If it is important that the number is valid, then
175   // its validity must first be checked using IsValidShortNumber or
176   // IsValidShortNumberForRegion. Returns false if the number doesn't match the
177   // region provided.
178   bool IsSmsServiceForRegion(
179       const PhoneNumber& number,
180       const string& region_dialing_from) const;
181 
182  private:
183   const PhoneNumberUtil& phone_util_;
184   const scoped_ptr<const MatcherApi> matcher_api_;
185 
186   // A mapping from a RegionCode to the PhoneMetadata for that region.
187   scoped_ptr<std::map<string, PhoneMetadata> >
188       region_to_short_metadata_map_;
189 
190   // In these countries, if extra digits are added to an emergency number, it no
191   // longer connects to the emergency service.
192   scoped_ptr<std::set<string> >
193       regions_where_emergency_numbers_must_be_exact_;
194 
195   const i18n::phonenumbers::PhoneMetadata* GetMetadataForRegion(
196       const string& region_code) const;
197 
198   bool RegionDialingFromMatchesNumber(const PhoneNumber& number,
199       const string& region_dialing_from) const;
200 
201   // Helper method to get the region code for a given phone number, from a list
202   // of possible region codes. If the list contains more than one region, the
203   // first region for which the number is valid is returned.
204   void GetRegionCodeForShortNumberFromRegionList(
205       const PhoneNumber& number,
206       const list<string>& region_codes,
207       string* region_code) const;
208 
209   bool MatchesEmergencyNumberHelper(const string& number,
210                                     const string& region_code,
211                                     bool allow_prefix_match) const;
212 };
213 
214 }  // namespace phonenumbers
215 }  // namespace i18n
216 
217 #endif  // I18N_PHONENUMBERS_SHORTNUMBERINFO_H_
218