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