summaryrefslogtreecommitdiff
path: root/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
diff options
context:
space:
mode:
Diffstat (limited to 'libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java')
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java84
1 files changed, 55 insertions, 29 deletions
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
index 705d657b..90a969e2 100644
--- a/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
@@ -313,9 +313,9 @@ public class PhoneNumberUtil {
// One-character symbols that can be used to indicate an extension.
String singleExtnSymbolsForMatching = "x\uFF58#\uFF03~\uFF5E";
// For parsing, we are slightly more lenient in our interpretation than for matching. Here we
- // allow a "comma" as a possible extension indicator. When matching, this is hardly ever used to
- // indicate this.
- String singleExtnSymbolsForParsing = "," + singleExtnSymbolsForMatching;
+ // allow "comma" and "semicolon" as possible extension indicators. When matching, these are
+ // hardly ever used to indicate this.
+ String singleExtnSymbolsForParsing = ",;" + singleExtnSymbolsForMatching;
EXTN_PATTERNS_FOR_PARSING = createExtnPattern(singleExtnSymbolsForParsing);
EXTN_PATTERNS_FOR_MATCHING = createExtnPattern(singleExtnSymbolsForMatching);
@@ -328,9 +328,9 @@ public class PhoneNumberUtil {
private static String createExtnPattern(String singleExtnSymbols) {
// There are three regular expressions here. The first covers RFC 3966 format, where the
// extension is added using ";ext=". The second more generic one starts with optional white
- // space and ends with an optional full stop (.), followed by zero or more spaces/tabs and then
- // the numbers themselves. The other one covers the special case of American numbers where the
- // extension is written with a hash at the end, such as "- 503#".
+ // space and ends with an optional full stop (.), followed by zero or more spaces/tabs/commas
+ // and then the numbers themselves. The other one covers the special case of American numbers
+ // where the extension is written with a hash at the end, such as "- 503#"
// Note that the only capturing groups should be around the digits that you want to capture as
// part of the extension, or else parsing will fail!
// Canonical-equivalence doesn't seem to be an option with Android java, so we allow two options
@@ -440,9 +440,25 @@ public class PhoneNumberUtil {
* Possible outcomes when testing if a PhoneNumber is possible.
*/
public enum ValidationResult {
+ /** The number length matches that of valid numbers for this region. */
IS_POSSIBLE,
+ /**
+ * The number length matches that of local numbers for this region only (i.e. numbers that may
+ * be able to be dialled within an area, but do not have all the information to be dialled from
+ * anywhere inside or outside the country).
+ */
+ IS_POSSIBLE_LOCAL_ONLY,
+ /** The number has an invalid country calling code. */
INVALID_COUNTRY_CODE,
+ /** The number is shorter than all valid numbers for this region. */
TOO_SHORT,
+ /**
+ * The number is longer than the shortest valid numbers for this region, shorter than the
+ * longest valid numbers for this region, and does not itself have a number length that matches
+ * valid numbers for this region.
+ */
+ INVALID_LENGTH,
+ /** The number is longer than all valid numbers for this region. */
TOO_LONG,
}
@@ -728,7 +744,7 @@ public class PhoneNumberUtil {
* @param number a string of characters representing a phone number
* @return the normalized string version of the phone number
*/
- static String normalizeDiallableCharsOnly(String number) {
+ public static String normalizeDiallableCharsOnly(String number) {
return normalizeHelper(number, DIALLABLE_CHAR_MAPPINGS, true /* remove non matches */);
}
@@ -2135,7 +2151,11 @@ public class PhoneNumberUtil {
/**
* Tests whether a phone number matches a valid pattern. Note this doesn't verify the number
- * is actually in use, which is impossible to tell by just looking at a number itself.
+ * is actually in use, which is impossible to tell by just looking at a number itself. It only
+ * verifies whether the parsed, canonicalised number is valid: not whether a particular series of
+ * digits entered by the user is diallable from the region provided when parsing. For example, the
+ * number +41 (0) 78 927 2696 can be parsed into a number with country code "41" and national
+ * significant number "789272696". This is valid, while the original string is not diallable.
*
* @param number the phone number that we want to validate
* @return a boolean that indicates whether the number is of a valid pattern
@@ -2923,6 +2943,9 @@ public class PhoneNumberUtil {
* parse() method, with the exception that it allows the default region to be null, for use by
* isNumberMatch(). checkRegion should be set to false if it is permitted for the default region
* to be null or unknown ("ZZ").
+ *
+ * Note if any new field is added to this method that should always be filled in, even when
+ * keepRawInput is false, it should also be handled in the copyCoreFieldsOnly() method.
*/
private void parseHelper(String numberToParse, String defaultRegion, boolean keepRawInput,
boolean checkRegion, PhoneNumber phoneNumber)
@@ -3086,6 +3109,26 @@ public class PhoneNumberUtil {
}
/**
+ * Returns a new phone number containing only the fields needed to uniquely identify a phone
+ * number, rather than any fields that capture the context in which the phone number was created.
+ * These fields correspond to those set in parse() rather than parseHelper().
+ */
+ private static PhoneNumber copyCoreFieldsOnly(PhoneNumber phoneNumberIn) {
+ PhoneNumber phoneNumber = new PhoneNumber();
+ phoneNumber.setCountryCode(phoneNumberIn.getCountryCode());
+ phoneNumber.setNationalNumber(phoneNumberIn.getNationalNumber());
+ if (phoneNumberIn.getExtension().length() > 0) {
+ phoneNumber.setExtension(phoneNumberIn.getExtension());
+ }
+ if (phoneNumberIn.isItalianLeadingZero()) {
+ phoneNumber.setItalianLeadingZero(true);
+ // This field is only relevant if there are leading zeros at all.
+ phoneNumber.setNumberOfLeadingZeros(phoneNumberIn.getNumberOfLeadingZeros());
+ }
+ return phoneNumber;
+ }
+
+ /**
* Takes two phone numbers and compares them for equality.
*
* <p>Returns EXACT_MATCH if the country_code, NSN, presence of a leading zero for Italian numbers
@@ -3106,27 +3149,10 @@ public class PhoneNumberUtil {
* of the two numbers, described in the method definition.
*/
public MatchType isNumberMatch(PhoneNumber firstNumberIn, PhoneNumber secondNumberIn) {
- // Make copies of the phone number so that the numbers passed in are not edited.
- PhoneNumber firstNumber = new PhoneNumber();
- firstNumber.mergeFrom(firstNumberIn);
- PhoneNumber secondNumber = new PhoneNumber();
- secondNumber.mergeFrom(secondNumberIn);
- // First clear raw_input, country_code_source and preferred_domestic_carrier_code fields and any
- // empty-string extensions so that we can use the proto-buffer equality method.
- firstNumber.clearRawInput();
- firstNumber.clearCountryCodeSource();
- firstNumber.clearPreferredDomesticCarrierCode();
- secondNumber.clearRawInput();
- secondNumber.clearCountryCodeSource();
- secondNumber.clearPreferredDomesticCarrierCode();
- if (firstNumber.hasExtension()
- && firstNumber.getExtension().length() == 0) {
- firstNumber.clearExtension();
- }
- if (secondNumber.hasExtension()
- && secondNumber.getExtension().length() == 0) {
- secondNumber.clearExtension();
- }
+ // We only care about the fields that uniquely define a number, so we copy these across
+ // explicitly.
+ PhoneNumber firstNumber = copyCoreFieldsOnly(firstNumberIn);
+ PhoneNumber secondNumber = copyCoreFieldsOnly(secondNumberIn);
// Early exit if both had extensions and these are different.
if (firstNumber.hasExtension() && secondNumber.hasExtension()
&& !firstNumber.getExtension().equals(secondNumber.getExtension())) {