|
|
|
@ -1818,6 +1818,62 @@ public class PhoneNumberUtil { |
|
|
|
return getExampleNumberForType(regionCode, PhoneNumberType.FIXED_LINE); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Gets an invalid number for the specified region. This is useful for unit-testing purposes, |
|
|
|
* where you want to test what will happen with an invalid number. Note that the number that is |
|
|
|
* returned will always be able to be parsed and will have the correct country code. It may also |
|
|
|
* be a valid *short* number/code for this region. Validity checking such numbers is handled with |
|
|
|
* {@link com.google.i18n.phonenumbers.ShortNumberInfo}. |
|
|
|
* |
|
|
|
* @param regionCode the region for which an example number is needed |
|
|
|
* @return an invalid number for the specified region. Returns null when an unsupported region or |
|
|
|
* the region 001 (Earth) is passed in. |
|
|
|
*/ |
|
|
|
public PhoneNumber getInvalidExampleNumber(String regionCode) { |
|
|
|
if (!isValidRegionCode(regionCode)) { |
|
|
|
logger.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode); |
|
|
|
return null; |
|
|
|
} |
|
|
|
// We start off with a valid fixed-line number since every country supports this. Alternatively |
|
|
|
// we could start with a different number type, since fixed-line numbers typically have a wide |
|
|
|
// breadth of valid number lengths and we may have to make it very short before we get an |
|
|
|
// invalid number. |
|
|
|
PhoneNumberDesc desc = getNumberDescByType(getMetadataForRegion(regionCode), |
|
|
|
PhoneNumberType.FIXED_LINE); |
|
|
|
if (desc.exampleNumber.equals("")) { |
|
|
|
// This shouldn't happen; we have a test for this. |
|
|
|
return null; |
|
|
|
} |
|
|
|
String exampleNumber = desc.exampleNumber; |
|
|
|
// Try and make the number invalid. We do this by changing the length. We try reducing the |
|
|
|
// length of the number, since currently no region has a number that is the same length as |
|
|
|
// MIN_LENGTH_FOR_NSN. This is probably quicker than making the number longer, which is another |
|
|
|
// alternative. We could also use the possible number pattern to extract the possible lengths of |
|
|
|
// the number to make this faster, but this method is only for unit-testing so simplicity is |
|
|
|
// preferred to performance. We don't want to return a number that can't be parsed, so we check |
|
|
|
// the number is long enough. We try all possible lengths because phone number plans often have |
|
|
|
// overlapping prefixes so the number 123456 might be valid as a fixed-line number, and 12345 as |
|
|
|
// a mobile number. It would be faster to loop in a different order, but we prefer numbers that |
|
|
|
// look closer to real numbers (and it gives us a variety of different lengths for the resulting |
|
|
|
// phone numbers - otherwise they would all be MIN_LENGTH_FOR_NSN digits long.) |
|
|
|
for (int phoneNumberLength = exampleNumber.length() - 1; |
|
|
|
phoneNumberLength >= MIN_LENGTH_FOR_NSN; |
|
|
|
phoneNumberLength--) { |
|
|
|
String numberToTry = exampleNumber.substring(0, phoneNumberLength); |
|
|
|
try { |
|
|
|
PhoneNumber possiblyValidNumber = parse(numberToTry, regionCode); |
|
|
|
if (!isValidNumber(possiblyValidNumber)) { |
|
|
|
return possiblyValidNumber; |
|
|
|
} |
|
|
|
} catch (NumberParseException e) { |
|
|
|
// Shouldn't happen: we have already checked the length, we know example numbers have |
|
|
|
// only valid digits, and we know the region code is fine. |
|
|
|
} |
|
|
|
} |
|
|
|
// We have a test to check that this doesn't happen for any of our supported regions. |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Gets a valid number for the specified region and number type. |
|
|
|
* |
|
|
|
@ -1845,6 +1901,37 @@ public class PhoneNumberUtil { |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Gets a valid number for the specified number type (it may belong to any country). |
|
|
|
* |
|
|
|
* @param type the type of number that is needed |
|
|
|
* @return a valid number for the specified type. Returns null when the metadata |
|
|
|
* does not contain such information. This should only happen when no numbers of this type are |
|
|
|
* allocated anywhere in the world anymore. |
|
|
|
*/ |
|
|
|
public PhoneNumber getExampleNumberForType(PhoneNumberType type) { |
|
|
|
for (String regionCode : getSupportedRegions()) { |
|
|
|
PhoneNumber exampleNumber = getExampleNumberForType(regionCode, type); |
|
|
|
if (exampleNumber != null) { |
|
|
|
return exampleNumber; |
|
|
|
} |
|
|
|
} |
|
|
|
// If there wasn't an example number for a region, try the non-geographical entities. |
|
|
|
for (int countryCallingCode : getSupportedGlobalNetworkCallingCodes()) { |
|
|
|
PhoneNumberDesc desc = getNumberDescByType( |
|
|
|
getMetadataForNonGeographicalRegion(countryCallingCode), type); |
|
|
|
try { |
|
|
|
if (!desc.exampleNumber.equals("")) { |
|
|
|
return parse("+" + countryCallingCode + desc.exampleNumber, UNKNOWN_REGION); |
|
|
|
} |
|
|
|
} catch (NumberParseException e) { |
|
|
|
logger.log(Level.SEVERE, e.toString()); |
|
|
|
} |
|
|
|
} |
|
|
|
// There are no example numbers of this type for any country in the library. |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Gets a valid number for the specified country calling code for a non-geographical entity. |
|
|
|
* |
|
|
|
@ -1859,7 +1946,7 @@ public class PhoneNumberUtil { |
|
|
|
PhoneNumberDesc desc = metadata.generalDesc; |
|
|
|
try { |
|
|
|
if (!desc.exampleNumber.equals("")) { |
|
|
|
return parse("+" + countryCallingCode + desc.exampleNumber, "ZZ"); |
|
|
|
return parse("+" + countryCallingCode + desc.exampleNumber, UNKNOWN_REGION); |
|
|
|
} |
|
|
|
} catch (NumberParseException e) { |
|
|
|
logger.log(Level.SEVERE, e.toString()); |
|
|
|
@ -2670,10 +2757,18 @@ public class PhoneNumberUtil { |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Parses a string and returns it in proto buffer format. This method will throw a |
|
|
|
* {@link com.google.i18n.phonenumbers.NumberParseException} if the number is not considered to be |
|
|
|
* a possible number. Note that validation of whether the number is actually a valid number for a |
|
|
|
* particular region is not performed. This can be done separately with {@link #isValidNumber}. |
|
|
|
* Parses a string and returns it as a phone number in proto buffer format. The method is quite |
|
|
|
* lenient and looks for a number in the input text (raw input) and does not check whether the |
|
|
|
* string is definitely only a phone number. To do this, it ignores punctuation and white-space, |
|
|
|
* as well as any text before the number (e.g. a leading “Tel: ”) and trims the non-number bits. |
|
|
|
* It will accept a number in any format (E164, national, international etc), assuming it can be |
|
|
|
* interpreted with the defaultRegion supplied. It also attempts to convert any alpha characters |
|
|
|
* into digits if it thinks this is a vanity number of the type "1800 MICROSOFT". |
|
|
|
* |
|
|
|
* <p> This method will throw a {@link com.google.i18n.phonenumbers.NumberParseException} if the |
|
|
|
* number is not considered to be a possible number. Note that validation of whether the number |
|
|
|
* is actually a valid number for a particular region is not performed. This can be done |
|
|
|
* separately with {@link #isValidNumber}. |
|
|
|
* |
|
|
|
* @param numberToParse number that we are attempting to parse. This can contain formatting |
|
|
|
* such as +, ( and -, as well as a phone number extension. It can also |
|
|
|
@ -2685,9 +2780,10 @@ public class PhoneNumberUtil { |
|
|
|
* start with a '+' followed by the country calling code, then |
|
|
|
* "ZZ" or null can be supplied. |
|
|
|
* @return a phone number proto buffer filled with the parsed number |
|
|
|
* @throws NumberParseException if the string is not considered to be a viable phone number or if |
|
|
|
* no default region was supplied and the number is not in |
|
|
|
* international format (does not start with +) |
|
|
|
* @throws NumberParseException if the string is not considered to be a viable phone number (e.g. |
|
|
|
* too few or too many digits) or if no default region was supplied |
|
|
|
* and the number is not in international format (does not start |
|
|
|
* with +) |
|
|
|
*/ |
|
|
|
public PhoneNumber parse(String numberToParse, String defaultRegion) |
|
|
|
throws NumberParseException { |
|
|
|
|