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