JS: Change back from getCountryCode() to getCountryCodeOrDefault().
[platform/upstream/libphonenumber.git] / javascript / i18n / phonenumbers / phonenumberutil.js
1 /**
2  * @license
3  * Copyright (C) 2010 The Libphonenumber Authors
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 /**
19  * @fileoverview  Utility for international phone numbers.
20  * Functionality includes formatting, parsing and validation.
21  * (based on the java implementation).
22  *
23  * NOTE: A lot of methods in this class require Region Code strings. These must
24  * be provided using ISO 3166-1 two-letter country-code format. These should be
25  * in upper-case (but for compatibility lower-case is also allowed). The list of
26  * the codes can be found here:
27  * http://www.iso.org/iso/english_country_names_and_code_elements
28  *
29  * @author Nikolaos Trogkanis
30  */
31
32 goog.provide('i18n.phonenumbers.Error');
33 goog.provide('i18n.phonenumbers.PhoneNumberFormat');
34 goog.provide('i18n.phonenumbers.PhoneNumberType');
35 goog.provide('i18n.phonenumbers.PhoneNumberUtil');
36 goog.provide('i18n.phonenumbers.PhoneNumberUtil.MatchType');
37 goog.provide('i18n.phonenumbers.PhoneNumberUtil.ValidationResult');
38
39 goog.require('goog.array');
40 goog.require('goog.proto2.PbLiteSerializer');
41 goog.require('goog.string');
42 goog.require('goog.string.StringBuffer');
43 goog.require('i18n.phonenumbers.NumberFormat');
44 goog.require('i18n.phonenumbers.PhoneMetadata');
45 goog.require('i18n.phonenumbers.PhoneMetadataCollection');
46 goog.require('i18n.phonenumbers.PhoneNumber');
47 goog.require('i18n.phonenumbers.PhoneNumber.CountryCodeSource');
48 goog.require('i18n.phonenumbers.PhoneNumberDesc');
49 goog.require('i18n.phonenumbers.metadata');
50
51
52
53 /**
54  * @constructor
55  * @private
56  */
57 i18n.phonenumbers.PhoneNumberUtil = function() {
58   /**
59    * A mapping from a region code to the PhoneMetadata for that region.
60    * @type {Object.<string, i18n.phonenumbers.PhoneMetadata>}
61    */
62   this.regionToMetadataMap = {};
63 };
64 goog.addSingletonGetter(i18n.phonenumbers.PhoneNumberUtil);
65
66
67 /**
68  * Errors encountered when parsing phone numbers.
69  *
70  * @enum {string}
71  */
72 i18n.phonenumbers.Error = {
73   INVALID_COUNTRY_CODE: 'Invalid country calling code',
74   // This generally indicates the string passed in had less than 3 digits in it.
75   // More specifically, the number failed to match the regular expression
76   // VALID_PHONE_NUMBER.
77   NOT_A_NUMBER: 'The string supplied did not seem to be a phone number',
78   // This indicates the string started with an international dialing prefix, but
79   // after this was stripped from the number, had less digits than any valid
80   // phone number (including country calling code) could have.
81   TOO_SHORT_AFTER_IDD: 'Phone number too short after IDD',
82   // This indicates the string, after any country calling code has been
83   // stripped, had less digits than any valid phone number could have.
84   TOO_SHORT_NSN: 'The string supplied is too short to be a phone number',
85   // This indicates the string had more digits than any valid phone number could
86   // have.
87   TOO_LONG: 'The string supplied is too long to be a phone number'
88 };
89
90
91 /**
92  * @const
93  * @type {number}
94  * @private
95  */
96 i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_ = 1;
97
98
99 /**
100  * The minimum length of the national significant number.
101  *
102  * @const
103  * @type {number}
104  * @private
105  */
106 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_ = 2;
107
108
109 /**
110  * The ITU says the maximum length should be 15, but we have found longer
111  * numbers in Germany.
112  *
113  * @const
114  * @type {number}
115  * @private
116  */
117 i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_ = 16;
118
119
120 /**
121  * The maximum length of the country calling code.
122  *
123  * @const
124  * @type {number}
125  * @private
126  */
127 i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE_ = 3;
128
129
130 /**
131  * We don't allow input strings for parsing to be longer than 250 chars. This
132  * prevents malicious input from consuming CPU.
133  *
134  * @const
135  * @type {number}
136  * @private
137  */
138 i18n.phonenumbers.PhoneNumberUtil.MAX_INPUT_STRING_LENGTH_ = 250;
139
140
141 /**
142  * Region-code for the unknown region.
143  *
144  * @const
145  * @type {string}
146  * @private
147  */
148 i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_ = 'ZZ';
149
150
151 /**
152  * The prefix that needs to be inserted in front of a Colombian landline number
153  * when dialed from a mobile phone in Colombia.
154  *
155  * @const
156  * @type {string}
157  * @private
158  */
159 i18n.phonenumbers.PhoneNumberUtil.COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX_ = '3';
160
161
162 /**
163  * The PLUS_SIGN signifies the international prefix.
164  *
165  * @const
166  * @type {string}
167  */
168 i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN = '+';
169
170
171 /**
172  * @const
173  * @type {string}
174  * @private
175  */
176 i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ = '*';
177
178
179 /**
180  * The RFC 3966 format for extensions.
181  *
182  * @const
183  * @type {string}
184  * @private
185  */
186 i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ = ';ext=';
187
188
189 /**
190  * @const
191  * @type {string}
192  * @private
193  */
194 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_ = 'tel:';
195
196
197 /**
198  * @const
199  * @type {string}
200  * @private
201  */
202 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_ = ';phone-context=';
203
204
205 /**
206  * @const
207  * @type {string}
208  * @private
209  */
210 i18n.phonenumbers.PhoneNumberUtil.RFC3966_ISDN_SUBADDRESS_ = ';isub=';
211
212
213 /**
214  * These mappings map a character (key) to a specific digit that should replace
215  * it for normalization purposes. Non-European digits that may be used in phone
216  * numbers are mapped to a European equivalent.
217  *
218  * @const
219  * @type {!Object.<string, string>}
220  */
221 i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS = {
222   '0': '0',
223   '1': '1',
224   '2': '2',
225   '3': '3',
226   '4': '4',
227   '5': '5',
228   '6': '6',
229   '7': '7',
230   '8': '8',
231   '9': '9',
232   '\uFF10': '0', // Fullwidth digit 0
233   '\uFF11': '1', // Fullwidth digit 1
234   '\uFF12': '2', // Fullwidth digit 2
235   '\uFF13': '3', // Fullwidth digit 3
236   '\uFF14': '4', // Fullwidth digit 4
237   '\uFF15': '5', // Fullwidth digit 5
238   '\uFF16': '6', // Fullwidth digit 6
239   '\uFF17': '7', // Fullwidth digit 7
240   '\uFF18': '8', // Fullwidth digit 8
241   '\uFF19': '9', // Fullwidth digit 9
242   '\u0660': '0', // Arabic-indic digit 0
243   '\u0661': '1', // Arabic-indic digit 1
244   '\u0662': '2', // Arabic-indic digit 2
245   '\u0663': '3', // Arabic-indic digit 3
246   '\u0664': '4', // Arabic-indic digit 4
247   '\u0665': '5', // Arabic-indic digit 5
248   '\u0666': '6', // Arabic-indic digit 6
249   '\u0667': '7', // Arabic-indic digit 7
250   '\u0668': '8', // Arabic-indic digit 8
251   '\u0669': '9', // Arabic-indic digit 9
252   '\u06F0': '0', // Eastern-Arabic digit 0
253   '\u06F1': '1', // Eastern-Arabic digit 1
254   '\u06F2': '2', // Eastern-Arabic digit 2
255   '\u06F3': '3', // Eastern-Arabic digit 3
256   '\u06F4': '4', // Eastern-Arabic digit 4
257   '\u06F5': '5', // Eastern-Arabic digit 5
258   '\u06F6': '6', // Eastern-Arabic digit 6
259   '\u06F7': '7', // Eastern-Arabic digit 7
260   '\u06F8': '8', // Eastern-Arabic digit 8
261   '\u06F9': '9'  // Eastern-Arabic digit 9
262 };
263
264
265 /**
266  * A map that contains characters that are essential when dialling. That means
267  * any of the characters in this map must not be removed from a number when
268  * dialling, otherwise the call will not reach the intended destination.
269  *
270  * @const
271  * @type {!Object.<string, string>}
272  * @private
273  */
274 i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_ = {
275   '0': '0',
276   '1': '1',
277   '2': '2',
278   '3': '3',
279   '4': '4',
280   '5': '5',
281   '6': '6',
282   '7': '7',
283   '8': '8',
284   '9': '9',
285   '+': i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN,
286   '*': '*'
287 };
288
289
290 /**
291  * Only upper-case variants of alpha characters are stored.
292  *
293  * @const
294  * @type {!Object.<string, string>}
295  * @private
296  */
297 i18n.phonenumbers.PhoneNumberUtil.ALPHA_MAPPINGS_ = {
298   'A': '2',
299   'B': '2',
300   'C': '2',
301   'D': '3',
302   'E': '3',
303   'F': '3',
304   'G': '4',
305   'H': '4',
306   'I': '4',
307   'J': '5',
308   'K': '5',
309   'L': '5',
310   'M': '6',
311   'N': '6',
312   'O': '6',
313   'P': '7',
314   'Q': '7',
315   'R': '7',
316   'S': '7',
317   'T': '8',
318   'U': '8',
319   'V': '8',
320   'W': '9',
321   'X': '9',
322   'Y': '9',
323   'Z': '9'
324 };
325
326
327 /**
328  * For performance reasons, amalgamate both into one map.
329  *
330  * @const
331  * @type {!Object.<string, string>}
332  * @private
333  */
334 i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_ = {
335   '0': '0',
336   '1': '1',
337   '2': '2',
338   '3': '3',
339   '4': '4',
340   '5': '5',
341   '6': '6',
342   '7': '7',
343   '8': '8',
344   '9': '9',
345   '\uFF10': '0', // Fullwidth digit 0
346   '\uFF11': '1', // Fullwidth digit 1
347   '\uFF12': '2', // Fullwidth digit 2
348   '\uFF13': '3', // Fullwidth digit 3
349   '\uFF14': '4', // Fullwidth digit 4
350   '\uFF15': '5', // Fullwidth digit 5
351   '\uFF16': '6', // Fullwidth digit 6
352   '\uFF17': '7', // Fullwidth digit 7
353   '\uFF18': '8', // Fullwidth digit 8
354   '\uFF19': '9', // Fullwidth digit 9
355   '\u0660': '0', // Arabic-indic digit 0
356   '\u0661': '1', // Arabic-indic digit 1
357   '\u0662': '2', // Arabic-indic digit 2
358   '\u0663': '3', // Arabic-indic digit 3
359   '\u0664': '4', // Arabic-indic digit 4
360   '\u0665': '5', // Arabic-indic digit 5
361   '\u0666': '6', // Arabic-indic digit 6
362   '\u0667': '7', // Arabic-indic digit 7
363   '\u0668': '8', // Arabic-indic digit 8
364   '\u0669': '9', // Arabic-indic digit 9
365   '\u06F0': '0', // Eastern-Arabic digit 0
366   '\u06F1': '1', // Eastern-Arabic digit 1
367   '\u06F2': '2', // Eastern-Arabic digit 2
368   '\u06F3': '3', // Eastern-Arabic digit 3
369   '\u06F4': '4', // Eastern-Arabic digit 4
370   '\u06F5': '5', // Eastern-Arabic digit 5
371   '\u06F6': '6', // Eastern-Arabic digit 6
372   '\u06F7': '7', // Eastern-Arabic digit 7
373   '\u06F8': '8', // Eastern-Arabic digit 8
374   '\u06F9': '9', // Eastern-Arabic digit 9
375   'A': '2',
376   'B': '2',
377   'C': '2',
378   'D': '3',
379   'E': '3',
380   'F': '3',
381   'G': '4',
382   'H': '4',
383   'I': '4',
384   'J': '5',
385   'K': '5',
386   'L': '5',
387   'M': '6',
388   'N': '6',
389   'O': '6',
390   'P': '7',
391   'Q': '7',
392   'R': '7',
393   'S': '7',
394   'T': '8',
395   'U': '8',
396   'V': '8',
397   'W': '9',
398   'X': '9',
399   'Y': '9',
400   'Z': '9'
401 };
402
403
404 /**
405  * Separate map of all symbols that we wish to retain when formatting alpha
406  * numbers. This includes digits, ASCII letters and number grouping symbols such
407  * as '-' and ' '.
408  *
409  * @const
410  * @type {!Object.<string, string>}
411  * @private
412  */
413 i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_ = {
414   '0': '0',
415   '1': '1',
416   '2': '2',
417   '3': '3',
418   '4': '4',
419   '5': '5',
420   '6': '6',
421   '7': '7',
422   '8': '8',
423   '9': '9',
424   'A': 'A',
425   'B': 'B',
426   'C': 'C',
427   'D': 'D',
428   'E': 'E',
429   'F': 'F',
430   'G': 'G',
431   'H': 'H',
432   'I': 'I',
433   'J': 'J',
434   'K': 'K',
435   'L': 'L',
436   'M': 'M',
437   'N': 'N',
438   'O': 'O',
439   'P': 'P',
440   'Q': 'Q',
441   'R': 'R',
442   'S': 'S',
443   'T': 'T',
444   'U': 'U',
445   'V': 'V',
446   'W': 'W',
447   'X': 'X',
448   'Y': 'Y',
449   'Z': 'Z',
450   'a': 'A',
451   'b': 'B',
452   'c': 'C',
453   'd': 'D',
454   'e': 'E',
455   'f': 'F',
456   'g': 'G',
457   'h': 'H',
458   'i': 'I',
459   'j': 'J',
460   'k': 'K',
461   'l': 'L',
462   'm': 'M',
463   'n': 'N',
464   'o': 'O',
465   'p': 'P',
466   'q': 'Q',
467   'r': 'R',
468   's': 'S',
469   't': 'T',
470   'u': 'U',
471   'v': 'V',
472   'w': 'W',
473   'x': 'X',
474   'y': 'Y',
475   'z': 'Z',
476   '-': '-',
477   '\uFF0D': '-',
478   '\u2010': '-',
479   '\u2011': '-',
480   '\u2012': '-',
481   '\u2013': '-',
482   '\u2014': '-',
483   '\u2015': '-',
484   '\u2212': '-',
485   '/': '/',
486   '\uFF0F': '/',
487   ' ': ' ',
488   '\u3000': ' ',
489   '\u2060': ' ',
490   '.': '.',
491   '\uFF0E': '.'
492 };
493
494
495 /**
496  * Pattern that makes it easy to distinguish whether a region has a unique
497  * international dialing prefix or not. If a region has a unique international
498  * prefix (e.g. 011 in USA), it will be represented as a string that contains a
499  * sequence of ASCII digits. If there are multiple available international
500  * prefixes in a region, they will be represented as a regex string that always
501  * contains character(s) other than ASCII digits. Note this regex also includes
502  * tilde, which signals waiting for the tone.
503  *
504  * @const
505  * @type {!RegExp}
506  * @private
507  */
508 i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_ =
509     /[\d]+(?:[~\u2053\u223C\uFF5E][\d]+)?/;
510
511
512 /**
513  * Regular expression of acceptable punctuation found in phone numbers. This
514  * excludes punctuation found as a leading character only. This consists of dash
515  * characters, white space characters, full stops, slashes, square brackets,
516  * parentheses and tildes. It also includes the letter 'x' as that is found as a
517  * placeholder for carrier information in some phone numbers. Full-width
518  * variants are also present.
519  *
520  * @const
521  * @type {string}
522  */
523 i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION =
524     '-x\u2010-\u2015\u2212\u30FC\uFF0D-\uFF0F \u00A0\u00AD\u200B\u2060\u3000' +
525     '()\uFF08\uFF09\uFF3B\uFF3D.\\[\\]/~\u2053\u223C\uFF5E';
526
527
528 /**
529  * Digits accepted in phone numbers (ascii, fullwidth, arabic-indic, and eastern
530  * arabic digits).
531  *
532  * @const
533  * @type {string}
534  * @private
535  */
536 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ =
537     '0-9\uFF10-\uFF19\u0660-\u0669\u06F0-\u06F9';
538
539
540 /**
541  * We accept alpha characters in phone numbers, ASCII only, upper and lower
542  * case.
543  *
544  * @const
545  * @type {string}
546  * @private
547  */
548 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ = 'A-Za-z';
549
550
551 /**
552  * @const
553  * @type {string}
554  * @private
555  */
556 i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ = '+\uFF0B';
557
558
559 /**
560  * @const
561  * @type {!RegExp}
562  */
563 i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN =
564     new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']+');
565
566
567 /**
568  * @const
569  * @type {!RegExp}
570  * @private
571  */
572 i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_ =
573     new RegExp('^[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']+');
574
575
576 /**
577  * @const
578  * @type {string}
579  * @private
580  */
581 i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_ =
582     '[' + i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION + ']+';
583
584
585 /**
586  * @const
587  * @type {!RegExp}
588  */
589 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN =
590     new RegExp('([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + '])');
591
592
593 /**
594  * Regular expression of acceptable characters that may start a phone number for
595  * the purposes of parsing. This allows us to strip away meaningless prefixes to
596  * phone numbers that may be mistakenly given to us. This consists of digits,
597  * the plus symbol and arabic-indic digits. This does not contain alpha
598  * characters, although they may be used later in the number. It also does not
599  * include other punctuation, as this will be stripped later during parsing and
600  * is of no information value when parsing a number.
601  *
602  * @const
603  * @type {!RegExp}
604  * @private
605  */
606 i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN_ =
607     new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ +
608                i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']');
609
610
611 /**
612  * Regular expression of characters typically used to start a second phone
613  * number for the purposes of parsing. This allows us to strip off parts of the
614  * number that are actually the start of another number, such as for:
615  * (530) 583-6985 x302/x2303 -> the second extension here makes this actually
616  * two phone numbers, (530) 583-6985 x302 and (530) 583-6985 x2303. We remove
617  * the second extension so that the first number is parsed correctly.
618  *
619  * @const
620  * @type {!RegExp}
621  * @private
622  */
623 i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_ = /[\\\/] *x/;
624
625
626 /**
627  * Regular expression of trailing characters that we want to remove. We remove
628  * all characters that are not alpha or numerical characters. The hash character
629  * is retained here, as it may signify the previous block was an extension.
630  *
631  * @const
632  * @type {!RegExp}
633  * @private
634  */
635 i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_ =
636     new RegExp('[^' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ +
637                i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ + '#]+$');
638
639
640 /**
641  * We use this pattern to check if the phone number has at least three letters
642  * in it - if so, then we treat it as a number where some phone-number digits
643  * are represented by letters.
644  *
645  * @const
646  * @type {!RegExp}
647  * @private
648  */
649 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_ =
650     /(?:.*?[A-Za-z]){3}.*/;
651
652
653 /**
654  * Regular expression of viable phone numbers. This is location independent.
655  * Checks we have at least three leading digits, and only valid punctuation,
656  * alpha characters and digits in the phone number. Does not include extension
657  * data. The symbol 'x' is allowed here as valid punctuation since it is often
658  * used as a placeholder for carrier codes, for example in Brazilian phone
659  * numbers. We also allow multiple '+' characters at the start.
660  * Corresponds to the following:
661  * [digits]{minLengthNsn}|
662  * plus_sign*
663  * (([punctuation]|[star])*[digits]){3,}([punctuation]|[star]|[digits]|[alpha])*
664  *
665  * The first reg-ex is to allow short numbers (two digits long) to be parsed if
666  * they are entered as "15" etc, but only if there is no punctuation in them.
667  * The second expression restricts the number of digits to three or more, but
668  * then allows them to be in international form, and to have alpha-characters
669  * and punctuation. We split up the two reg-exes here and combine them when
670  * creating the reg-ex VALID_PHONE_NUMBER_PATTERN_ itself so we can prefix it
671  * with ^ and append $ to each branch.
672  *
673  * Note VALID_PUNCTUATION starts with a -, so must be the first in the range.
674  *
675  * @const
676  * @type {string}
677  * @private
678  */
679 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_PHONE_NUMBER_PATTERN_ =
680     '[' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{' +
681     i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_ + '}';
682
683
684 /**
685  * See MIN_LENGTH_PHONE_NUMBER_PATTERN_ for a full description of this reg-exp.
686  *
687  * @const
688  * @type {string}
689  * @private
690  */
691 i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ =
692     '[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']*(?:[' +
693     i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION +
694     i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ + ']*[' +
695     i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']){3,}[' +
696     i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION +
697     i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ +
698     i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ +
699     i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']*';
700
701
702 /**
703  * Default extension prefix to use when formatting. This will be put in front of
704  * any extension component of the number, after the main national number is
705  * formatted. For example, if you wish the default extension formatting to be
706  * ' extn: 3456', then you should specify ' extn: ' here as the default
707  * extension prefix. This can be overridden by region-specific preferences.
708  *
709  * @const
710  * @type {string}
711  * @private
712  */
713 i18n.phonenumbers.PhoneNumberUtil.DEFAULT_EXTN_PREFIX_ = ' ext. ';
714
715
716 /**
717  * Pattern to capture digits used in an extension.
718  * Places a maximum length of '7' for an extension.
719  *
720  * @const
721  * @type {string}
722  * @private
723  */
724 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ =
725     '([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,7})';
726
727
728 /**
729  * Regexp of all possible ways to write extensions, for use when parsing. This
730  * will be run as a case-insensitive regexp match. Wide character versions are
731  * also provided after each ASCII version. There are three regular expressions
732  * here. The first covers RFC 3966 format, where the extension is added using
733  * ';ext='. The second more generic one starts with optional white space and
734  * ends with an optional full stop (.), followed by zero or more spaces/tabs and
735  * then the numbers themselves. The other one covers the special case of
736  * American numbers where the extension is written with a hash at the end, such
737  * as '- 503#'. Note that the only capturing groups should be around the digits
738  * that you want to capture as part of the extension, or else parsing will fail!
739  * We allow two options for representing the accented o - the character itself,
740  * and one in the unicode decomposed form with the combining acute accent.
741  *
742  * @const
743  * @type {string}
744  * @private
745  */
746 i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ =
747     i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
748     i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '|' +
749     '[ \u00A0\\t,]*' +
750     '(?:e?xt(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45?\uFF58\uFF54\uFF4E?|' +
751     '[,x\uFF58#\uFF03~\uFF5E]|int|anexo|\uFF49\uFF4E\uFF54)' +
752     '[:\\.\uFF0E]?[ \u00A0\\t,-]*' +
753     i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '#?|' +
754     '[- ]+([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,5})#';
755
756
757 /**
758  * Regexp of all known extension prefixes used by different regions followed by
759  * 1 or more valid digits, for use when parsing.
760  *
761  * @const
762  * @type {!RegExp}
763  * @private
764  */
765 i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_ =
766     new RegExp('(?:' +
767                i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ +
768                ')$', 'i');
769
770
771 /**
772  * We append optionally the extension pattern to the end here, as a valid phone
773  * number may have an extension prefix appended, followed by 1 or more digits.
774  *
775  * @const
776  * @type {!RegExp}
777  * @private
778  */
779 i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_ =
780     new RegExp(
781         '^' +
782         i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_PHONE_NUMBER_PATTERN_ +
783         '$|' +
784         '^' + i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ +
785         '(?:' + i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ +
786         ')?' + '$', 'i');
787
788
789 /**
790  * @const
791  * @type {!RegExp}
792  * @private
793  */
794 i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_ = /\D+/;
795
796
797 /**
798  * This was originally set to $1 but there are some countries for which the
799  * first group is not used in the national pattern (e.g. Argentina) so the $1
800  * group does not match correctly.  Therefore, we use \d, so that the first
801  * group actually used in the pattern will be matched.
802  * @const
803  * @type {!RegExp}
804  * @private
805  */
806 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_ = /(\$\d)/;
807
808
809 /**
810  * @const
811  * @type {!RegExp}
812  * @private
813  */
814 i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_ = /\$NP/;
815
816
817 /**
818  * @const
819  * @type {!RegExp}
820  * @private
821  */
822 i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_ = /\$FG/;
823
824
825 /**
826  * @const
827  * @type {!RegExp}
828  * @private
829  */
830 i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_ = /\$CC/;
831
832
833 /**
834  * A pattern that is used to determine if the national prefix formatting rule
835  * has the first group only, i.e., does not start with the national prefix.
836  * Note that the pattern explicitly allows for unbalanced parentheses.
837  * @const
838  * @type {!RegExp}
839  * @private
840  */
841 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_ONLY_PREFIX_PATTERN_ =
842     /^\(?\$1\)?$/;
843
844
845 /**
846  * @const
847  * @type {string}
848  */
849 i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY = '001';
850
851
852 /**
853  * INTERNATIONAL and NATIONAL formats are consistent with the definition in
854  * ITU-T Recommendation E123. For example, the number of the Google Switzerland
855  * office will be written as '+41 44 668 1800' in INTERNATIONAL format, and as
856  * '044 668 1800' in NATIONAL format. E164 format is as per INTERNATIONAL format
857  * but with no formatting applied, e.g. '+41446681800'. RFC3966 is as per
858  * INTERNATIONAL format, but with all spaces and other separating symbols
859  * replaced with a hyphen, and with any phone number extension appended with
860  * ';ext='. It also will have a prefix of 'tel:' added, e.g.
861  * 'tel:+41-44-668-1800'.
862  *
863  * Note: If you are considering storing the number in a neutral format, you are
864  * highly advised to use the PhoneNumber class.
865  * @enum {number}
866  */
867 i18n.phonenumbers.PhoneNumberFormat = {
868   E164: 0,
869   INTERNATIONAL: 1,
870   NATIONAL: 2,
871   RFC3966: 3
872 };
873
874
875 /**
876  * Type of phone numbers.
877  *
878  * @enum {number}
879  */
880 i18n.phonenumbers.PhoneNumberType = {
881   FIXED_LINE: 0,
882   MOBILE: 1,
883   // In some regions (e.g. the USA), it is impossible to distinguish between
884   // fixed-line and mobile numbers by looking at the phone number itself.
885   FIXED_LINE_OR_MOBILE: 2,
886   // Freephone lines
887   TOLL_FREE: 3,
888   PREMIUM_RATE: 4,
889   // The cost of this call is shared between the caller and the recipient, and
890   // is hence typically less than PREMIUM_RATE calls. See
891   // http://en.wikipedia.org/wiki/Shared_Cost_Service for more information.
892   SHARED_COST: 5,
893   // Voice over IP numbers. This includes TSoIP (Telephony Service over IP).
894   VOIP: 6,
895   // A personal number is associated with a particular person, and may be routed
896   // to either a MOBILE or FIXED_LINE number. Some more information can be found
897   // here: http://en.wikipedia.org/wiki/Personal_Numbers
898   PERSONAL_NUMBER: 7,
899   PAGER: 8,
900   // Used for 'Universal Access Numbers' or 'Company Numbers'. They may be
901   // further routed to specific offices, but allow one number to be used for a
902   // company.
903   UAN: 9,
904   // Used for 'Voice Mail Access Numbers'.
905   VOICEMAIL: 10,
906   // A phone number is of type UNKNOWN when it does not fit any of the known
907   // patterns for a specific region.
908   UNKNOWN: -1
909 };
910
911
912 /**
913  * Types of phone number matches. See detailed description beside the
914  * isNumberMatch() method.
915  *
916  * @enum {number}
917  */
918 i18n.phonenumbers.PhoneNumberUtil.MatchType = {
919   NOT_A_NUMBER: 0,
920   NO_MATCH: 1,
921   SHORT_NSN_MATCH: 2,
922   NSN_MATCH: 3,
923   EXACT_MATCH: 4
924 };
925
926
927 /**
928  * Possible outcomes when testing if a PhoneNumber is possible.
929  *
930  * @enum {number}
931  */
932 i18n.phonenumbers.PhoneNumberUtil.ValidationResult = {
933   IS_POSSIBLE: 0,
934   INVALID_COUNTRY_CODE: 1,
935   TOO_SHORT: 2,
936   TOO_LONG: 3
937 };
938
939
940 /**
941  * Attempts to extract a possible number from the string passed in. This
942  * currently strips all leading characters that cannot be used to start a phone
943  * number. Characters that can be used to start a phone number are defined in
944  * the VALID_START_CHAR_PATTERN. If none of these characters are found in the
945  * number passed in, an empty string is returned. This function also attempts to
946  * strip off any alternative extensions or endings if two or more are present,
947  * such as in the case of: (530) 583-6985 x302/x2303. The second extension here
948  * makes this actually two phone numbers, (530) 583-6985 x302 and (530) 583-6985
949  * x2303. We remove the second extension so that the first number is parsed
950  * correctly.
951  *
952  * @param {string} number the string that might contain a phone number.
953  * @return {string} the number, stripped of any non-phone-number prefix (such as
954  *     'Tel:') or an empty string if no character used to start phone numbers
955  *     (such as + or any digit) is found in the number.
956  */
957 i18n.phonenumbers.PhoneNumberUtil.extractPossibleNumber = function(number) {
958   /** @type {string} */
959   var possibleNumber;
960
961   /** @type {number} */
962   var start = number
963       .search(i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN_);
964   if (start >= 0) {
965     possibleNumber = number.substring(start);
966     // Remove trailing non-alpha non-numerical characters.
967     possibleNumber = possibleNumber.replace(
968         i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_, '');
969
970     // Check for extra numbers at the end.
971     /** @type {number} */
972     var secondNumberStart = possibleNumber
973         .search(i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_);
974     if (secondNumberStart >= 0) {
975       possibleNumber = possibleNumber.substring(0, secondNumberStart);
976     }
977   } else {
978     possibleNumber = '';
979   }
980   return possibleNumber;
981 };
982
983
984 /**
985  * Checks to see if the string of characters could possibly be a phone number at
986  * all. At the moment, checks to see that the string begins with at least 2
987  * digits, ignoring any punctuation commonly found in phone numbers. This method
988  * does not require the number to be normalized in advance - but does assume
989  * that leading non-number symbols have been removed, such as by the method
990  * extractPossibleNumber.
991  *
992  * @param {string} number string to be checked for viability as a phone number.
993  * @return {boolean} true if the number could be a phone number of some sort,
994  *     otherwise false.
995  */
996 i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber = function(number) {
997   if (number.length < i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
998     return false;
999   }
1000   return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
1001       i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_, number);
1002 };
1003
1004
1005 /**
1006  * Normalizes a string of characters representing a phone number. This performs
1007  * the following conversions:
1008  *   Punctuation is stripped.
1009  *   For ALPHA/VANITY numbers:
1010  *   Letters are converted to their numeric representation on a telephone
1011  *       keypad. The keypad used here is the one defined in ITU Recommendation
1012  *       E.161. This is only done if there are 3 or more letters in the number,
1013  *       to lessen the risk that such letters are typos.
1014  *   For other numbers:
1015  *   Wide-ascii digits are converted to normal ASCII (European) digits.
1016  *   Arabic-Indic numerals are converted to European numerals.
1017  *   Spurious alpha characters are stripped.
1018  *
1019  * @param {string} number a string of characters representing a phone number.
1020  * @return {string} the normalized string version of the phone number.
1021  */
1022 i18n.phonenumbers.PhoneNumberUtil.normalize = function(number) {
1023   if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
1024       i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_, number)) {
1025     return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
1026         i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_, true);
1027   } else {
1028     return i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(number);
1029   }
1030 };
1031
1032
1033 /**
1034  * Normalizes a string of characters representing a phone number. This is a
1035  * wrapper for normalize(String number) but does in-place normalization of the
1036  * StringBuffer provided.
1037  *
1038  * @param {!goog.string.StringBuffer} number a StringBuffer of characters
1039  *     representing a phone number that will be normalized in place.
1040  * @private
1041  */
1042 i18n.phonenumbers.PhoneNumberUtil.normalizeSB_ = function(number) {
1043   /** @type {string} */
1044   var normalizedNumber = i18n.phonenumbers.PhoneNumberUtil.normalize(number
1045       .toString());
1046   number.clear();
1047   number.append(normalizedNumber);
1048 };
1049
1050
1051 /**
1052  * Normalizes a string of characters representing a phone number. This converts
1053  * wide-ascii and arabic-indic numerals to European numerals, and strips
1054  * punctuation and alpha characters.
1055  *
1056  * @param {string} number a string of characters representing a phone number.
1057  * @return {string} the normalized string version of the phone number.
1058  */
1059 i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly = function(number) {
1060   return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
1061       i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS, true);
1062 };
1063
1064
1065 /**
1066  * Converts all alpha characters in a number to their respective digits on a
1067  * keypad, but retains existing formatting. Also converts wide-ascii digits to
1068  * normal ascii digits, and converts Arabic-Indic numerals to European numerals.
1069  *
1070  * @param {string} number a string of characters representing a phone number.
1071  * @return {string} the normalized string version of the phone number.
1072  */
1073 i18n.phonenumbers.PhoneNumberUtil.convertAlphaCharactersInNumber =
1074     function(number) {
1075
1076   return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
1077       i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_, false);
1078 };
1079
1080
1081 /**
1082  * Gets the length of the geographical area code from the
1083  * {@code national_number} field of the PhoneNumber object passed in, so that
1084  * clients could use it to split a national significant number into geographical
1085  * area code and subscriber number. It works in such a way that the resultant
1086  * subscriber number should be diallable, at least on some devices. An example
1087  * of how this could be used:
1088  *
1089  * <pre>
1090  * var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
1091  * var number = phoneUtil.parse('16502530000', 'US');
1092  * var nationalSignificantNumber =
1093  *     phoneUtil.getNationalSignificantNumber(number);
1094  * var areaCode;
1095  * var subscriberNumber;
1096  *
1097  * var areaCodeLength = phoneUtil.getLengthOfGeographicalAreaCode(number);
1098  * if (areaCodeLength > 0) {
1099  *   areaCode = nationalSignificantNumber.substring(0, areaCodeLength);
1100  *   subscriberNumber = nationalSignificantNumber.substring(areaCodeLength);
1101  * } else {
1102  *   areaCode = '';
1103  *   subscriberNumber = nationalSignificantNumber;
1104  * }
1105  * </pre>
1106  *
1107  * N.B.: area code is a very ambiguous concept, so the I18N team generally
1108  * recommends against using it for most purposes, but recommends using the more
1109  * general {@code national_number} instead. Read the following carefully before
1110  * deciding to use this method:
1111  * <ul>
1112  *  <li> geographical area codes change over time, and this method honors those
1113  *    changes; therefore, it doesn't guarantee the stability of the result it
1114  *    produces.
1115  *  <li> subscriber numbers may not be diallable from all devices (notably
1116  *    mobile devices, which typically requires the full national_number to be
1117  *    dialled in most regions).
1118  *  <li> most non-geographical numbers have no area codes, including numbers
1119  *    from non-geographical entities.
1120  *  <li> some geographical numbers have no area codes.
1121  * </ul>
1122  *
1123  * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber object for
1124  *     which clients want to know the length of the area code.
1125  * @return {number} the length of area code of the PhoneNumber object passed in.
1126  */
1127 i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfGeographicalAreaCode =
1128     function(number) {
1129   /** @type {i18n.phonenumbers.PhoneMetadata} */
1130   var metadata = this.getMetadataForRegion(this.getRegionCodeForNumber(number));
1131   if (metadata == null) {
1132     return 0;
1133   }
1134   // If a country doesn't use a national prefix, and this number doesn't have
1135   // an Italian leading zero, we assume it is a closed dialling plan with no
1136   // area codes.
1137   if (!metadata.hasNationalPrefix() && !number.hasItalianLeadingZero()) {
1138     return 0;
1139   }
1140
1141   if (!this.isNumberGeographical_(number)) {
1142     return 0;
1143   }
1144
1145   return this.getLengthOfNationalDestinationCode(number);
1146 };
1147
1148
1149 /**
1150  * Gets the length of the national destination code (NDC) from the PhoneNumber
1151  * object passed in, so that clients could use it to split a national
1152  * significant number into NDC and subscriber number. The NDC of a phone number
1153  * is normally the first group of digit(s) right after the country calling code
1154  * when the number is formatted in the international format, if there is a
1155  * subscriber number part that follows. An example of how this could be used:
1156  *
1157  * <pre>
1158  * var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
1159  * var number = phoneUtil.parse('18002530000', 'US');
1160  * var nationalSignificantNumber =
1161  *     phoneUtil.getNationalSignificantNumber(number);
1162  * var nationalDestinationCode;
1163  * var subscriberNumber;
1164  *
1165  * var nationalDestinationCodeLength =
1166  *     phoneUtil.getLengthOfNationalDestinationCode(number);
1167  * if (nationalDestinationCodeLength > 0) {
1168  *   nationalDestinationCode =
1169  *       nationalSignificantNumber.substring(0, nationalDestinationCodeLength);
1170  *   subscriberNumber =
1171  *       nationalSignificantNumber.substring(nationalDestinationCodeLength);
1172  * } else {
1173  *   nationalDestinationCode = '';
1174  *   subscriberNumber = nationalSignificantNumber;
1175  * }
1176  * </pre>
1177  *
1178  * Refer to the unittests to see the difference between this function and
1179  * {@link #getLengthOfGeographicalAreaCode}.
1180  *
1181  * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber object for
1182  *     which clients want to know the length of the NDC.
1183  * @return {number} the length of NDC of the PhoneNumber object passed in.
1184  */
1185 i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfNationalDestinationCode =
1186     function(number) {
1187
1188   /** @type {i18n.phonenumbers.PhoneNumber} */
1189   var copiedProto;
1190   if (number.hasExtension()) {
1191     // We don't want to alter the proto given to us, but we don't want to
1192     // include the extension when we format it, so we copy it and clear the
1193     // extension here.
1194     copiedProto = number.clone();
1195     copiedProto.clearExtension();
1196   } else {
1197     copiedProto = number;
1198   }
1199
1200   /** @type {string} */
1201   var nationalSignificantNumber = this.format(copiedProto,
1202       i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1203   /** @type {!Array.<string>} */
1204   var numberGroups = nationalSignificantNumber.split(
1205       i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_);
1206   // The pattern will start with '+COUNTRY_CODE ' so the first group will always
1207   // be the empty string (before the + symbol) and the second group will be the
1208   // country calling code. The third group will be area code if it is not the
1209   // last group.
1210   // NOTE: On IE the first group that is supposed to be the empty string does
1211   // not appear in the array of number groups... so make the result on non-IE
1212   // browsers to be that of IE.
1213   if (numberGroups[0].length == 0) {
1214     numberGroups.shift();
1215   }
1216   if (numberGroups.length <= 2) {
1217     return 0;
1218   }
1219
1220   if (this.getRegionCodeForCountryCode(number.getCountryCodeOrDefault()) ==
1221       'AR' &&
1222       this.getNumberType(number) == i18n.phonenumbers.PhoneNumberType.MOBILE) {
1223     // Argentinian mobile numbers, when formatted in the international format,
1224     // are in the form of +54 9 NDC XXXX.... As a result, we take the length of
1225     // the third group (NDC) and add 1 for the digit 9, which also forms part of
1226     // the national significant number.
1227     //
1228     // TODO: Investigate the possibility of better modeling the metadata to make
1229     // it easier to obtain the NDC.
1230     return numberGroups[2].length + 1;
1231   }
1232   return numberGroups[1].length;
1233 };
1234
1235
1236 /**
1237  * Normalizes a string of characters representing a phone number by replacing
1238  * all characters found in the accompanying map with the values therein, and
1239  * stripping all other characters if removeNonMatches is true.
1240  *
1241  * @param {string} number a string of characters representing a phone number.
1242  * @param {!Object.<string, string>} normalizationReplacements a mapping of
1243  *     characters to what they should be replaced by in the normalized version
1244  *     of the phone number.
1245  * @param {boolean} removeNonMatches indicates whether characters that are not
1246  *     able to be replaced should be stripped from the number. If this is false,
1247  *     they will be left unchanged in the number.
1248  * @return {string} the normalized string version of the phone number.
1249  * @private
1250  */
1251 i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_ =
1252     function(number, normalizationReplacements, removeNonMatches) {
1253
1254   /** @type {!goog.string.StringBuffer} */
1255   var normalizedNumber = new goog.string.StringBuffer();
1256   /** @type {string} */
1257   var character;
1258   /** @type {string} */
1259   var newDigit;
1260   /** @type {number} */
1261   var numberLength = number.length;
1262   for (var i = 0; i < numberLength; ++i) {
1263     character = number.charAt(i);
1264     newDigit = normalizationReplacements[character.toUpperCase()];
1265     if (newDigit != null) {
1266       normalizedNumber.append(newDigit);
1267     } else if (!removeNonMatches) {
1268       normalizedNumber.append(character);
1269     }
1270     // If neither of the above are true, we remove this character.
1271   }
1272   return normalizedNumber.toString();
1273 };
1274
1275
1276 /**
1277  * Helper function to check if the national prefix formatting rule has the first
1278  * group only, i.e., does not start with the national prefix.
1279  *
1280  * @param {string} nationalPrefixFormattingRule The formatting rule for the
1281  *     national prefix.
1282  * @return {boolean} true if the national prefix formatting rule has the first
1283  *     group only.
1284  */
1285 i18n.phonenumbers.PhoneNumberUtil.prototype.formattingRuleHasFirstGroupOnly =
1286     function(nationalPrefixFormattingRule) {
1287   return i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_ONLY_PREFIX_PATTERN_.
1288       test(nationalPrefixFormattingRule);
1289 };
1290
1291
1292 /**
1293  * Tests whether a phone number has a geographical association. It checks if
1294  * the number is associated to a certain region in the country where it belongs
1295  * to. Note that this doesn't verify if the number is actually in use.
1296  *
1297  * @param {i18n.phonenumbers.PhoneNumber} phoneNumber The phone number to test.
1298  * @return {boolean} true if the phone number has a geographical association.
1299  * @private
1300  */
1301 i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberGeographical_ =
1302     function(phoneNumber) {
1303   /** @type {i18n.phonenumbers.PhoneNumberType} */
1304   var numberType = this.getNumberType(phoneNumber);
1305   // TODO: Include mobile phone numbers from countries like Indonesia, which
1306   // has some mobile numbers that are geographical.
1307   return numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE ||
1308       numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
1309 };
1310
1311
1312 /**
1313  * Helper function to check region code is not unknown or null.
1314  *
1315  * @param {?string} regionCode the ISO 3166-1 two-letter region code.
1316  * @return {boolean} true if region code is valid.
1317  * @private
1318  */
1319 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidRegionCode_ =
1320     function(regionCode) {
1321
1322   // In Java we check whether the regionCode is contained in supportedRegions
1323   // that is built out of all the values of countryCallingCodeToRegionCodeMap
1324   // (countryCodeToRegionCodeMap in JS) minus REGION_CODE_FOR_NON_GEO_ENTITY.
1325   // In JS we check whether the regionCode is contained in the keys of
1326   // countryToMetadata but since for non-geographical country calling codes
1327   // (e.g. +800) we use the country calling codes instead of the region code as
1328   // key in the map we have to make sure regionCode is not a number to prevent
1329   // returning true for non-geographical country calling codes.
1330   return regionCode != null &&
1331       isNaN(regionCode) &&
1332       regionCode.toUpperCase() in i18n.phonenumbers.metadata.countryToMetadata;
1333 };
1334
1335
1336 /**
1337  * Helper function to check the country calling code is valid.
1338  *
1339  * @param {number} countryCallingCode the country calling code.
1340  * @return {boolean} true if country calling code code is valid.
1341  * @private
1342  */
1343 i18n.phonenumbers.PhoneNumberUtil.prototype.hasValidCountryCallingCode_ =
1344     function(countryCallingCode) {
1345
1346   return countryCallingCode in
1347       i18n.phonenumbers.metadata.countryCodeToRegionCodeMap;
1348 };
1349
1350
1351 /**
1352  * Formats a phone number in the specified format using default rules. Note that
1353  * this does not promise to produce a phone number that the user can dial from
1354  * where they are - although we do format in either 'national' or
1355  * 'international' format depending on what the client asks for, we do not
1356  * currently support a more abbreviated format, such as for users in the same
1357  * 'area' who could potentially dial the number without area code. Note that if
1358  * the phone number has a country calling code of 0 or an otherwise invalid
1359  * country calling code, we cannot work out which formatting rules to apply so
1360  * we return the national significant number with no formatting applied.
1361  *
1362  * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1363  *     formatted.
1364  * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1365  *     phone number should be formatted into.
1366  * @return {string} the formatted phone number.
1367  */
1368 i18n.phonenumbers.PhoneNumberUtil.prototype.format =
1369     function(number, numberFormat) {
1370
1371   if (number.getNationalNumber() == 0 && number.hasRawInput()) {
1372     // Unparseable numbers that kept their raw input just use that.
1373     // This is the only case where a number can be formatted as E164 without a
1374     // leading '+' symbol (but the original number wasn't parseable anyway).
1375     // TODO: Consider removing the 'if' above so that unparseable strings
1376     // without raw input format to the empty string instead of "+00"
1377     /** @type {string} */
1378     var rawInput = number.getRawInputOrDefault();
1379     if (rawInput.length > 0) {
1380       return rawInput;
1381     }
1382   }
1383   /** @type {number} */
1384   var countryCallingCode = number.getCountryCodeOrDefault();
1385   /** @type {string} */
1386   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1387   if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.E164) {
1388     // Early exit for E164 case (even if the country calling code is invalid)
1389     // since no formatting of the national number needs to be applied.
1390     // Extensions are not formatted.
1391     return this.prefixNumberWithCountryCallingCode_(
1392         countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.E164,
1393         nationalSignificantNumber, '');
1394   }
1395   if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1396     return nationalSignificantNumber;
1397   }
1398   // Note getRegionCodeForCountryCode() is used because formatting information
1399   // for regions which share a country calling code is contained by only one
1400   // region for performance reasons. For example, for NANPA regions it will be
1401   // contained in the metadata for US.
1402   /** @type {string} */
1403   var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1404
1405   // Metadata cannot be null because the country calling code is valid (which
1406   // means that the region code cannot be ZZ and must be one of our supported
1407   // region codes).
1408   /** @type {i18n.phonenumbers.PhoneMetadata} */
1409   var metadata =
1410       this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1411   /** @type {string} */
1412   var formattedExtension =
1413       this.maybeGetFormattedExtension_(number, metadata, numberFormat);
1414   /** @type {string} */
1415   var formattedNationalNumber =
1416       this.formatNsn_(nationalSignificantNumber, metadata, numberFormat);
1417   return this.prefixNumberWithCountryCallingCode_(countryCallingCode,
1418                                                   numberFormat,
1419                                                   formattedNationalNumber,
1420                                                   formattedExtension);
1421 };
1422
1423
1424 /**
1425  * Formats a phone number in the specified format using client-defined
1426  * formatting rules. Note that if the phone number has a country calling code of
1427  * zero or an otherwise invalid country calling code, we cannot work out things
1428  * like whether there should be a national prefix applied, or how to format
1429  * extensions, so we return the national significant number with no formatting
1430  * applied.
1431  *
1432  * @param {i18n.phonenumbers.PhoneNumber} number the phone  number to be
1433  *     formatted.
1434  * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1435  *     phone number should be formatted into.
1436  * @param {Array.<i18n.phonenumbers.NumberFormat>} userDefinedFormats formatting
1437  *     rules specified by clients.
1438  * @return {string} the formatted phone number.
1439  */
1440 i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern =
1441     function(number, numberFormat, userDefinedFormats) {
1442
1443   /** @type {number} */
1444   var countryCallingCode = number.getCountryCodeOrDefault();
1445   /** @type {string} */
1446   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1447   if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1448     return nationalSignificantNumber;
1449   }
1450   // Note getRegionCodeForCountryCode() is used because formatting information
1451   // for regions which share a country calling code is contained by only one
1452   // region for performance reasons. For example, for NANPA regions it will be
1453   // contained in the metadata for US.
1454   /** @type {string} */
1455   var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1456   // Metadata cannot be null because the country calling code is valid
1457   /** @type {i18n.phonenumbers.PhoneMetadata} */
1458   var metadata =
1459       this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1460
1461   /** @type {string} */
1462   var formattedNumber = '';
1463
1464   /** @type {i18n.phonenumbers.NumberFormat} */
1465   var formattingPattern = this.chooseFormattingPatternForNumber_(
1466       userDefinedFormats, nationalSignificantNumber);
1467   if (formattingPattern == null) {
1468     // If no pattern above is matched, we format the number as a whole.
1469     formattedNumber = nationalSignificantNumber;
1470   } else {
1471     // Before we do a replacement of the national prefix pattern $NP with the
1472     // national prefix, we need to copy the rule so that subsequent replacements
1473     // for different numbers have the appropriate national prefix.
1474     /** type {i18n.phonenumbers.NumberFormat} */
1475     var numFormatCopy = formattingPattern.clone();
1476     /** @type {string} */
1477     var nationalPrefixFormattingRule =
1478         formattingPattern.getNationalPrefixFormattingRuleOrDefault();
1479     /** @type {string} */
1480     if (nationalPrefixFormattingRule.length > 0) {
1481       var nationalPrefix = metadata.getNationalPrefixOrDefault();
1482       if (nationalPrefix.length > 0) {
1483         // Replace $NP with national prefix and $FG with the first group ($1).
1484         nationalPrefixFormattingRule = nationalPrefixFormattingRule
1485             .replace(i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_,
1486                      nationalPrefix)
1487             .replace(i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_, '$1');
1488         numFormatCopy.setNationalPrefixFormattingRule(
1489             nationalPrefixFormattingRule);
1490       } else {
1491         // We don't want to have a rule for how to format the national prefix if
1492         // there isn't one.
1493         numFormatCopy.clearNationalPrefixFormattingRule();
1494       }
1495     }
1496     formattedNumber = this.formatNsnUsingPattern_(
1497         nationalSignificantNumber, numFormatCopy, numberFormat);
1498   }
1499
1500   /** @type {string} */
1501   var formattedExtension =
1502       this.maybeGetFormattedExtension_(number, metadata, numberFormat);
1503   return this.prefixNumberWithCountryCallingCode_(countryCallingCode,
1504                                                   numberFormat,
1505                                                   formattedNumber,
1506                                                   formattedExtension);
1507 };
1508
1509
1510 /**
1511  * Formats a phone number in national format for dialing using the carrier as
1512  * specified in the {@code carrierCode}. The {@code carrierCode} will always be
1513  * used regardless of whether the phone number already has a preferred domestic
1514  * carrier code stored. If {@code carrierCode} contains an empty string, returns
1515  * the number in national format without any carrier code.
1516  *
1517  * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1518  *     formatted.
1519  * @param {string} carrierCode the carrier selection code to be used.
1520  * @return {string} the formatted phone number in national format for dialing
1521  *     using the carrier as specified in the {@code carrierCode}.
1522  */
1523 i18n.phonenumbers.PhoneNumberUtil.prototype.
1524     formatNationalNumberWithCarrierCode = function(number, carrierCode) {
1525
1526   /** @type {number} */
1527   var countryCallingCode = number.getCountryCodeOrDefault();
1528   /** @type {string} */
1529   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1530   if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1531     return nationalSignificantNumber;
1532   }
1533
1534   // Note getRegionCodeForCountryCode() is used because formatting information
1535   // for regions which share a country calling code is contained by only one
1536   // region for performance reasons. For example, for NANPA regions it will be
1537   // contained in the metadata for US.
1538   /** @type {string} */
1539   var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1540   // Metadata cannot be null because the country calling code is valid.
1541   /** @type {i18n.phonenumbers.PhoneMetadata} */
1542   var metadata =
1543       this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1544   /** @type {string} */
1545   var formattedExtension = this.maybeGetFormattedExtension_(
1546       number, metadata, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1547   /** @type {string} */
1548   var formattedNationalNumber = this.formatNsn_(
1549       nationalSignificantNumber, metadata,
1550       i18n.phonenumbers.PhoneNumberFormat.NATIONAL, carrierCode);
1551   return this.prefixNumberWithCountryCallingCode_(
1552       countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.NATIONAL,
1553       formattedNationalNumber, formattedExtension);
1554 };
1555
1556
1557 /**
1558  * @param {number} countryCallingCode
1559  * @param {?string} regionCode
1560  * @return {i18n.phonenumbers.PhoneMetadata}
1561  * @private
1562  */
1563 i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegionOrCallingCode_ =
1564     function(countryCallingCode, regionCode) {
1565   return i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY ==
1566       regionCode ?
1567       this.getMetadataForNonGeographicalRegion(countryCallingCode) :
1568       this.getMetadataForRegion(regionCode);
1569 };
1570
1571
1572 /**
1573  * Formats a phone number in national format for dialing using the carrier as
1574  * specified in the preferred_domestic_carrier_code field of the PhoneNumber
1575  * object passed in. If that is missing, use the {@code fallbackCarrierCode}
1576  * passed in instead. If there is no {@code preferred_domestic_carrier_code},
1577  * and the {@code fallbackCarrierCode} contains an empty string, return the
1578  * number in national format without any carrier code.
1579  *
1580  * <p>Use {@link #formatNationalNumberWithCarrierCode} instead if the carrier
1581  * code passed in should take precedence over the number's
1582  * {@code preferred_domestic_carrier_code} when formatting.
1583  *
1584  * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1585  *     formatted.
1586  * @param {string} fallbackCarrierCode the carrier selection code to be used, if
1587  *     none is found in the phone number itself.
1588  * @return {string} the formatted phone number in national format for dialing
1589  *     using the number's preferred_domestic_carrier_code, or the
1590  *     {@code fallbackCarrierCode} passed in if none is found.
1591  */
1592 i18n.phonenumbers.PhoneNumberUtil.prototype.
1593     formatNationalNumberWithPreferredCarrierCode = function(
1594         number, fallbackCarrierCode) {
1595   return this.formatNationalNumberWithCarrierCode(
1596       number,
1597       number.hasPreferredDomesticCarrierCode() ?
1598           number.getPreferredDomesticCarrierCodeOrDefault() :
1599           fallbackCarrierCode);
1600 };
1601
1602
1603 /**
1604  * Returns a number formatted in such a way that it can be dialed from a mobile
1605  * phone in a specific region. If the number cannot be reached from the region
1606  * (e.g. some countries block toll-free numbers from being called outside of the
1607  * country), the method returns an empty string.
1608  *
1609  * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1610  *     formatted.
1611  * @param {string} regionCallingFrom the region where the call is being placed.
1612  * @param {boolean} withFormatting whether the number should be returned with
1613  *     formatting symbols, such as spaces and dashes.
1614  * @return {string} the formatted phone number.
1615  */
1616 i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberForMobileDialing =
1617     function(number, regionCallingFrom, withFormatting) {
1618
1619   /** @type {number} */
1620   var countryCallingCode = number.getCountryCodeOrDefault();
1621   if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1622     return number.hasRawInput() ? number.getRawInputOrDefault() : '';
1623   }
1624
1625   /** @type {string} */
1626   var formattedNumber;
1627   // Clear the extension, as that part cannot normally be dialed together with
1628   // the main number.
1629   /** @type {i18n.phonenumbers.PhoneNumber} */
1630   var numberNoExt = number.clone();
1631   numberNoExt.clearExtension();
1632   /** @type {i18n.phonenumbers.PhoneNumberType} */
1633   var numberType = this.getNumberType(numberNoExt);
1634   /** @type {string} */
1635   var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1636   if (regionCode == 'CO' && regionCallingFrom == 'CO') {
1637     if (numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE) {
1638       formattedNumber = this.formatNationalNumberWithCarrierCode(
1639           numberNoExt,
1640           i18n.phonenumbers.PhoneNumberUtil
1641               .COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX_);
1642     } else {
1643       // E164 doesn't work at all when dialing within Colombia.
1644       formattedNumber = this.format(
1645           numberNoExt, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1646     }
1647   } else if (regionCode == 'PE' && regionCallingFrom == 'PE') {
1648     // In Peru, numbers cannot be dialled using E164 format from a mobile phone
1649     // for Movistar. Instead they must be dialled in national format.
1650     formattedNumber = this.format(
1651         numberNoExt, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1652   } else if (regionCode == 'BR' && regionCallingFrom == 'BR' &&
1653       ((numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE) ||
1654       (numberType == i18n.phonenumbers.PhoneNumberType.MOBILE) ||
1655       (numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE))) {
1656     formattedNumber = numberNoExt.hasPreferredDomesticCarrierCode() ?
1657         this.formatNationalNumberWithPreferredCarrierCode(numberNoExt, '') :
1658         // Brazilian fixed line and mobile numbers need to be dialed with a
1659         // carrier code when called within Brazil. Without that, most of the
1660         // carriers won't connect the call. Because of that, we return an empty
1661         // string here.
1662         '';
1663   } else if (this.canBeInternationallyDialled(numberNoExt)) {
1664     return withFormatting ?
1665         this.format(numberNoExt,
1666                     i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL) :
1667         this.format(numberNoExt, i18n.phonenumbers.PhoneNumberFormat.E164);
1668   } else {
1669     formattedNumber = (regionCallingFrom == regionCode) ?
1670         this.format(numberNoExt, i18n.phonenumbers.PhoneNumberFormat.NATIONAL) :
1671         '';
1672   }
1673   return withFormatting ?
1674       formattedNumber :
1675       i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(formattedNumber,
1676           i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_, true);
1677 };
1678
1679
1680 /**
1681  * Formats a phone number for out-of-country dialing purposes. If no
1682  * regionCallingFrom is supplied, we format the number in its INTERNATIONAL
1683  * format. If the country calling code is the same as that of the region where
1684  * the number is from, then NATIONAL formatting will be applied.
1685  *
1686  * <p>If the number itself has a country calling code of zero or an otherwise
1687  * invalid country calling code, then we return the number with no formatting
1688  * applied.
1689  *
1690  * <p>Note this function takes care of the case for calling inside of NANPA and
1691  * between Russia and Kazakhstan (who share the same country calling code). In
1692  * those cases, no international prefix is used. For regions which have multiple
1693  * international prefixes, the number in its INTERNATIONAL format will be
1694  * returned instead.
1695  *
1696  * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1697  *     formatted.
1698  * @param {string} regionCallingFrom the region where the call is being placed.
1699  * @return {string} the formatted phone number.
1700  */
1701 i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
1702     function(number, regionCallingFrom) {
1703
1704   if (!this.isValidRegionCode_(regionCallingFrom)) {
1705     return this.format(number,
1706                        i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1707   }
1708   /** @type {number} */
1709   var countryCallingCode = number.getCountryCodeOrDefault();
1710   /** @type {string} */
1711   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1712   if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1713     return nationalSignificantNumber;
1714   }
1715   if (countryCallingCode ==
1716           i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
1717     if (this.isNANPACountry(regionCallingFrom)) {
1718       // For NANPA regions, return the national format for these regions but
1719       // prefix it with the country calling code.
1720       return countryCallingCode + ' ' +
1721           this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1722     }
1723   } else if (countryCallingCode ==
1724                  this.getCountryCodeForValidRegion_(regionCallingFrom)) {
1725     // If regions share a country calling code, the country calling code need
1726     // not be dialled. This also applies when dialling within a region, so this
1727     // if clause covers both these cases. Technically this is the case for
1728     // dialling from La Reunion to other overseas departments of France (French
1729     // Guiana, Martinique, Guadeloupe), but not vice versa - so we don't cover
1730     // this edge case for now and for those cases return the version including
1731     // country calling code. Details here:
1732     // http://www.petitfute.com/voyage/225-info-pratiques-reunion
1733     return this.format(number,
1734                        i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1735   }
1736   // Metadata cannot be null because we checked 'isValidRegionCode()' above.
1737   /** @type {i18n.phonenumbers.PhoneMetadata} */
1738   var metadataForRegionCallingFrom =
1739       this.getMetadataForRegion(regionCallingFrom);
1740   /** @type {string} */
1741   var internationalPrefix =
1742       metadataForRegionCallingFrom.getInternationalPrefixOrDefault();
1743
1744   // For regions that have multiple international prefixes, the international
1745   // format of the number is returned, unless there is a preferred international
1746   // prefix.
1747   /** @type {string} */
1748   var internationalPrefixForFormatting = '';
1749   if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
1750       i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
1751       internationalPrefix)) {
1752     internationalPrefixForFormatting = internationalPrefix;
1753   } else if (metadataForRegionCallingFrom.hasPreferredInternationalPrefix()) {
1754     internationalPrefixForFormatting =
1755         metadataForRegionCallingFrom.getPreferredInternationalPrefixOrDefault();
1756   }
1757
1758   /** @type {string} */
1759   var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1760   // Metadata cannot be null because the country calling code is valid.
1761   /** @type {i18n.phonenumbers.PhoneMetadata} */
1762   var metadataForRegion =
1763       this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1764   /** @type {string} */
1765   var formattedNationalNumber = this.formatNsn_(
1766       nationalSignificantNumber, metadataForRegion,
1767       i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1768   /** @type {string} */
1769   var formattedExtension = this.maybeGetFormattedExtension_(number,
1770       metadataForRegion, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1771   return internationalPrefixForFormatting.length > 0 ?
1772       internationalPrefixForFormatting + ' ' + countryCallingCode + ' ' +
1773           formattedNationalNumber + formattedExtension :
1774       this.prefixNumberWithCountryCallingCode_(
1775           countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL,
1776           formattedNationalNumber, formattedExtension);
1777 };
1778
1779
1780 /**
1781  * Formats a phone number using the original phone number format that the number
1782  * is parsed from. The original format is embedded in the country_code_source
1783  * field of the PhoneNumber object passed in. If such information is missing,
1784  * the number will be formatted into the NATIONAL format by default. When the
1785  * number contains a leading zero and this is unexpected for this country, or we
1786  * don't have a formatting pattern for the number, the method returns the raw
1787  * input when it is available.
1788  *
1789  * Note this method guarantees no digit will be inserted, removed or modified as
1790  * a result of formatting.
1791  *
1792  * @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to
1793  *     be formatted in its original number format.
1794  * @param {string} regionCallingFrom the region whose IDD needs to be prefixed
1795  *     if the original number has one.
1796  * @return {string} the formatted phone number in its original number format.
1797  */
1798 i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat =
1799     function(number, regionCallingFrom) {
1800
1801   if (number.hasRawInput() &&
1802       (this.hasUnexpectedItalianLeadingZero_(number) ||
1803        !this.hasFormattingPatternForNumber_(number))) {
1804     // We check if we have the formatting pattern because without that, we might
1805     // format the number as a group without national prefix.
1806     return number.getRawInputOrDefault();
1807   }
1808   if (!number.hasCountryCodeSource()) {
1809     return this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1810   }
1811   /** @type {string} */
1812   var formattedNumber;
1813   switch (number.getCountryCodeSource()) {
1814     case i18n.phonenumbers.PhoneNumber.CountryCodeSource
1815         .FROM_NUMBER_WITH_PLUS_SIGN:
1816       formattedNumber = this.format(number,
1817           i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1818       break;
1819     case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD:
1820       formattedNumber =
1821           this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
1822       break;
1823     case i18n.phonenumbers.PhoneNumber.CountryCodeSource
1824         .FROM_NUMBER_WITHOUT_PLUS_SIGN:
1825       formattedNumber = this.format(number,
1826           i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL).substring(1);
1827       break;
1828     case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY:
1829       // Fall-through to default case.
1830     default:
1831       /** @type {string} */
1832       var regionCode =
1833           this.getRegionCodeForCountryCode(number.getCountryCodeOrDefault());
1834       // We strip non-digits from the NDD here, and from the raw input later,
1835       // so that we can compare them easily.
1836       /** @type {?string} */
1837       var nationalPrefix = this.getNddPrefixForRegion(regionCode, true);
1838       /** @type {string} */
1839       var nationalFormat =
1840           this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1841       if (nationalPrefix == null || nationalPrefix.length == 0) {
1842         // If the region doesn't have a national prefix at all, we can safely
1843         // return the national format without worrying about a national prefix
1844         // being added.
1845         formattedNumber = nationalFormat;
1846         break;
1847       }
1848       // Otherwise, we check if the original number was entered with a national
1849       // prefix.
1850       if (this.rawInputContainsNationalPrefix_(
1851           number.getRawInputOrDefault(), nationalPrefix, regionCode)) {
1852         // If so, we can safely return the national format.
1853         formattedNumber = nationalFormat;
1854         break;
1855       }
1856       // Metadata cannot be null here because getNddPrefixForRegion() (above)
1857       // returns null if there is no metadata for the region.
1858       /** @type {i18n.phonenumbers.PhoneMetadata} */
1859       var metadata = this.getMetadataForRegion(regionCode);
1860       /** @type {string} */
1861       var nationalNumber = this.getNationalSignificantNumber(number);
1862       /** @type {i18n.phonenumbers.NumberFormat} */
1863       var formatRule = this.chooseFormattingPatternForNumber_(
1864           metadata.numberFormatArray(), nationalNumber);
1865       // The format rule could still be null here if the national number was 0
1866       // and there was no raw input (this should not be possible for numbers
1867       // generated by the phonenumber library as they would also not have a
1868       // country calling code and we would have exited earlier).
1869       if (formatRule == null) {
1870         formattedNumber = nationalFormat;
1871         break;
1872       }
1873       // When the format we apply to this number doesn't contain national
1874       // prefix, we can just return the national format.
1875       // TODO: Refactor the code below with the code in
1876       // isNationalPrefixPresentIfRequired.
1877       /** @type {string} */
1878       var candidateNationalPrefixRule =
1879           formatRule.getNationalPrefixFormattingRuleOrDefault();
1880       // We assume that the first-group symbol will never be _before_ the
1881       // national prefix.
1882       /** @type {number} */
1883       var indexOfFirstGroup = candidateNationalPrefixRule.indexOf('$1');
1884       if (indexOfFirstGroup <= 0) {
1885         formattedNumber = nationalFormat;
1886         break;
1887       }
1888       candidateNationalPrefixRule =
1889           candidateNationalPrefixRule.substring(0, indexOfFirstGroup);
1890       candidateNationalPrefixRule = i18n.phonenumbers.PhoneNumberUtil
1891           .normalizeDigitsOnly(candidateNationalPrefixRule);
1892       if (candidateNationalPrefixRule.length == 0) {
1893         // National prefix not used when formatting this number.
1894         formattedNumber = nationalFormat;
1895         break;
1896       }
1897       // Otherwise, we need to remove the national prefix from our output.
1898       /** @type {i18n.phonenumbers.NumberFormat} */
1899       var numFormatCopy = formatRule.clone();
1900       numFormatCopy.clearNationalPrefixFormattingRule();
1901       formattedNumber = this.formatByPattern(number,
1902           i18n.phonenumbers.PhoneNumberFormat.NATIONAL, [numFormatCopy]);
1903       break;
1904   }
1905   /** @type {string} */
1906   var rawInput = number.getRawInputOrDefault();
1907   // If no digit is inserted/removed/modified as a result of our formatting, we
1908   // return the formatted phone number; otherwise we return the raw input the
1909   // user entered.
1910   if (formattedNumber != null && rawInput.length > 0) {
1911     /** @type {string} */
1912     var normalizedFormattedNumber =
1913         i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(formattedNumber,
1914             i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
1915             true /* remove non matches */);
1916     /** @type {string} */
1917     var normalizedRawInput =
1918         i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(rawInput,
1919             i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
1920             true /* remove non matches */);
1921     if (normalizedFormattedNumber != normalizedRawInput) {
1922       formattedNumber = rawInput;
1923     }
1924   }
1925   return formattedNumber;
1926 };
1927
1928
1929 /**
1930  * Check if rawInput, which is assumed to be in the national format, has a
1931  * national prefix. The national prefix is assumed to be in digits-only form.
1932  * @param {string} rawInput
1933  * @param {string} nationalPrefix
1934  * @param {string} regionCode
1935  * @return {boolean}
1936  * @private
1937  */
1938 i18n.phonenumbers.PhoneNumberUtil.prototype.rawInputContainsNationalPrefix_ =
1939     function(rawInput, nationalPrefix, regionCode) {
1940
1941   /** @type {string} */
1942   var normalizedNationalNumber =
1943       i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(rawInput);
1944   if (goog.string.startsWith(normalizedNationalNumber, nationalPrefix)) {
1945     try {
1946       // Some Japanese numbers (e.g. 00777123) might be mistaken to contain the
1947       // national prefix when written without it (e.g. 0777123) if we just do
1948       // prefix matching. To tackle that, we check the validity of the number if
1949       // the assumed national prefix is removed (777123 won't be valid in
1950       // Japan).
1951       return this.isValidNumber(
1952           this.parse(normalizedNationalNumber.substring(nationalPrefix.length),
1953                      regionCode));
1954     } catch (e) {
1955       return false;
1956     }
1957   }
1958   return false;
1959 };
1960
1961
1962 /**
1963  * Returns true if a number is from a region whose national significant number
1964  * couldn't contain a leading zero, but has the italian_leading_zero field set
1965  * to true.
1966  * @param {i18n.phonenumbers.PhoneNumber} number
1967  * @return {boolean}
1968  * @private
1969  */
1970 i18n.phonenumbers.PhoneNumberUtil.prototype.hasUnexpectedItalianLeadingZero_ =
1971     function(number) {
1972
1973   return number.hasItalianLeadingZero() &&
1974       !this.isLeadingZeroPossible(number.getCountryCodeOrDefault());
1975 };
1976
1977
1978 /**
1979  * @param {i18n.phonenumbers.PhoneNumber} number
1980  * @return {boolean}
1981  * @private
1982  */
1983 i18n.phonenumbers.PhoneNumberUtil.prototype.hasFormattingPatternForNumber_ =
1984     function(number) {
1985
1986   /** @type {number} */
1987   var countryCallingCode = number.getCountryCodeOrDefault();
1988   /** @type {string} */
1989   var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCallingCode);
1990   /** @type {i18n.phonenumbers.PhoneMetadata} */
1991   var metadata = this.getMetadataForRegionOrCallingCode_(
1992       countryCallingCode, phoneNumberRegion);
1993   if (metadata == null) {
1994     return false;
1995   }
1996   /** @type {string} */
1997   var nationalNumber = this.getNationalSignificantNumber(number);
1998   /** @type {i18n.phonenumbers.NumberFormat} */
1999   var formatRule = this.chooseFormattingPatternForNumber_(
2000       metadata.numberFormatArray(), nationalNumber);
2001   return formatRule != null;
2002 };
2003
2004
2005 /**
2006  * Formats a phone number for out-of-country dialing purposes.
2007  *
2008  * Note that in this version, if the number was entered originally using alpha
2009  * characters and this version of the number is stored in raw_input, this
2010  * representation of the number will be used rather than the digit
2011  * representation. Grouping information, as specified by characters such as '-'
2012  * and ' ', will be retained.
2013  *
2014  * <p><b>Caveats:</b></p>
2015  * <ul>
2016  * <li>This will not produce good results if the country calling code is both
2017  * present in the raw input _and_ is the start of the national number. This is
2018  * not a problem in the regions which typically use alpha numbers.
2019  * <li>This will also not produce good results if the raw input has any grouping
2020  * information within the first three digits of the national number, and if the
2021  * function needs to strip preceding digits/words in the raw input before these
2022  * digits. Normally people group the first three digits together so this is not
2023  * a huge problem - and will be fixed if it proves to be so.
2024  * </ul>
2025  *
2026  * @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to
2027  *     be formatted.
2028  * @param {string} regionCallingFrom the region where the call is being placed.
2029  * @return {string} the formatted phone number.
2030  */
2031 i18n.phonenumbers.PhoneNumberUtil.prototype.
2032     formatOutOfCountryKeepingAlphaChars = function(number, regionCallingFrom) {
2033   /** @type {string} */
2034   var rawInput = number.getRawInputOrDefault();
2035   // If there is no raw input, then we can't keep alpha characters because there
2036   // aren't any. In this case, we return formatOutOfCountryCallingNumber.
2037   if (rawInput.length == 0) {
2038     return this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
2039   }
2040   /** @type {number} */
2041   var countryCode = number.getCountryCodeOrDefault();
2042   if (!this.hasValidCountryCallingCode_(countryCode)) {
2043     return rawInput;
2044   }
2045   // Strip any prefix such as country calling code, IDD, that was present. We do
2046   // this by comparing the number in raw_input with the parsed number. To do
2047   // this, first we normalize punctuation. We retain number grouping symbols
2048   // such as ' ' only.
2049   rawInput = i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(
2050       rawInput,
2051       i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_,
2052       true);
2053   // Now we trim everything before the first three digits in the parsed number.
2054   // We choose three because all valid alpha numbers have 3 digits at the start
2055   // - if it does not, then we don't trim anything at all. Similarly, if the
2056   // national number was less than three digits, we don't trim anything at all.
2057   /** @type {string} */
2058   var nationalNumber = this.getNationalSignificantNumber(number);
2059   if (nationalNumber.length > 3) {
2060     /** @type {number} */
2061     var firstNationalNumberDigit =
2062         rawInput.indexOf(nationalNumber.substring(0, 3));
2063     if (firstNationalNumberDigit != -1) {
2064       rawInput = rawInput.substring(firstNationalNumberDigit);
2065     }
2066   }
2067   /** @type {i18n.phonenumbers.PhoneMetadata} */
2068   var metadataForRegionCallingFrom =
2069       this.getMetadataForRegion(regionCallingFrom);
2070   if (countryCode == i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
2071     if (this.isNANPACountry(regionCallingFrom)) {
2072       return countryCode + ' ' + rawInput;
2073     }
2074   } else if (metadataForRegionCallingFrom != null &&
2075       countryCode == this.getCountryCodeForValidRegion_(regionCallingFrom)) {
2076     /** @type {i18n.phonenumbers.NumberFormat} */
2077     var formattingPattern = this.chooseFormattingPatternForNumber_(
2078         metadataForRegionCallingFrom.numberFormatArray(), nationalNumber);
2079     if (formattingPattern == null) {
2080       // If no pattern above is matched, we format the original input.
2081       return rawInput;
2082     }
2083     /** @type {i18n.phonenumbers.NumberFormat} */
2084     var newFormat = formattingPattern.clone();
2085     // The first group is the first group of digits that the user wrote
2086     // together.
2087     newFormat.setPattern('(\\d+)(.*)');
2088     // Here we just concatenate them back together after the national prefix
2089     // has been fixed.
2090     newFormat.setFormat('$1$2');
2091     // Now we format using this pattern instead of the default pattern, but
2092     // with the national prefix prefixed if necessary.
2093     // This will not work in the cases where the pattern (and not the leading
2094     // digits) decide whether a national prefix needs to be used, since we have
2095     // overridden the pattern to match anything, but that is not the case in the
2096     // metadata to date.
2097     return this.formatNsnUsingPattern_(rawInput, newFormat,
2098         i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
2099   }
2100   /** @type {string} */
2101   var internationalPrefixForFormatting = '';
2102   // If an unsupported region-calling-from is entered, or a country with
2103   // multiple international prefixes, the international format of the number is
2104   // returned, unless there is a preferred international prefix.
2105   if (metadataForRegionCallingFrom != null) {
2106     /** @type {string} */
2107     var internationalPrefix =
2108         metadataForRegionCallingFrom.getInternationalPrefixOrDefault();
2109     internationalPrefixForFormatting =
2110         i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2111             i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
2112             internationalPrefix) ?
2113         internationalPrefix :
2114         metadataForRegionCallingFrom.getPreferredInternationalPrefixOrDefault();
2115   }
2116   /** @type {string} */
2117   var regionCode = this.getRegionCodeForCountryCode(countryCode);
2118   // Metadata cannot be null because the country calling code is valid.
2119   /** @type {i18n.phonenumbers.PhoneMetadata} */
2120   var metadataForRegion =
2121       this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
2122   /** @type {string} */
2123   var formattedExtension = this.maybeGetFormattedExtension_(
2124       number, metadataForRegion,
2125       i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
2126   if (internationalPrefixForFormatting.length > 0) {
2127     return internationalPrefixForFormatting + ' ' + countryCode + ' ' +
2128         rawInput + formattedExtension;
2129   } else {
2130     // Invalid region entered as country-calling-from (so no metadata was found
2131     // for it) or the region chosen has multiple international dialling
2132     // prefixes.
2133     return this.prefixNumberWithCountryCallingCode_(
2134         countryCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL,
2135         rawInput, formattedExtension);
2136   }
2137 };
2138
2139
2140 /**
2141  * Gets the national significant number of the a phone number. Note a national
2142  * significant number doesn't contain a national prefix or any formatting.
2143  *
2144  * @param {i18n.phonenumbers.PhoneNumber} number the phone number for which the
2145  *     national significant number is needed.
2146  * @return {string} the national significant number of the PhoneNumber object
2147  *     passed in.
2148  */
2149 i18n.phonenumbers.PhoneNumberUtil.prototype.getNationalSignificantNumber =
2150     function(number) {
2151
2152   // If a leading zero has been set, we prefix this now. Note this is not a
2153   // national prefix.
2154   /** @type {string} */
2155   var nationalNumber = '' + number.getNationalNumber();
2156   if (number.hasItalianLeadingZero() && number.getItalianLeadingZero()) {
2157     return '0' + nationalNumber;
2158   }
2159   return nationalNumber;
2160 };
2161
2162
2163 /**
2164  * A helper function that is used by format and formatByPattern.
2165  *
2166  * @param {number} countryCallingCode the country calling code.
2167  * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2168  *     phone number should be formatted into.
2169  * @param {string} formattedNationalNumber
2170  * @param {string} formattedExtension
2171  * @return {string} the formatted phone number.
2172  * @private
2173  */
2174 i18n.phonenumbers.PhoneNumberUtil.prototype.
2175     prefixNumberWithCountryCallingCode_ = function(countryCallingCode,
2176                                                    numberFormat,
2177                                                    formattedNationalNumber,
2178                                                    formattedExtension) {
2179
2180   switch (numberFormat) {
2181     case i18n.phonenumbers.PhoneNumberFormat.E164:
2182       return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
2183           formattedNationalNumber + formattedExtension;
2184     case i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL:
2185       return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
2186           ' ' + formattedNationalNumber + formattedExtension;
2187     case i18n.phonenumbers.PhoneNumberFormat.RFC3966:
2188       return i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_ +
2189           i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
2190           '-' + formattedNationalNumber + formattedExtension;
2191     case i18n.phonenumbers.PhoneNumberFormat.NATIONAL:
2192     default:
2193       return formattedNationalNumber + formattedExtension;
2194   }
2195 };
2196
2197
2198 /**
2199  * Note in some regions, the national number can be written in two completely
2200  * different ways depending on whether it forms part of the NATIONAL format or
2201  * INTERNATIONAL format. The numberFormat parameter here is used to specify
2202  * which format to use for those cases. If a carrierCode is specified, this will
2203  * be inserted into the formatted string to replace $CC.
2204  *
2205  * @param {string} number a string of characters representing a phone number.
2206  * @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
2207  *     region that we think this number is from.
2208  * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2209  *     phone number should be formatted into.
2210  * @param {string=} opt_carrierCode
2211  * @return {string} the formatted phone number.
2212  * @private
2213  */
2214 i18n.phonenumbers.PhoneNumberUtil.prototype.formatNsn_ =
2215     function(number, metadata, numberFormat, opt_carrierCode) {
2216
2217   /** @type {Array.<i18n.phonenumbers.NumberFormat>} */
2218   var intlNumberFormats = metadata.intlNumberFormatArray();
2219   // When the intlNumberFormats exists, we use that to format national number
2220   // for the INTERNATIONAL format instead of using the numberDesc.numberFormats.
2221   /** @type {Array.<i18n.phonenumbers.NumberFormat>} */
2222   var availableFormats =
2223       (intlNumberFormats.length == 0 ||
2224           numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL) ?
2225       metadata.numberFormatArray() : metadata.intlNumberFormatArray();
2226   /** @type {i18n.phonenumbers.NumberFormat} */
2227   var formattingPattern = this.chooseFormattingPatternForNumber_(
2228       availableFormats, number);
2229   return (formattingPattern == null) ?
2230       number :
2231       this.formatNsnUsingPattern_(number, formattingPattern,
2232                                   numberFormat, opt_carrierCode);
2233 };
2234
2235
2236 /**
2237  * @param {Array.<i18n.phonenumbers.NumberFormat>} availableFormats the
2238  *     available formats the phone number could be formatted into.
2239  * @param {string} nationalNumber a string of characters representing a phone
2240  *     number.
2241  * @return {i18n.phonenumbers.NumberFormat}
2242  * @private
2243  */
2244 i18n.phonenumbers.PhoneNumberUtil.prototype.chooseFormattingPatternForNumber_ =
2245     function(availableFormats, nationalNumber) {
2246
2247   /** @type {i18n.phonenumbers.NumberFormat} */
2248   var numFormat;
2249   /** @type {number} */
2250   var l = availableFormats.length;
2251   for (var i = 0; i < l; ++i) {
2252     numFormat = availableFormats[i];
2253     /** @type {number} */
2254     var size = numFormat.leadingDigitsPatternCount();
2255     if (size == 0 ||
2256         // We always use the last leading_digits_pattern, as it is the most
2257         // detailed.
2258         nationalNumber
2259             .search(numFormat.getLeadingDigitsPattern(size - 1)) == 0) {
2260       /** @type {!RegExp} */
2261       var patternToMatch = new RegExp(numFormat.getPattern());
2262       if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(patternToMatch,
2263                                                              nationalNumber)) {
2264         return numFormat;
2265       }
2266     }
2267   }
2268   return null;
2269 };
2270
2271
2272 /**
2273  * Note that carrierCode is optional - if null or an empty string, no carrier
2274  * code replacement will take place.
2275  *
2276  * @param {string} nationalNumber a string of characters representing a phone
2277  *     number.
2278  * @param {i18n.phonenumbers.NumberFormat} formattingPattern the formatting rule
2279  *     the phone number should be formatted into.
2280  * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2281  *     phone number should be formatted into.
2282  * @param {string=} opt_carrierCode
2283  * @return {string} the formatted phone number.
2284  * @private
2285  */
2286 i18n.phonenumbers.PhoneNumberUtil.prototype.formatNsnUsingPattern_ =
2287     function(nationalNumber, formattingPattern, numberFormat, opt_carrierCode) {
2288
2289   /** @type {string} */
2290   var numberFormatRule = formattingPattern.getFormatOrDefault();
2291   /** @type {!RegExp} */
2292   var patternToMatch = new RegExp(formattingPattern.getPattern());
2293   /** @type {string} */
2294   var domesticCarrierCodeFormattingRule =
2295       formattingPattern.getDomesticCarrierCodeFormattingRuleOrDefault();
2296   /** @type {string} */
2297   var formattedNationalNumber = '';
2298   if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL &&
2299       opt_carrierCode != null && opt_carrierCode.length > 0 &&
2300       domesticCarrierCodeFormattingRule.length > 0) {
2301     // Replace the $CC in the formatting rule with the desired carrier code.
2302     /** @type {string} */
2303     var carrierCodeFormattingRule = domesticCarrierCodeFormattingRule
2304         .replace(i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_,
2305                  opt_carrierCode);
2306     // Now replace the $FG in the formatting rule with the first group and
2307     // the carrier code combined in the appropriate way.
2308     numberFormatRule = numberFormatRule.replace(
2309         i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_,
2310         carrierCodeFormattingRule);
2311     formattedNationalNumber =
2312         nationalNumber.replace(patternToMatch, numberFormatRule);
2313   } else {
2314     // Use the national prefix formatting rule instead.
2315     /** @type {string} */
2316     var nationalPrefixFormattingRule =
2317         formattingPattern.getNationalPrefixFormattingRuleOrDefault();
2318     if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL &&
2319         nationalPrefixFormattingRule != null &&
2320         nationalPrefixFormattingRule.length > 0) {
2321       formattedNationalNumber = nationalNumber.replace(patternToMatch,
2322           numberFormatRule.replace(
2323               i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_,
2324               nationalPrefixFormattingRule));
2325     } else {
2326       formattedNationalNumber =
2327           nationalNumber.replace(patternToMatch, numberFormatRule);
2328     }
2329   }
2330   if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) {
2331     // Strip any leading punctuation.
2332     formattedNationalNumber = formattedNationalNumber.replace(
2333         new RegExp('^' + i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_),
2334         '');
2335     // Replace the rest with a dash between each number group.
2336     formattedNationalNumber = formattedNationalNumber.replace(
2337         new RegExp(i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_, 'g'),
2338         '-');
2339   }
2340   return formattedNationalNumber;
2341 };
2342
2343
2344 /**
2345  * Gets a valid number for the specified region.
2346  *
2347  * @param {string} regionCode the region for which an example number is needed.
2348  * @return {i18n.phonenumbers.PhoneNumber} a valid fixed-line number for the
2349  *     specified region. Returns null when the metadata does not contain such
2350  *     information, or the region 001 is passed in. For 001 (representing non-
2351  *     geographical numbers), call {@link #getExampleNumberForNonGeoEntity}
2352  *     instead.
2353  */
2354 i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumber =
2355     function(regionCode) {
2356
2357   return this.getExampleNumberForType(regionCode,
2358       i18n.phonenumbers.PhoneNumberType.FIXED_LINE);
2359 };
2360
2361
2362 /**
2363  * Gets a valid number for the specified region and number type.
2364  *
2365  * @param {string} regionCode the region for which an example number is needed.
2366  * @param {i18n.phonenumbers.PhoneNumberType} type the type of number that is
2367  *     needed.
2368  * @return {i18n.phonenumbers.PhoneNumber} a valid number for the specified
2369  *     region and type. Returns null when the metadata does not contain such
2370  *     information or if an invalid region or region 001 was entered.
2371  *     For 001 (representing non-geographical numbers), call
2372  *     {@link #getExampleNumberForNonGeoEntity} instead.
2373  */
2374 i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForType =
2375     function(regionCode, type) {
2376
2377   // Check the region code is valid.
2378   if (!this.isValidRegionCode_(regionCode)) {
2379     return null;
2380   }
2381   /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2382   var desc = this.getNumberDescByType_(
2383       this.getMetadataForRegion(regionCode), type);
2384   try {
2385     if (desc.hasExampleNumber()) {
2386       return this.parse(desc.getExampleNumberOrDefault(), regionCode);
2387     }
2388   } catch (e) {
2389   }
2390   return null;
2391 };
2392
2393
2394 /**
2395  * Gets a valid number for the specified country calling code for a
2396  * non-geographical entity.
2397  *
2398  * @param {number} countryCallingCode the country calling code for a
2399  *     non-geographical entity.
2400  * @return {i18n.phonenumbers.PhoneNumber} a valid number for the
2401  *     non-geographical entity. Returns null when the metadata does not contain
2402  *     such information, or the country calling code passed in does not belong
2403  *     to a non-geographical entity.
2404  */
2405 i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForNonGeoEntity =
2406     function(countryCallingCode) {
2407   /** @type {i18n.phonenumbers.PhoneMetadata} */
2408   var metadata =
2409       this.getMetadataForNonGeographicalRegion(countryCallingCode);
2410   if (metadata != null) {
2411     /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2412     var desc = metadata.getGeneralDesc();
2413     try {
2414       if (desc.hasExampleNumber()) {
2415         return this.parse('+' + countryCallingCode + desc.getExampleNumber(),
2416                           'ZZ');
2417       }
2418     } catch (e) {
2419     }
2420   }
2421   return null;
2422 };
2423
2424
2425 /**
2426  * Gets the formatted extension of a phone number, if the phone number had an
2427  * extension specified. If not, it returns an empty string.
2428  *
2429  * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber that might have
2430  *     an extension.
2431  * @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
2432  *     region that we think this number is from.
2433  * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2434  *     phone number should be formatted into.
2435  * @return {string} the formatted extension if any.
2436  * @private
2437  */
2438 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeGetFormattedExtension_ =
2439     function(number, metadata, numberFormat) {
2440
2441   if (!number.hasExtension() || number.getExtension().length == 0) {
2442     return '';
2443   } else {
2444     if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) {
2445       return i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
2446           number.getExtension();
2447     } else {
2448       if (metadata.hasPreferredExtnPrefix()) {
2449         return metadata.getPreferredExtnPrefix() +
2450             number.getExtensionOrDefault();
2451       } else {
2452         return i18n.phonenumbers.PhoneNumberUtil.DEFAULT_EXTN_PREFIX_ +
2453             number.getExtensionOrDefault();
2454       }
2455     }
2456   }
2457 };
2458
2459
2460 /**
2461  * @param {i18n.phonenumbers.PhoneMetadata} metadata
2462  * @param {i18n.phonenumbers.PhoneNumberType} type
2463  * @return {i18n.phonenumbers.PhoneNumberDesc}
2464  * @private
2465  */
2466 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberDescByType_ =
2467     function(metadata, type) {
2468
2469   switch (type) {
2470     case i18n.phonenumbers.PhoneNumberType.PREMIUM_RATE:
2471       return metadata.getPremiumRate();
2472     case i18n.phonenumbers.PhoneNumberType.TOLL_FREE:
2473       return metadata.getTollFree();
2474     case i18n.phonenumbers.PhoneNumberType.MOBILE:
2475       return metadata.getMobile();
2476     case i18n.phonenumbers.PhoneNumberType.FIXED_LINE:
2477     case i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE:
2478       return metadata.getFixedLine();
2479     case i18n.phonenumbers.PhoneNumberType.SHARED_COST:
2480       return metadata.getSharedCost();
2481     case i18n.phonenumbers.PhoneNumberType.VOIP:
2482       return metadata.getVoip();
2483     case i18n.phonenumbers.PhoneNumberType.PERSONAL_NUMBER:
2484       return metadata.getPersonalNumber();
2485     case i18n.phonenumbers.PhoneNumberType.PAGER:
2486       return metadata.getPager();
2487     case i18n.phonenumbers.PhoneNumberType.UAN:
2488       return metadata.getUan();
2489     case i18n.phonenumbers.PhoneNumberType.VOICEMAIL:
2490       return metadata.getVoicemail();
2491     default:
2492       return metadata.getGeneralDesc();
2493   }
2494 };
2495
2496
2497 /**
2498  * Gets the type of a phone number.
2499  *
2500  * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
2501  *     to know the type.
2502  * @return {i18n.phonenumbers.PhoneNumberType} the type of the phone number.
2503  */
2504 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberType =
2505     function(number) {
2506
2507   /** @type {?string} */
2508   var regionCode = this.getRegionCodeForNumber(number);
2509   /** @type {i18n.phonenumbers.PhoneMetadata} */
2510   var metadata = this.getMetadataForRegionOrCallingCode_(
2511       number.getCountryCodeOrDefault(), regionCode);
2512   if (metadata == null) {
2513     return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2514   }
2515   /** @type {string} */
2516   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
2517   return this.getNumberTypeHelper_(nationalSignificantNumber, metadata);
2518 };
2519
2520
2521 /**
2522  * @param {string} nationalNumber
2523  * @param {i18n.phonenumbers.PhoneMetadata} metadata
2524  * @return {i18n.phonenumbers.PhoneNumberType}
2525  * @private
2526  */
2527 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberTypeHelper_ =
2528     function(nationalNumber, metadata) {
2529
2530   /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2531   var generalNumberDesc = metadata.getGeneralDesc();
2532   if (!generalNumberDesc.hasNationalNumberPattern() ||
2533       !this.isNumberMatchingDesc_(nationalNumber, generalNumberDesc)) {
2534     return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2535   }
2536
2537   if (this.isNumberMatchingDesc_(nationalNumber, metadata.getPremiumRate())) {
2538     return i18n.phonenumbers.PhoneNumberType.PREMIUM_RATE;
2539   }
2540   if (this.isNumberMatchingDesc_(nationalNumber, metadata.getTollFree())) {
2541     return i18n.phonenumbers.PhoneNumberType.TOLL_FREE;
2542   }
2543   if (this.isNumberMatchingDesc_(nationalNumber, metadata.getSharedCost())) {
2544     return i18n.phonenumbers.PhoneNumberType.SHARED_COST;
2545   }
2546   if (this.isNumberMatchingDesc_(nationalNumber, metadata.getVoip())) {
2547     return i18n.phonenumbers.PhoneNumberType.VOIP;
2548   }
2549   if (this.isNumberMatchingDesc_(nationalNumber,
2550                                  metadata.getPersonalNumber())) {
2551     return i18n.phonenumbers.PhoneNumberType.PERSONAL_NUMBER;
2552   }
2553   if (this.isNumberMatchingDesc_(nationalNumber, metadata.getPager())) {
2554     return i18n.phonenumbers.PhoneNumberType.PAGER;
2555   }
2556   if (this.isNumberMatchingDesc_(nationalNumber, metadata.getUan())) {
2557     return i18n.phonenumbers.PhoneNumberType.UAN;
2558   }
2559   if (this.isNumberMatchingDesc_(nationalNumber, metadata.getVoicemail())) {
2560     return i18n.phonenumbers.PhoneNumberType.VOICEMAIL;
2561   }
2562
2563   /** @type {boolean} */
2564   var isFixedLine = this.isNumberMatchingDesc_(nationalNumber, metadata
2565       .getFixedLine());
2566   if (isFixedLine) {
2567     if (metadata.getSameMobileAndFixedLinePattern()) {
2568       return i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
2569     } else if (this.isNumberMatchingDesc_(nationalNumber,
2570                                           metadata.getMobile())) {
2571       return i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
2572     }
2573     return i18n.phonenumbers.PhoneNumberType.FIXED_LINE;
2574   }
2575   // Otherwise, test to see if the number is mobile. Only do this if certain
2576   // that the patterns for mobile and fixed line aren't the same.
2577   if (!metadata.getSameMobileAndFixedLinePattern() &&
2578       this.isNumberMatchingDesc_(nationalNumber, metadata.getMobile())) {
2579     return i18n.phonenumbers.PhoneNumberType.MOBILE;
2580   }
2581   return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2582 };
2583
2584
2585 /**
2586  * Returns the metadata for the given region code or {@code null} if the region
2587  * code is invalid or unknown.
2588  *
2589  * @param {?string} regionCode
2590  * @return {i18n.phonenumbers.PhoneMetadata}
2591  */
2592 i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegion =
2593     function(regionCode) {
2594
2595   if (regionCode == null) {
2596     return null;
2597   }
2598   regionCode = regionCode.toUpperCase();
2599   /** @type {i18n.phonenumbers.PhoneMetadata} */
2600   var metadata = this.regionToMetadataMap[regionCode];
2601   if (metadata == null) {
2602     /** @type {goog.proto2.PbLiteSerializer} */
2603     var serializer = new goog.proto2.PbLiteSerializer();
2604     /** @type {Array} */
2605     var metadataSerialized =
2606         i18n.phonenumbers.metadata.countryToMetadata[regionCode];
2607     if (metadataSerialized == null) {
2608       return null;
2609     }
2610     metadata = /** @type {i18n.phonenumbers.PhoneMetadata} */ (
2611         serializer.deserialize(i18n.phonenumbers.PhoneMetadata.getDescriptor(),
2612             metadataSerialized));
2613     this.regionToMetadataMap[regionCode] = metadata;
2614   }
2615   return metadata;
2616 };
2617
2618
2619 /**
2620  * @param {number} countryCallingCode
2621  * @return {i18n.phonenumbers.PhoneMetadata}
2622  */
2623 i18n.phonenumbers.PhoneNumberUtil.prototype.
2624     getMetadataForNonGeographicalRegion = function(countryCallingCode) {
2625
2626   return this.getMetadataForRegion('' + countryCallingCode);
2627 };
2628
2629
2630 /**
2631  * @param {string} nationalNumber
2632  * @param {i18n.phonenumbers.PhoneNumberDesc} numberDesc
2633  * @return {boolean}
2634  * @private
2635  */
2636 i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatchingDesc_ =
2637     function(nationalNumber, numberDesc) {
2638
2639   return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2640       numberDesc.getPossibleNumberPatternOrDefault(), nationalNumber) &&
2641       i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2642           numberDesc.getNationalNumberPatternOrDefault(), nationalNumber);
2643 };
2644
2645
2646 /**
2647  * Tests whether a phone number matches a valid pattern. Note this doesn't
2648  * verify the number is actually in use, which is impossible to tell by just
2649  * looking at a number itself.
2650  *
2651  * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
2652  *     to validate.
2653  * @return {boolean} a boolean that indicates whether the number is of a valid
2654  *     pattern.
2655  */
2656 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumber = function(number) {
2657   /** @type {?string} */
2658   var regionCode = this.getRegionCodeForNumber(number);
2659   return this.isValidNumberForRegion(number, regionCode);
2660 };
2661
2662
2663 /**
2664  * Tests whether a phone number is valid for a certain region. Note this doesn't
2665  * verify the number is actually in use, which is impossible to tell by just
2666  * looking at a number itself. If the country calling code is not the same as
2667  * the country calling code for the region, this immediately exits with false.
2668  * After this, the specific number pattern rules for the region are examined.
2669  * This is useful for determining for example whether a particular number is
2670  * valid for Canada, rather than just a valid NANPA number.
2671  * Warning: In most cases, you want to use {@link #isValidNumber} instead. For
2672  * example, this method will mark numbers from British Crown dependencies such
2673  * as the Isle of Man as invalid for the region "GB" (United Kingdom), since it
2674  * has its own region code, "IM", which may be undesirable.
2675  *
2676  * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
2677  *     to validate.
2678  * @param {?string} regionCode the region that we want to validate the phone
2679  *     number for.
2680  * @return {boolean} a boolean that indicates whether the number is of a valid
2681  *     pattern.
2682  */
2683 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumberForRegion =
2684     function(number, regionCode) {
2685
2686   /** @type {number} */
2687   var countryCode = number.getCountryCodeOrDefault();
2688   /** @type {i18n.phonenumbers.PhoneMetadata} */
2689   var metadata =
2690       this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
2691   if (metadata == null ||
2692       (i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY !=
2693        regionCode &&
2694        countryCode != this.getCountryCodeForValidRegion_(regionCode))) {
2695     // Either the region code was invalid, or the country calling code for this
2696     // number does not match that of the region code.
2697     return false;
2698   }
2699   /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2700   var generalNumDesc = metadata.getGeneralDesc();
2701   /** @type {string} */
2702   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
2703
2704   // For regions where we don't have metadata for PhoneNumberDesc, we treat any
2705   // number passed in as a valid number if its national significant number is
2706   // between the minimum and maximum lengths defined by ITU for a national
2707   // significant number.
2708   if (!generalNumDesc.hasNationalNumberPattern()) {
2709     /** @type {number} */
2710     var numberLength = nationalSignificantNumber.length;
2711     return numberLength >
2712         i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_ &&
2713         numberLength <= i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_;
2714   }
2715   return this.getNumberTypeHelper_(nationalSignificantNumber, metadata) !=
2716       i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2717 };
2718
2719
2720 /**
2721  * Returns the region where a phone number is from. This could be used for
2722  * geocoding at the region level.
2723  *
2724  * @param {i18n.phonenumbers.PhoneNumber} number the phone number whose origin
2725  *     we want to know.
2726  * @return {?string} the region where the phone number is from, or null
2727  *     if no region matches this calling code.
2728  */
2729 i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForNumber =
2730     function(number) {
2731
2732   if (number == null) {
2733     return null;
2734   }
2735   /** @type {number} */
2736   var countryCode = number.getCountryCodeOrDefault();
2737   /** @type {Array.<string>} */
2738   var regions =
2739       i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCode];
2740   if (regions == null) {
2741     return null;
2742   }
2743   if (regions.length == 1) {
2744     return regions[0];
2745   } else {
2746     return this.getRegionCodeForNumberFromRegionList_(number, regions);
2747   }
2748 };
2749
2750
2751 /**
2752  * @param {i18n.phonenumbers.PhoneNumber} number
2753  * @param {Array.<string>} regionCodes
2754  * @return {?string}
2755  * @private
2756  */
2757 i18n.phonenumbers.PhoneNumberUtil.prototype.
2758     getRegionCodeForNumberFromRegionList_ = function(number, regionCodes) {
2759
2760   /** @type {string} */
2761   var nationalNumber = this.getNationalSignificantNumber(number);
2762   /** @type {string} */
2763   var regionCode;
2764   /** @type {number} */
2765   var regionCodesLength = regionCodes.length;
2766   for (var i = 0; i < regionCodesLength; i++) {
2767     regionCode = regionCodes[i];
2768     // If leadingDigits is present, use this. Otherwise, do full validation.
2769     // Metadata cannot be null because the region codes come from the country
2770     // calling code map.
2771     /** @type {i18n.phonenumbers.PhoneMetadata} */
2772     var metadata = this.getMetadataForRegion(regionCode);
2773     if (metadata.hasLeadingDigits()) {
2774       if (nationalNumber.search(metadata.getLeadingDigits()) == 0) {
2775         return regionCode;
2776       }
2777     } else if (this.getNumberTypeHelper_(nationalNumber, metadata) !=
2778         i18n.phonenumbers.PhoneNumberType.UNKNOWN) {
2779       return regionCode;
2780     }
2781   }
2782   return null;
2783 };
2784
2785
2786 /**
2787  * Returns the region code that matches the specific country calling code. In
2788  * the case of no region code being found, ZZ will be returned. In the case of
2789  * multiple regions, the one designated in the metadata as the 'main' region for
2790  * this calling code will be returned.
2791  *
2792  * @param {number} countryCallingCode the country calling code.
2793  * @return {string}
2794  */
2795 i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForCountryCode =
2796     function(countryCallingCode) {
2797
2798   /** @type {Array.<string>} */
2799   var regionCodes =
2800       i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCallingCode];
2801   return regionCodes == null ?
2802       i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_ : regionCodes[0];
2803 };
2804
2805
2806 /**
2807  * Returns a list with the region codes that match the specific country calling
2808  * code. For non-geographical country calling codes, the region code 001 is
2809  * returned. Also, in the case of no region code being found, an empty list is
2810  * returned.
2811  *
2812  * @param {number} countryCallingCode the country calling code.
2813  * @return {Array.<string>}
2814  */
2815 i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodesForCountryCode =
2816     function(countryCallingCode) {
2817
2818   /** @type {Array.<string>} */
2819   var regionCodes =
2820       i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCallingCode];
2821   return regionCodes == null ? [] : regionCodes;
2822 };
2823
2824
2825 /**
2826  * Returns the country calling code for a specific region. For example, this
2827  * would be 1 for the United States, and 64 for New Zealand.
2828  *
2829  * @param {?string} regionCode the region that we want to get the country
2830  *     calling code for.
2831  * @return {number} the country calling code for the region denoted by
2832  *     regionCode.
2833  */
2834 i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForRegion =
2835     function(regionCode) {
2836
2837   if (!this.isValidRegionCode_(regionCode)) {
2838     return 0;
2839   }
2840   return this.getCountryCodeForValidRegion_(regionCode);
2841 };
2842
2843
2844 /**
2845  * Returns the country calling code for a specific region. For example, this
2846  * would be 1 for the United States, and 64 for New Zealand. Assumes the region
2847  * is already valid.
2848  *
2849  * @param {?string} regionCode the region that we want to get the country
2850  *     calling code for.
2851  * @return {number} the country calling code for the region denoted by
2852  *     regionCode.
2853  * @throws {string} if the region is invalid
2854  * @private
2855  */
2856 i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForValidRegion_ =
2857     function(regionCode) {
2858
2859   /** @type {i18n.phonenumbers.PhoneMetadata} */
2860   var metadata = this.getMetadataForRegion(regionCode);
2861   if (metadata == null) {
2862     throw 'Invalid region code: ' + regionCode;
2863   }
2864   return metadata.getCountryCodeOrDefault();
2865 };
2866
2867
2868 /**
2869  * Returns the national dialling prefix for a specific region. For example, this
2870  * would be 1 for the United States, and 0 for New Zealand. Set stripNonDigits
2871  * to true to strip symbols like '~' (which indicates a wait for a dialling
2872  * tone) from the prefix returned. If no national prefix is present, we return
2873  * null.
2874  *
2875  * <p>Warning: Do not use this method for do-your-own formatting - for some
2876  * regions, the national dialling prefix is used only for certain types of
2877  * numbers. Use the library's formatting functions to prefix the national prefix
2878  * when required.
2879  *
2880  * @param {?string} regionCode the region that we want to get the dialling
2881  *     prefix for.
2882  * @param {boolean} stripNonDigits true to strip non-digits from the national
2883  *     dialling prefix.
2884  * @return {?string} the dialling prefix for the region denoted by
2885  *     regionCode.
2886  */
2887 i18n.phonenumbers.PhoneNumberUtil.prototype.getNddPrefixForRegion = function(
2888     regionCode, stripNonDigits) {
2889   /** @type {i18n.phonenumbers.PhoneMetadata} */
2890   var metadata = this.getMetadataForRegion(regionCode);
2891   if (metadata == null) {
2892     return null;
2893   }
2894   /** @type {string} */
2895   var nationalPrefix = metadata.getNationalPrefixOrDefault();
2896   // If no national prefix was found, we return null.
2897   if (nationalPrefix.length == 0) {
2898     return null;
2899   }
2900   if (stripNonDigits) {
2901     // Note: if any other non-numeric symbols are ever used in national
2902     // prefixes, these would have to be removed here as well.
2903     nationalPrefix = nationalPrefix.replace('~', '');
2904   }
2905   return nationalPrefix;
2906 };
2907
2908
2909 /**
2910  * Checks if this is a region under the North American Numbering Plan
2911  * Administration (NANPA).
2912  *
2913  * @param {?string} regionCode the ISO 3166-1 two-letter region code.
2914  * @return {boolean} true if regionCode is one of the regions under NANPA.
2915  */
2916 i18n.phonenumbers.PhoneNumberUtil.prototype.isNANPACountry =
2917     function(regionCode) {
2918
2919   return regionCode != null && goog.array.contains(
2920       i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[
2921           i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_],
2922       regionCode.toUpperCase());
2923 };
2924
2925
2926 /**
2927  * Checks whether countryCode represents the country calling code from a region
2928  * whose national significant number could contain a leading zero. An example of
2929  * such a region is Italy. Returns false if no metadata for the country is
2930  * found.
2931  *
2932  * @param {number} countryCallingCode the country calling code.
2933  * @return {boolean}
2934  */
2935 i18n.phonenumbers.PhoneNumberUtil.prototype.isLeadingZeroPossible =
2936     function(countryCallingCode) {
2937   /** @type {i18n.phonenumbers.PhoneMetadata} */
2938   var mainMetadataForCallingCode = this.getMetadataForRegionOrCallingCode_(
2939       countryCallingCode,
2940       this.getRegionCodeForCountryCode(countryCallingCode));
2941   return mainMetadataForCallingCode != null &&
2942       mainMetadataForCallingCode.getLeadingZeroPossibleOrDefault();
2943 };
2944
2945
2946 /**
2947  * Checks if the number is a valid vanity (alpha) number such as 800 MICROSOFT.
2948  * A valid vanity number will start with at least 3 digits and will have three
2949  * or more alpha characters. This does not do region-specific checks - to work
2950  * out if this number is actually valid for a region, it should be parsed and
2951  * methods such as {@link #isPossibleNumberWithReason} and
2952  * {@link #isValidNumber} should be used.
2953  *
2954  * @param {string} number the number that needs to be checked.
2955  * @return {boolean} true if the number is a valid vanity number.
2956  */
2957 i18n.phonenumbers.PhoneNumberUtil.prototype.isAlphaNumber = function(number) {
2958   if (!i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(number)) {
2959     // Number is too short, or doesn't match the basic phone number pattern.
2960     return false;
2961   }
2962   /** @type {!goog.string.StringBuffer} */
2963   var strippedNumber = new goog.string.StringBuffer(number);
2964   this.maybeStripExtension(strippedNumber);
2965   return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2966       i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_,
2967       strippedNumber.toString());
2968 };
2969
2970
2971 /**
2972  * Convenience wrapper around {@link #isPossibleNumberWithReason}. Instead of
2973  * returning the reason for failure, this method returns a boolean value.
2974  *
2975  * @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be
2976  *     checked.
2977  * @return {boolean} true if the number is possible.
2978  */
2979 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumber =
2980     function(number) {
2981
2982   return this.isPossibleNumberWithReason(number) ==
2983       i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
2984 };
2985
2986
2987 /**
2988  * Helper method to check a number against a particular pattern and determine
2989  * whether it matches, or is too short or too long. Currently, if a number
2990  * pattern suggests that numbers of length 7 and 10 are possible, and a number
2991  * in between these possible lengths is entered, such as of length 8, this will
2992  * return TOO_LONG.
2993  *
2994  * @param {string} numberPattern
2995  * @param {string} number
2996  * @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult}
2997  * @private
2998  */
2999 i18n.phonenumbers.PhoneNumberUtil.prototype.testNumberLengthAgainstPattern_ =
3000     function(numberPattern, number) {
3001   if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(numberPattern,
3002                                                          number)) {
3003     return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
3004   }
3005   if (number.search(numberPattern) == 0) {
3006     return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG;
3007   } else {
3008     return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT;
3009   }
3010 };
3011
3012
3013 /**
3014  * Check whether a phone number is a possible number. It provides a more lenient
3015  * check than {@link #isValidNumber} in the following sense:
3016  * <ol>
3017  * <li>It only checks the length of phone numbers. In particular, it doesn't
3018  * check starting digits of the number.
3019  * <li>It doesn't attempt to figure out the type of the number, but uses general
3020  * rules which applies to all types of phone numbers in a region. Therefore, it
3021  * is much faster than isValidNumber.
3022  * <li>For fixed line numbers, many regions have the concept of area code, which
3023  * together with subscriber number constitute the national significant number.
3024  * It is sometimes okay to dial the subscriber number only when dialing in the
3025  * same area. This function will return true if the subscriber-number-only
3026  * version is passed in. On the other hand, because isValidNumber validates
3027  * using information on both starting digits (for fixed line numbers, that would
3028  * most likely be area codes) and length (obviously includes the length of area
3029  * codes for fixed line numbers), it will return false for the
3030  * subscriber-number-only version.
3031  * </ol>
3032  *
3033  * @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be
3034  *     checked.
3035  * @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult} a
3036  *     ValidationResult object which indicates whether the number is possible.
3037  */
3038 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberWithReason =
3039     function(number) {
3040
3041   /** @type {string} */
3042   var nationalNumber = this.getNationalSignificantNumber(number);
3043   /** @type {number} */
3044   var countryCode = number.getCountryCodeOrDefault();
3045   // Note: For Russian Fed and NANPA numbers, we just use the rules from the
3046   // default region (US or Russia) since the getRegionCodeForNumber will not
3047   // work if the number is possible but not valid. This would need to be
3048   // revisited if the possible number pattern ever differed between various
3049   // regions within those plans.
3050   if (!this.hasValidCountryCallingCode_(countryCode)) {
3051     return i18n.phonenumbers.PhoneNumberUtil.ValidationResult
3052         .INVALID_COUNTRY_CODE;
3053   }
3054   /** @type {string} */
3055   var regionCode = this.getRegionCodeForCountryCode(countryCode);
3056   // Metadata cannot be null because the country calling code is valid.
3057   /** @type {i18n.phonenumbers.PhoneMetadata} */
3058   var metadata =
3059       this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
3060   /** @type {i18n.phonenumbers.PhoneNumberDesc} */
3061   var generalNumDesc = metadata.getGeneralDesc();
3062   // Handling case of numbers with no metadata.
3063   if (!generalNumDesc.hasNationalNumberPattern()) {
3064     /** @type {number} */
3065     var numberLength = nationalNumber.length;
3066     if (numberLength < i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3067       return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT;
3068     } else if (numberLength >
3069                i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_) {
3070       return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG;
3071     } else {
3072       return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
3073     }
3074   }
3075   /** @type {string} */
3076   var possibleNumberPattern =
3077       generalNumDesc.getPossibleNumberPatternOrDefault();
3078   return this.testNumberLengthAgainstPattern_(possibleNumberPattern,
3079                                               nationalNumber);
3080 };
3081
3082
3083 /**
3084  * Check whether a phone number is a possible number given a number in the form
3085  * of a string, and the region where the number could be dialed from. It
3086  * provides a more lenient check than {@link #isValidNumber}. See
3087  * {@link #isPossibleNumber} for details.
3088  *
3089  * <p>This method first parses the number, then invokes
3090  * {@link #isPossibleNumber} with the resultant PhoneNumber object.
3091  *
3092  * @param {string} number the number that needs to be checked, in the form of a
3093  *     string.
3094  * @param {string} regionDialingFrom the region that we are expecting the number
3095  *     to be dialed from.
3096  *     Note this is different from the region where the number belongs.
3097  *     For example, the number +1 650 253 0000 is a number that belongs to US.
3098  *     When written in this form, it can be dialed from any region. When it is
3099  *     written as 00 1 650 253 0000, it can be dialed from any region which uses
3100  *     an international dialling prefix of 00. When it is written as
3101  *     650 253 0000, it can only be dialed from within the US, and when written
3102  *     as 253 0000, it can only be dialed from within a smaller area in the US
3103  *     (Mountain View, CA, to be more specific).
3104  * @return {boolean} true if the number is possible.
3105  */
3106 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberString =
3107     function(number, regionDialingFrom) {
3108
3109   try {
3110     return this.isPossibleNumber(this.parse(number, regionDialingFrom));
3111   } catch (e) {
3112     return false;
3113   }
3114 };
3115
3116
3117 /**
3118  * Attempts to extract a valid number from a phone number that is too long to be
3119  * valid, and resets the PhoneNumber object passed in to that valid version. If
3120  * no valid number could be extracted, the PhoneNumber object passed in will not
3121  * be modified.
3122  * @param {i18n.phonenumbers.PhoneNumber} number a PhoneNumber object which
3123  *     contains a number that is too long to be valid.
3124  * @return {boolean} true if a valid phone number can be successfully extracted.
3125  */
3126 i18n.phonenumbers.PhoneNumberUtil.prototype.truncateTooLongNumber =
3127     function(number) {
3128
3129   if (this.isValidNumber(number)) {
3130     return true;
3131   }
3132   /** @type {i18n.phonenumbers.PhoneNumber} */
3133   var numberCopy = number.clone();
3134   /** @type {number} */
3135   var nationalNumber = number.getNationalNumberOrDefault();
3136   do {
3137     nationalNumber = Math.floor(nationalNumber / 10);
3138     numberCopy.setNationalNumber(nationalNumber);
3139     if (nationalNumber == 0 ||
3140         this.isPossibleNumberWithReason(numberCopy) ==
3141             i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT) {
3142       return false;
3143     }
3144   } while (!this.isValidNumber(numberCopy));
3145   number.setNationalNumber(nationalNumber);
3146   return true;
3147 };
3148
3149
3150 /**
3151  * Extracts country calling code from fullNumber, returns it and places the
3152  * remaining number in nationalNumber. It assumes that the leading plus sign or
3153  * IDD has already been removed. Returns 0 if fullNumber doesn't start with a
3154  * valid country calling code, and leaves nationalNumber unmodified.
3155  *
3156  * @param {!goog.string.StringBuffer} fullNumber
3157  * @param {!goog.string.StringBuffer} nationalNumber
3158  * @return {number}
3159  */
3160 i18n.phonenumbers.PhoneNumberUtil.prototype.extractCountryCode =
3161     function(fullNumber, nationalNumber) {
3162
3163   /** @type {string} */
3164   var fullNumberStr = fullNumber.toString();
3165   if ((fullNumberStr.length == 0) || (fullNumberStr.charAt(0) == '0')) {
3166     // Country codes do not begin with a '0'.
3167     return 0;
3168   }
3169   /** @type {number} */
3170   var potentialCountryCode;
3171   /** @type {number} */
3172   var numberLength = fullNumberStr.length;
3173   for (var i = 1;
3174       i <= i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE_ &&
3175       i <= numberLength; ++i) {
3176     potentialCountryCode = parseInt(fullNumberStr.substring(0, i), 10);
3177     if (potentialCountryCode in
3178         i18n.phonenumbers.metadata.countryCodeToRegionCodeMap) {
3179       nationalNumber.append(fullNumberStr.substring(i));
3180       return potentialCountryCode;
3181     }
3182   }
3183   return 0;
3184 };
3185
3186
3187 /**
3188  * Tries to extract a country calling code from a number. This method will
3189  * return zero if no country calling code is considered to be present. Country
3190  * calling codes are extracted in the following ways:
3191  * <ul>
3192  * <li>by stripping the international dialing prefix of the region the person is
3193  * dialing from, if this is present in the number, and looking at the next
3194  * digits
3195  * <li>by stripping the '+' sign if present and then looking at the next digits
3196  * <li>by comparing the start of the number and the country calling code of the
3197  * default region. If the number is not considered possible for the numbering
3198  * plan of the default region initially, but starts with the country calling
3199  * code of this region, validation will be reattempted after stripping this
3200  * country calling code. If this number is considered a possible number, then
3201  * the first digits will be considered the country calling code and removed as
3202  * such.
3203  * </ul>
3204  *
3205  * It will throw a i18n.phonenumbers.Error if the number starts with a '+' but
3206  * the country calling code supplied after this does not match that of any known
3207  * region.
3208  *
3209  * @param {string} number non-normalized telephone number that we wish to
3210  *     extract a country calling code from - may begin with '+'.
3211  * @param {i18n.phonenumbers.PhoneMetadata} defaultRegionMetadata metadata
3212  *     about the region this number may be from.
3213  * @param {!goog.string.StringBuffer} nationalNumber a string buffer to store
3214  *     the national significant number in, in the case that a country calling
3215  *     code was extracted. The number is appended to any existing contents. If
3216  *     no country calling code was extracted, this will be left unchanged.
3217  * @param {boolean} keepRawInput true if the country_code_source and
3218  *     preferred_carrier_code fields of phoneNumber should be populated.
3219  * @param {i18n.phonenumbers.PhoneNumber} phoneNumber the PhoneNumber object
3220  *     where the country_code and country_code_source need to be populated.
3221  *     Note the country_code is always populated, whereas country_code_source is
3222  *     only populated when keepCountryCodeSource is true.
3223  * @return {number} the country calling code extracted or 0 if none could be
3224  *     extracted.
3225  * @throws {i18n.phonenumbers.Error}
3226  */
3227 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeExtractCountryCode =
3228     function(number, defaultRegionMetadata, nationalNumber,
3229              keepRawInput, phoneNumber) {
3230
3231   if (number.length == 0) {
3232     return 0;
3233   }
3234   /** @type {!goog.string.StringBuffer} */
3235   var fullNumber = new goog.string.StringBuffer(number);
3236   // Set the default prefix to be something that will never match.
3237   /** @type {?string} */
3238   var possibleCountryIddPrefix;
3239   if (defaultRegionMetadata != null) {
3240     possibleCountryIddPrefix = defaultRegionMetadata.getInternationalPrefix();
3241   }
3242   if (possibleCountryIddPrefix == null) {
3243     possibleCountryIddPrefix = 'NonMatch';
3244   }
3245
3246   /** @type {i18n.phonenumbers.PhoneNumber.CountryCodeSource} */
3247   var countryCodeSource = this.maybeStripInternationalPrefixAndNormalize(
3248       fullNumber, possibleCountryIddPrefix);
3249   if (keepRawInput) {
3250     phoneNumber.setCountryCodeSource(countryCodeSource);
3251   }
3252   if (countryCodeSource !=
3253       i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY) {
3254     if (fullNumber.getLength() <=
3255         i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3256       throw i18n.phonenumbers.Error.TOO_SHORT_AFTER_IDD;
3257     }
3258     /** @type {number} */
3259     var potentialCountryCode = this.extractCountryCode(fullNumber,
3260                                                        nationalNumber);
3261     if (potentialCountryCode != 0) {
3262       phoneNumber.setCountryCode(potentialCountryCode);
3263       return potentialCountryCode;
3264     }
3265
3266     // If this fails, they must be using a strange country calling code that we
3267     // don't recognize, or that doesn't exist.
3268     throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
3269   } else if (defaultRegionMetadata != null) {
3270     // Check to see if the number starts with the country calling code for the
3271     // default region. If so, we remove the country calling code, and do some
3272     // checks on the validity of the number before and after.
3273     /** @type {number} */
3274     var defaultCountryCode = defaultRegionMetadata.getCountryCodeOrDefault();
3275     /** @type {string} */
3276     var defaultCountryCodeString = '' + defaultCountryCode;
3277     /** @type {string} */
3278     var normalizedNumber = fullNumber.toString();
3279     if (goog.string.startsWith(normalizedNumber, defaultCountryCodeString)) {
3280       /** @type {!goog.string.StringBuffer} */
3281       var potentialNationalNumber = new goog.string.StringBuffer(
3282           normalizedNumber.substring(defaultCountryCodeString.length));
3283       /** @type {i18n.phonenumbers.PhoneNumberDesc} */
3284       var generalDesc = defaultRegionMetadata.getGeneralDesc();
3285       /** @type {!RegExp} */
3286       var validNumberPattern =
3287           new RegExp(generalDesc.getNationalNumberPatternOrDefault());
3288       // Passing null since we don't need the carrier code.
3289       this.maybeStripNationalPrefixAndCarrierCode(
3290           potentialNationalNumber, defaultRegionMetadata, null);
3291       /** @type {string} */
3292       var potentialNationalNumberStr = potentialNationalNumber.toString();
3293       /** @type {string} */
3294       var possibleNumberPattern =
3295           generalDesc.getPossibleNumberPatternOrDefault();
3296       // If the number was not valid before but is valid now, or if it was too
3297       // long before, we consider the number with the country calling code
3298       // stripped to be a better result and keep that instead.
3299       if ((!i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3300               validNumberPattern, fullNumber.toString()) &&
3301           i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3302               validNumberPattern, potentialNationalNumberStr)) ||
3303           this.testNumberLengthAgainstPattern_(possibleNumberPattern,
3304                                                fullNumber.toString()) ==
3305               i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG) {
3306         nationalNumber.append(potentialNationalNumberStr);
3307         if (keepRawInput) {
3308           phoneNumber.setCountryCodeSource(
3309               i18n.phonenumbers.PhoneNumber.CountryCodeSource
3310                   .FROM_NUMBER_WITHOUT_PLUS_SIGN);
3311         }
3312         phoneNumber.setCountryCode(defaultCountryCode);
3313         return defaultCountryCode;
3314       }
3315     }
3316   }
3317   // No country calling code present.
3318   phoneNumber.setCountryCode(0);
3319   return 0;
3320 };
3321
3322
3323 /**
3324  * Strips the IDD from the start of the number if present. Helper function used
3325  * by maybeStripInternationalPrefixAndNormalize.
3326  *
3327  * @param {!RegExp} iddPattern the regular expression for the international
3328  *     prefix.
3329  * @param {!goog.string.StringBuffer} number the phone number that we wish to
3330  *     strip any international dialing prefix from.
3331  * @return {boolean} true if an international prefix was present.
3332  * @private
3333  */
3334 i18n.phonenumbers.PhoneNumberUtil.prototype.parsePrefixAsIdd_ =
3335     function(iddPattern, number) {
3336
3337   /** @type {string} */
3338   var numberStr = number.toString();
3339   if (numberStr.search(iddPattern) == 0) {
3340     /** @type {number} */
3341     var matchEnd = numberStr.match(iddPattern)[0].length;
3342     /** @type {Array.<string>} */
3343     var matchedGroups = numberStr.substring(matchEnd).match(
3344         i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN);
3345     if (matchedGroups && matchedGroups[1] != null &&
3346         matchedGroups[1].length > 0) {
3347       /** @type {string} */
3348       var normalizedGroup =
3349           i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(
3350               matchedGroups[1]);
3351       if (normalizedGroup == '0') {
3352         return false;
3353       }
3354     }
3355     number.clear();
3356     number.append(numberStr.substring(matchEnd));
3357     return true;
3358   }
3359   return false;
3360 };
3361
3362
3363 /**
3364  * Strips any international prefix (such as +, 00, 011) present in the number
3365  * provided, normalizes the resulting number, and indicates if an international
3366  * prefix was present.
3367  *
3368  * @param {!goog.string.StringBuffer} number the non-normalized telephone number
3369  *     that we wish to strip any international dialing prefix from.
3370  * @param {string} possibleIddPrefix the international direct dialing prefix
3371  *     from the region we think this number may be dialed in.
3372  * @return {i18n.phonenumbers.PhoneNumber.CountryCodeSource} the corresponding
3373  *     CountryCodeSource if an international dialing prefix could be removed
3374  *     from the number, otherwise CountryCodeSource.FROM_DEFAULT_COUNTRY if
3375  *     the number did not seem to be in international format.
3376  */
3377 i18n.phonenumbers.PhoneNumberUtil.prototype.
3378     maybeStripInternationalPrefixAndNormalize = function(number,
3379                                                          possibleIddPrefix) {
3380   /** @type {string} */
3381   var numberStr = number.toString();
3382   if (numberStr.length == 0) {
3383     return i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY;
3384   }
3385   // Check to see if the number begins with one or more plus signs.
3386   if (i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_
3387       .test(numberStr)) {
3388     numberStr = numberStr.replace(
3389         i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_, '');
3390     // Can now normalize the rest of the number since we've consumed the '+'
3391     // sign at the start.
3392     number.clear();
3393     number.append(i18n.phonenumbers.PhoneNumberUtil.normalize(numberStr));
3394     return i18n.phonenumbers.PhoneNumber.CountryCodeSource
3395         .FROM_NUMBER_WITH_PLUS_SIGN;
3396   }
3397   // Attempt to parse the first digits as an international prefix.
3398   /** @type {!RegExp} */
3399   var iddPattern = new RegExp(possibleIddPrefix);
3400   i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(number);
3401   return this.parsePrefixAsIdd_(iddPattern, number) ?
3402       i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD :
3403       i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY;
3404 };
3405
3406
3407 /**
3408  * Strips any national prefix (such as 0, 1) present in the number provided.
3409  *
3410  * @param {!goog.string.StringBuffer} number the normalized telephone number
3411  *     that we wish to strip any national dialing prefix from.
3412  * @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
3413  *     region that we think this number is from.
3414  * @param {goog.string.StringBuffer} carrierCode a place to insert the carrier
3415  *     code if one is extracted.
3416  * @return {boolean} true if a national prefix or carrier code (or both) could
3417  *     be extracted.
3418  */
3419 i18n.phonenumbers.PhoneNumberUtil.prototype.
3420     maybeStripNationalPrefixAndCarrierCode = function(number, metadata,
3421                                                       carrierCode) {
3422
3423   /** @type {string} */
3424   var numberStr = number.toString();
3425   /** @type {number} */
3426   var numberLength = numberStr.length;
3427   /** @type {?string} */
3428   var possibleNationalPrefix = metadata.getNationalPrefixForParsing();
3429   if (numberLength == 0 || possibleNationalPrefix == null ||
3430       possibleNationalPrefix.length == 0) {
3431     // Early return for numbers of zero length.
3432     return false;
3433   }
3434   // Attempt to parse the first digits as a national prefix.
3435   /** @type {!RegExp} */
3436   var prefixPattern = new RegExp('^(?:' + possibleNationalPrefix + ')');
3437   /** @type {Array.<string>} */
3438   var prefixMatcher = prefixPattern.exec(numberStr);
3439   if (prefixMatcher) {
3440     /** @type {!RegExp} */
3441     var nationalNumberRule = new RegExp(
3442         metadata.getGeneralDesc().getNationalNumberPatternOrDefault());
3443     // prefixMatcher[numOfGroups] == null implies nothing was captured by the
3444     // capturing groups in possibleNationalPrefix; therefore, no transformation
3445     // is necessary, and we just remove the national prefix.
3446     /** @type {number} */
3447     var numOfGroups = prefixMatcher.length - 1;
3448     /** @type {?string} */
3449     var transformRule = metadata.getNationalPrefixTransformRule();
3450     /** @type {string} */
3451     var transformedNumber;
3452     /** @type {boolean} */
3453     var noTransform = transformRule == null || transformRule.length == 0 ||
3454                       prefixMatcher[numOfGroups] == null ||
3455                       prefixMatcher[numOfGroups].length == 0;
3456     if (noTransform) {
3457       transformedNumber = numberStr.substring(prefixMatcher[0].length);
3458     } else {
3459       transformedNumber = numberStr.replace(prefixPattern, transformRule);
3460     }
3461     // If the original number was viable, and the resultant number is not,
3462     // we return.
3463     if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3464             nationalNumberRule, numberStr) &&
3465         !i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3466             nationalNumberRule, transformedNumber)) {
3467       return false;
3468     }
3469     if ((noTransform && numOfGroups > 0 && prefixMatcher[1] != null) ||
3470         (!noTransform && numOfGroups > 1)) {
3471       if (carrierCode != null) {
3472         carrierCode.append(prefixMatcher[1]);
3473       }
3474     }
3475     number.clear();
3476     number.append(transformedNumber);
3477     return true;
3478   }
3479   return false;
3480 };
3481
3482
3483 /**
3484  * Strips any extension (as in, the part of the number dialled after the call is
3485  * connected, usually indicated with extn, ext, x or similar) from the end of
3486  * the number, and returns it.
3487  *
3488  * @param {!goog.string.StringBuffer} number the non-normalized telephone number
3489  *     that we wish to strip the extension from.
3490  * @return {string} the phone extension.
3491  */
3492 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeStripExtension =
3493     function(number) {
3494
3495   /** @type {string} */
3496   var numberStr = number.toString();
3497   /** @type {number} */
3498   var mStart =
3499       numberStr.search(i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_);
3500   // If we find a potential extension, and the number preceding this is a viable
3501   // number, we assume it is an extension.
3502   if (mStart >= 0 && i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(
3503       numberStr.substring(0, mStart))) {
3504     // The numbers are captured into groups in the regular expression.
3505     /** @type {Array.<string>} */
3506     var matchedGroups =
3507         numberStr.match(i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_);
3508     /** @type {number} */
3509     var matchedGroupsLength = matchedGroups.length;
3510     for (var i = 1; i < matchedGroupsLength; ++i) {
3511       if (matchedGroups[i] != null && matchedGroups[i].length > 0) {
3512         // We go through the capturing groups until we find one that captured
3513         // some digits. If none did, then we will return the empty string.
3514         number.clear();
3515         number.append(numberStr.substring(0, mStart));
3516         return matchedGroups[i];
3517       }
3518     }
3519   }
3520   return '';
3521 };
3522
3523
3524 /**
3525  * Checks to see that the region code used is valid, or if it is not valid, that
3526  * the number to parse starts with a + symbol so that we can attempt to infer
3527  * the region from the number.
3528  * @param {string} numberToParse number that we are attempting to parse.
3529  * @param {?string} defaultRegion region that we are expecting the number to be
3530  *     from.
3531  * @return {boolean} false if it cannot use the region provided and the region
3532  *     cannot be inferred.
3533  * @private
3534  */
3535 i18n.phonenumbers.PhoneNumberUtil.prototype.checkRegionForParsing_ = function(
3536     numberToParse, defaultRegion) {
3537   // If the number is null or empty, we can't infer the region.
3538   return this.isValidRegionCode_(defaultRegion) ||
3539       (numberToParse != null && numberToParse.length > 0 &&
3540           i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_.test(
3541               numberToParse));
3542 };
3543
3544
3545 /**
3546  * Parses a string and returns it in proto buffer format. This method will throw
3547  * a {@link i18n.phonenumbers.Error} if the number is not considered to be a
3548  * possible number. Note that validation of whether the number is actually a
3549  * valid number for a particular region is not performed. This can be done
3550  * separately with {@link #isValidNumber}.
3551  *
3552  * @param {?string} numberToParse number that we are attempting to parse. This
3553  *     can contain formatting such as +, ( and -, as well as a phone number
3554  *     extension. It can also be provided in RFC3966 format.
3555  * @param {?string} defaultRegion region that we are expecting the number to be
3556  *     from. This is only used if the number being parsed is not written in
3557  *     international format. The country_code for the number in this case would
3558  *     be stored as that of the default region supplied. If the number is
3559  *     guaranteed to start with a '+' followed by the country calling code, then
3560  *     'ZZ' or null can be supplied.
3561  * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
3562  *     with the parsed number.
3563  * @throws {i18n.phonenumbers.Error} if the string is not considered to be a
3564  *     viable phone number or if no default region was supplied and the number
3565  *     is not in international format (does not start with +).
3566  */
3567 i18n.phonenumbers.PhoneNumberUtil.prototype.parse = function(numberToParse,
3568                                                              defaultRegion) {
3569   return this.parseHelper_(numberToParse, defaultRegion, false, true);
3570 };
3571
3572
3573 /**
3574  * Parses a string and returns it in proto buffer format. This method differs
3575  * from {@link #parse} in that it always populates the raw_input field of the
3576  * protocol buffer with numberToParse as well as the country_code_source field.
3577  *
3578  * @param {string} numberToParse number that we are attempting to parse. This
3579  *     can contain formatting such as +, ( and -, as well as a phone number
3580  *     extension.
3581  * @param {?string} defaultRegion region that we are expecting the number to be
3582  *     from. This is only used if the number being parsed is not written in
3583  *     international format. The country calling code for the number in this
3584  *     case would be stored as that of the default region supplied.
3585  * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
3586  *     with the parsed number.
3587  * @throws {i18n.phonenumbers.Error} if the string is not considered to be a
3588  *     viable phone number or if no default region was supplied.
3589  */
3590 i18n.phonenumbers.PhoneNumberUtil.prototype.parseAndKeepRawInput =
3591     function(numberToParse, defaultRegion) {
3592
3593   if (!this.isValidRegionCode_(defaultRegion)) {
3594     if (numberToParse.length > 0 && numberToParse.charAt(0) !=
3595         i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) {
3596       throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
3597     }
3598   }
3599   return this.parseHelper_(numberToParse, defaultRegion, true, true);
3600 };
3601
3602
3603 /**
3604  * Parses a string and returns it in proto buffer format. This method is the
3605  * same as the public {@link #parse} method, with the exception that it allows
3606  * the default region to be null, for use by {@link #isNumberMatch}.
3607  *
3608  * @param {?string} numberToParse number that we are attempting to parse. This
3609  *     can contain formatting such as +, ( and -, as well as a phone number
3610  *     extension.
3611  * @param {?string} defaultRegion region that we are expecting the number to be
3612  *     from. This is only used if the number being parsed is not written in
3613  *     international format. The country calling code for the number in this
3614  *     case would be stored as that of the default region supplied.
3615  * @param {boolean} keepRawInput whether to populate the raw_input field of the
3616  *     phoneNumber with numberToParse.
3617  * @param {boolean} checkRegion should be set to false if it is permitted for
3618  *     the default coregion to be null or unknown ('ZZ').
3619  * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
3620  *     with the parsed number.
3621  * @throws {i18n.phonenumbers.Error}
3622  * @private
3623  */
3624 i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ =
3625     function(numberToParse, defaultRegion, keepRawInput, checkRegion) {
3626
3627   if (numberToParse == null) {
3628     throw i18n.phonenumbers.Error.NOT_A_NUMBER;
3629   } else if (numberToParse.length >
3630       i18n.phonenumbers.PhoneNumberUtil.MAX_INPUT_STRING_LENGTH_) {
3631     throw i18n.phonenumbers.Error.TOO_LONG;
3632   }
3633
3634   /** @type {!goog.string.StringBuffer} */
3635   var nationalNumber = new goog.string.StringBuffer();
3636   this.buildNationalNumberForParsing_(numberToParse, nationalNumber);
3637
3638   if (!i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(
3639       nationalNumber.toString())) {
3640     throw i18n.phonenumbers.Error.NOT_A_NUMBER;
3641   }
3642
3643   // Check the region supplied is valid, or that the extracted number starts
3644   // with some sort of + sign so the number's region can be determined.
3645   if (checkRegion &&
3646       !this.checkRegionForParsing_(nationalNumber.toString(), defaultRegion)) {
3647     throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
3648   }
3649
3650   /** @type {i18n.phonenumbers.PhoneNumber} */
3651   var phoneNumber = new i18n.phonenumbers.PhoneNumber();
3652   if (keepRawInput) {
3653     phoneNumber.setRawInput(numberToParse);
3654   }
3655   // Attempt to parse extension first, since it doesn't require region-specific
3656   // data and we want to have the non-normalised number here.
3657   /** @type {string} */
3658   var extension = this.maybeStripExtension(nationalNumber);
3659   if (extension.length > 0) {
3660     phoneNumber.setExtension(extension);
3661   }
3662
3663   /** @type {i18n.phonenumbers.PhoneMetadata} */
3664   var regionMetadata = this.getMetadataForRegion(defaultRegion);
3665   // Check to see if the number is given in international format so we know
3666   // whether this number is from the default region or not.
3667   /** @type {!goog.string.StringBuffer} */
3668   var normalizedNationalNumber = new goog.string.StringBuffer();
3669   /** @type {number} */
3670   var countryCode = 0;
3671   /** @type {string} */
3672   var nationalNumberStr = nationalNumber.toString();
3673   try {
3674     countryCode = this.maybeExtractCountryCode(nationalNumberStr,
3675         regionMetadata, normalizedNationalNumber, keepRawInput, phoneNumber);
3676   } catch (e) {
3677     if (e == i18n.phonenumbers.Error.INVALID_COUNTRY_CODE &&
3678         i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_
3679             .test(nationalNumberStr)) {
3680       // Strip the plus-char, and try again.
3681       nationalNumberStr = nationalNumberStr.replace(
3682           i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_, '');
3683       countryCode = this.maybeExtractCountryCode(nationalNumberStr,
3684           regionMetadata, normalizedNationalNumber, keepRawInput, phoneNumber);
3685       if (countryCode == 0) {
3686         throw e;
3687       }
3688     } else {
3689       throw e;
3690     }
3691   }
3692   if (countryCode != 0) {
3693     /** @type {string} */
3694     var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCode);
3695     if (phoneNumberRegion != defaultRegion) {
3696       // Metadata cannot be null because the country calling code is valid.
3697       regionMetadata = this.getMetadataForRegionOrCallingCode_(
3698           countryCode, phoneNumberRegion);
3699     }
3700   } else {
3701     // If no extracted country calling code, use the region supplied instead.
3702     // The national number is just the normalized version of the number we were
3703     // given to parse.
3704     i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(nationalNumber);
3705     normalizedNationalNumber.append(nationalNumber.toString());
3706     if (defaultRegion != null) {
3707       countryCode = regionMetadata.getCountryCodeOrDefault();
3708       phoneNumber.setCountryCode(countryCode);
3709     } else if (keepRawInput) {
3710       phoneNumber.clearCountryCodeSource();
3711     }
3712   }
3713   if (normalizedNationalNumber.getLength() <
3714       i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3715     throw i18n.phonenumbers.Error.TOO_SHORT_NSN;
3716   }
3717
3718   if (regionMetadata != null) {
3719     /** @type {goog.string.StringBuffer} */
3720     var carrierCode = new goog.string.StringBuffer();
3721     this.maybeStripNationalPrefixAndCarrierCode(
3722         normalizedNationalNumber, regionMetadata, carrierCode);
3723     if (keepRawInput) {
3724       phoneNumber.setPreferredDomesticCarrierCode(carrierCode.toString());
3725     }
3726   }
3727   /** @type {string} */
3728   var normalizedNationalNumberStr = normalizedNationalNumber.toString();
3729   /** @type {number} */
3730   var lengthOfNationalNumber = normalizedNationalNumberStr.length;
3731   if (lengthOfNationalNumber <
3732       i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3733     throw i18n.phonenumbers.Error.TOO_SHORT_NSN;
3734   }
3735   if (lengthOfNationalNumber >
3736       i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_) {
3737     throw i18n.phonenumbers.Error.TOO_LONG;
3738   }
3739   if (normalizedNationalNumberStr.charAt(0) == '0') {
3740     phoneNumber.setItalianLeadingZero(true);
3741   }
3742   phoneNumber.setNationalNumber(parseInt(normalizedNationalNumberStr, 10));
3743   return phoneNumber;
3744 };
3745
3746
3747 /**
3748  * Converts numberToParse to a form that we can parse and write it to
3749  * nationalNumber if it is written in RFC3966; otherwise extract a possible
3750  * number out of it and write to nationalNumber.
3751  *
3752  * @param {?string} numberToParse number that we are attempting to parse. This
3753  *     can contain formatting such as +, ( and -, as well as a phone number
3754  *     extension.
3755  * @param {!goog.string.StringBuffer} nationalNumber a string buffer for storing
3756  *     the national significant number.
3757  * @private
3758  */
3759 i18n.phonenumbers.PhoneNumberUtil.prototype.buildNationalNumberForParsing_ =
3760     function(numberToParse, nationalNumber) {
3761
3762   /** @type {number} */
3763   var indexOfPhoneContext = numberToParse.indexOf(
3764       i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_);
3765   if (indexOfPhoneContext > 0) {
3766     var phoneContextStart = indexOfPhoneContext +
3767         i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_.length;
3768     // If the phone context contains a phone number prefix, we need to capture
3769     // it, whereas domains will be ignored.
3770     if (numberToParse.charAt(phoneContextStart) ==
3771         i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) {
3772       // Additional parameters might follow the phone context. If so, we will
3773       // remove them here because the parameters after phone context are not
3774       // important for parsing the phone number.
3775       var phoneContextEnd = numberToParse.indexOf(';', phoneContextStart);
3776       if (phoneContextEnd > 0) {
3777         nationalNumber.append(numberToParse.substring(phoneContextStart,
3778             phoneContextEnd));
3779       } else {
3780         nationalNumber.append(numberToParse.substring(phoneContextStart));
3781       }
3782     }
3783
3784     // Now append everything between the "tel:" prefix and the phone-context.
3785     // This should include the national number, an optional extension or
3786     // isdn-subaddress component.
3787     nationalNumber.append(numberToParse.substring(
3788         numberToParse.indexOf(
3789             i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_) +
3790         i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_.length,
3791         indexOfPhoneContext));
3792   } else {
3793     // Extract a possible number from the string passed in (this strips leading
3794     // characters that could not be the start of a phone number.)
3795     nationalNumber.append(
3796         i18n.phonenumbers.PhoneNumberUtil.extractPossibleNumber(numberToParse));
3797   }
3798
3799   // Delete the isdn-subaddress and everything after it if it is present.
3800   // Note extension won't appear at the same time with isdn-subaddress
3801   // according to paragraph 5.3 of the RFC3966 spec,
3802   /** @type {string} */
3803   var nationalNumberStr = nationalNumber.toString();
3804   var indexOfIsdn = nationalNumberStr.indexOf(
3805       i18n.phonenumbers.PhoneNumberUtil.RFC3966_ISDN_SUBADDRESS_);
3806   if (indexOfIsdn > 0) {
3807     nationalNumber.clear();
3808     nationalNumber.append(nationalNumberStr.substring(0, indexOfIsdn));
3809   }
3810   // If both phone context and isdn-subaddress are absent but other
3811   // parameters are present, the parameters are left in nationalNumber. This
3812   // is because we are concerned about deleting content from a potential
3813   // number string when there is no strong evidence that the number is
3814   // actually written in RFC3966.
3815 };
3816
3817
3818 /**
3819  * Takes two phone numbers and compares them for equality.
3820  *
3821  * <p>Returns EXACT_MATCH if the country_code, NSN, presence of a leading zero
3822  * for Italian numbers and any extension present are the same. Returns NSN_MATCH
3823  * if either or both has no region specified, and the NSNs and extensions are
3824  * the same. Returns SHORT_NSN_MATCH if either or both has no region specified,
3825  * or the region specified is the same, and one NSN could be a shorter version
3826  * of the other number. This includes the case where one has an extension
3827  * specified, and the other does not. Returns NO_MATCH otherwise. For example,
3828  * the numbers +1 345 657 1234 and 657 1234 are a SHORT_NSN_MATCH. The numbers
3829  * +1 345 657 1234 and 345 657 are a NO_MATCH.
3830  *
3831  * @param {i18n.phonenumbers.PhoneNumber|string} firstNumberIn first number to
3832  *     compare. If it is a string it can contain formatting, and can have
3833  *     country calling code specified with + at the start.
3834  * @param {i18n.phonenumbers.PhoneNumber|string} secondNumberIn second number to
3835  *     compare. If it is a string it can contain formatting, and can have
3836  *     country calling code specified with + at the start.
3837  * @return {i18n.phonenumbers.PhoneNumberUtil.MatchType} NOT_A_NUMBER, NO_MATCH,
3838  *     SHORT_NSN_MATCH, NSN_MATCH or EXACT_MATCH depending on the level of
3839  *     equality of the two numbers, described in the method definition.
3840  */
3841 i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatch =
3842     function(firstNumberIn, secondNumberIn) {
3843
3844   // If the input arguements are strings parse them to a proto buffer format.
3845   // Else make copies of the phone numbers so that the numbers passed in are not
3846   // edited.
3847   /** @type {i18n.phonenumbers.PhoneNumber} */
3848   var firstNumber;
3849   /** @type {i18n.phonenumbers.PhoneNumber} */
3850   var secondNumber;
3851   if (typeof firstNumberIn == 'string') {
3852     // First see if the first number has an implicit country calling code, by
3853     // attempting to parse it.
3854     try {
3855       firstNumber = this.parse(
3856           firstNumberIn, i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_);
3857     } catch (e) {
3858       if (e != i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) {
3859         return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3860       }
3861       // The first number has no country calling code. EXACT_MATCH is no longer
3862       // possible. We parse it as if the region was the same as that for the
3863       // second number, and if EXACT_MATCH is returned, we replace this with
3864       // NSN_MATCH.
3865       if (typeof secondNumberIn != 'string') {
3866         /** @type {string} */
3867         var secondNumberRegion = this.getRegionCodeForCountryCode(
3868             secondNumberIn.getCountryCodeOrDefault());
3869         if (secondNumberRegion !=
3870             i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_) {
3871           try {
3872             firstNumber = this.parse(firstNumberIn, secondNumberRegion);
3873           } catch (e2) {
3874             return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3875           }
3876           /** @type {i18n.phonenumbers.PhoneNumberUtil.MatchType} */
3877           var match = this.isNumberMatch(firstNumber, secondNumberIn);
3878           if (match ==
3879               i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH) {
3880             return i18n.phonenumbers.PhoneNumberUtil.MatchType.NSN_MATCH;
3881           }
3882           return match;
3883         }
3884       }
3885       // If the second number is a string or doesn't have a valid country
3886       // calling code, we parse the first number without country calling code.
3887       try {
3888         firstNumber = this.parseHelper_(firstNumberIn, null, false, false);
3889       } catch (e2) {
3890         return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3891       }
3892     }
3893   } else {
3894     firstNumber = firstNumberIn.clone();
3895   }
3896   if (typeof secondNumberIn == 'string') {
3897     try {
3898       secondNumber = this.parse(
3899           secondNumberIn, i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_);
3900       return this.isNumberMatch(firstNumberIn, secondNumber);
3901     } catch (e) {
3902       if (e != i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) {
3903         return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3904       }
3905       return this.isNumberMatch(secondNumberIn, firstNumber);
3906     }
3907   } else {
3908     secondNumber = secondNumberIn.clone();
3909   }
3910   // First clear raw_input, country_code_source and
3911   // preferred_domestic_carrier_code fields and any empty-string extensions so
3912   // that we can use the proto-buffer equality method.
3913   firstNumber.clearRawInput();
3914   firstNumber.clearCountryCodeSource();
3915   firstNumber.clearPreferredDomesticCarrierCode();
3916   secondNumber.clearRawInput();
3917   secondNumber.clearCountryCodeSource();
3918   secondNumber.clearPreferredDomesticCarrierCode();
3919   if (firstNumber.hasExtension() && firstNumber.getExtension().length == 0) {
3920     firstNumber.clearExtension();
3921   }
3922   if (secondNumber.hasExtension() && secondNumber.getExtension().length == 0) {
3923     secondNumber.clearExtension();
3924   }
3925
3926   // Early exit if both had extensions and these are different.
3927   if (firstNumber.hasExtension() && secondNumber.hasExtension() &&
3928       firstNumber.getExtension() != secondNumber.getExtension()) {
3929     return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
3930   }
3931   /** @type {number} */
3932   var firstNumberCountryCode = firstNumber.getCountryCodeOrDefault();
3933   /** @type {number} */
3934   var secondNumberCountryCode = secondNumber.getCountryCodeOrDefault();
3935   // Both had country_code specified.
3936   if (firstNumberCountryCode != 0 && secondNumberCountryCode != 0) {
3937     if (firstNumber.equals(secondNumber)) {
3938       return i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH;
3939     } else if (firstNumberCountryCode == secondNumberCountryCode &&
3940         this.isNationalNumberSuffixOfTheOther_(firstNumber, secondNumber)) {
3941       // A SHORT_NSN_MATCH occurs if there is a difference because of the
3942       // presence or absence of an 'Italian leading zero', the presence or
3943       // absence of an extension, or one NSN being a shorter variant of the
3944       // other.
3945       return i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH;
3946     }
3947     // This is not a match.
3948     return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
3949   }
3950   // Checks cases where one or both country_code fields were not specified. To
3951   // make equality checks easier, we first set the country_code fields to be
3952   // equal.
3953   firstNumber.setCountryCode(0);
3954   secondNumber.setCountryCode(0);
3955   // If all else was the same, then this is an NSN_MATCH.
3956   if (firstNumber.equals(secondNumber)) {
3957     return i18n.phonenumbers.PhoneNumberUtil.MatchType.NSN_MATCH;
3958   }
3959   if (this.isNationalNumberSuffixOfTheOther_(firstNumber, secondNumber)) {
3960     return i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH;
3961   }
3962   return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
3963 };
3964
3965
3966 /**
3967  * Returns true when one national number is the suffix of the other or both are
3968  * the same.
3969  *
3970  * @param {i18n.phonenumbers.PhoneNumber} firstNumber the first PhoneNumber
3971  *     object.
3972  * @param {i18n.phonenumbers.PhoneNumber} secondNumber the second PhoneNumber
3973  *     object.
3974  * @return {boolean} true if one PhoneNumber is the suffix of the other one.
3975  * @private
3976  */
3977 i18n.phonenumbers.PhoneNumberUtil.prototype.isNationalNumberSuffixOfTheOther_ =
3978     function(firstNumber, secondNumber) {
3979
3980   /** @type {string} */
3981   var firstNumberNationalNumber = '' + firstNumber.getNationalNumber();
3982   /** @type {string} */
3983   var secondNumberNationalNumber = '' + secondNumber.getNationalNumber();
3984   // Note that endsWith returns true if the numbers are equal.
3985   return goog.string.endsWith(firstNumberNationalNumber,
3986                               secondNumberNationalNumber) ||
3987          goog.string.endsWith(secondNumberNationalNumber,
3988                               firstNumberNationalNumber);
3989 };
3990
3991
3992 /**
3993  * Returns true if the number can be dialled from outside the region, or
3994  * unknown. If the number can only be dialled from within the region, returns
3995  * false. Does not check the number is a valid number.
3996  * TODO: Make this method public when we have enough metadata to make it
3997  * worthwhile. Currently visible for testing purposes only.
3998  *
3999  * @param {i18n.phonenumbers.PhoneNumber} number the phone-number for which we
4000  *     want to know whether it is diallable from outside the region.
4001  * @return {boolean} true if the number can only be dialled from within the
4002  *     country.
4003  */
4004 i18n.phonenumbers.PhoneNumberUtil.prototype.canBeInternationallyDialled =
4005     function(number) {
4006   /** @type {i18n.phonenumbers.PhoneMetadata} */
4007   var metadata = this.getMetadataForRegion(this.getRegionCodeForNumber(number));
4008   if (metadata == null) {
4009     // Note numbers belonging to non-geographical entities (e.g. +800 numbers)
4010     // are always internationally diallable, and will be caught here.
4011     return true;
4012   }
4013   /** @type {string} */
4014   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
4015   return !this.isNumberMatchingDesc_(nationalSignificantNumber,
4016                                      metadata.getNoInternationalDialling());
4017 };
4018
4019
4020 /**
4021  * Check whether the entire input sequence can be matched against the regular
4022  * expression.
4023  *
4024  * @param {!RegExp|string} regex the regular expression to match against.
4025  * @param {string} str the string to test.
4026  * @return {boolean} true if str can be matched entirely against regex.
4027  * @private
4028  */
4029 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_ = function(regex, str) {
4030   /** @type {Array.<string>} */
4031   var matchedGroups = (typeof regex == 'string') ?
4032       str.match('^(?:' + regex + ')$') : str.match(regex);
4033   if (matchedGroups && matchedGroups[0].length == str.length) {
4034     return true;
4035   }
4036   return false;
4037 };