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