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