예제 #1
0
        /**
         * Parses a phone number from the {@code candidate} using {@link PhoneNumberUtil#parse} and
         * verifies it matches the requested {@link #leniency}. If parsing and verification succeed, a
         * corresponding {@link PhoneNumberMatch} is returned, otherwise this method returns null.
         *
         * @param candidate  the candidate match
         * @param offset  the offset of {@code candidate} within {@link #text}
         * @return  the parsed and validated phone number match, or null
         */
        private PhoneNumberMatch parseAndVerify(String candidate, int offset)
        {
            try {
                // Check the candidate doesn't contain any formatting which would indicate that it really
                // isn't a phone number.
                if (!MATCHING_BRACKETS.MatchWhole(candidate).Success || PUB_PAGES.Match(candidate).Success)
                {
                    return(null);
                }

                // If leniency is set to VALID or stricter, we also want to skip numbers that are surrounded
                // by Latin alphabetic characters, to skip cases like abc8005001234 or 8005001234def.
                if (leniency.CompareTo(PhoneNumberUtil.Leniency.VALID) >= 0)
                {
                    // If the candidate is not at the start of the text, and does not start with phone-number
                    // punctuation, check the previous character.
                    if (offset > 0 && !LEAD_CLASS.MatchBeginning(candidate).Success)
                    {
                        char previousChar = text[offset - 1];
                        // We return null if it is a latin letter or an invalid punctuation symbol.
                        if (isInvalidPunctuationSymbol(previousChar) || isLatinLetter(previousChar))
                        {
                            return(null);
                        }
                    }
                    int lastCharIndex = offset + candidate.Length;
                    if (lastCharIndex < text.Length)
                    {
                        char nextChar = text[lastCharIndex];
                        if (isInvalidPunctuationSymbol(nextChar) || isLatinLetter(nextChar))
                        {
                            return(null);
                        }
                    }
                }

                PhoneNumber number = phoneUtil.parseAndKeepRawInput(candidate, preferredRegion);

                // Check Israel * numbers: these are a special case in that they are four-digit numbers that
                // our library supports, but they can only be dialled with a leading *. Since we don't
                // actually store or detect the * in our phone number library, this means in practice we
                // detect most four digit numbers as being valid for Israel. We are considering moving these
                // numbers to ShortNumberInfo instead, in which case this problem would go away, but in the
                // meantime we want to restrict the false matches so we only allow these numbers if they are
                // preceded by a star. We enforce this for all leniency levels even though these numbers are
                // technically accepted by isPossibleNumber and isValidNumber since we consider it to be a
                // deficiency in those methods that they accept these numbers without the *.
                // TODO: Remove this or make it significantly less hacky once we've decided how to
                // handle these short codes going forward in ShortNumberInfo. We could use the formatting
                // rules for instance, but that would be slower.
                if (phoneUtil.getRegionCodeForCountryCode(number.getCountryCode()).Equals("IL") &&
                    phoneUtil.getNationalSignificantNumber(number).Length == 4 &&
                    (offset == 0 || (offset > 0 && text[offset - 1] != '*')))
                {
                    // No match.
                    return(null);
                }

                if (leniency.verify(number, candidate, phoneUtil))
                {
                    // We used parseAndKeepRawInput to create this number, but for now we don't return the extra
                    // values parsed. TODO: stop clearing all values here and switch all users over
                    // to using rawInput() rather than the rawString() of PhoneNumberMatch.
                    number.clearCountryCodeSource();
                    number.clearRawInput();
                    number.clearPreferredDomesticCarrierCode();
                    return(new PhoneNumberMatch(offset, candidate, number));
                }
            } catch (NumberParseException) {
                // ignore and continue
            }
            return(null);
        }