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