private bool matchesEmergencyNumberHelper(String number, String regionCode, bool allowPrefixMatch) { number = PhoneNumberUtil.extractPossibleNumber(number); if (PhoneNumberUtil.PLUS_CHARS_PATTERN.MatchBeginning(number).Success) { // Returns false if the number starts with a plus sign. We don't believe dialing the country // code before emergency numbers (e.g. +1911) works, but later, if that proves to work, we can // add additional logic here to handle it. return(false); } PhoneMetadata metadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); if (metadata == null || !metadata.HasEmergency()) { return(false); } var emergencyNumberPattern = new JavaRegex(metadata.getEmergency().getNationalNumberPattern()); String normalizedNumber = PhoneNumberUtil.normalizeDigitsOnly(number); return((!allowPrefixMatch || REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.Contains(regionCode)) ? emergencyNumberPattern.MatchWhole(normalizedNumber).Success : emergencyNumberPattern.MatchBeginning(normalizedNumber).Success); }
internal static bool checkNumberGroupingIsValid( PhoneNumber number, String candidate, PhoneNumberUtil util, NumberGroupingChecker checker) { // TODO: Evaluate how this works for other locales (testing has been limited to NANPA regions) // and optimise if necessary. StringBuilder normalizedCandidate = PhoneNumberUtil.normalizeDigits(candidate, true /* keep non-digits */); String[] formattedNumberGroups = getNationalNumberGroups(util, number, null); if (checker.checkGroups(util, number, normalizedCandidate, formattedNumberGroups)) { return(true); } // If this didn't pass, see if there are any alternate formats, and try them instead. PhoneMetadata alternateFormats = MetadataManager.getAlternateFormatsForCountry(number.getCountryCode()); if (alternateFormats != null) { foreach (NumberFormat alternateFormat in alternateFormats.numberFormats()) { formattedNumberGroups = getNationalNumberGroups(util, number, alternateFormat); if (checker.checkGroups(util, number, normalizedCandidate, formattedNumberGroups)) { return(true); } } } return(false); }
/** * Gets a valid short number for the specified cost category. * * @param regionCode the region for which an example short number is needed * @param cost the cost category of number that is needed * @return a valid short number for the specified region and cost category. Returns an empty * string when the metadata does not contain such information, or the cost is UNKNOWN_COST. */ // @VisibleForTesting internal String getExampleShortNumberForCost(String regionCode, ShortNumberCost cost) { PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); if (phoneMetadata == null) { return(""); } PhoneNumberDesc desc = null; switch (cost) { case ShortNumberCost.TOLL_FREE: desc = phoneMetadata.getTollFree(); break; case ShortNumberCost.STANDARD_RATE: desc = phoneMetadata.getStandardRate(); break; case ShortNumberCost.PREMIUM_RATE: desc = phoneMetadata.getPremiumRate(); break; default: // UNKNOWN_COST numbers are computed by the process of elimination from the other cost // categories. break; } if (desc != null && desc.HasExampleNumber()) { return(desc.getExampleNumber()); } return(""); }
/** * Extracts the country calling code from the beginning of nationalNumber to * prefixBeforeNationalNumber when they are available, and places the remaining input into * nationalNumber. * * @return true when a valid country calling code can be found. */ private bool attemptToExtractCountryCallingCode() { if (nationalNumber.Length == 0) { return(false); } StringBuilder numberWithoutCountryCallingCode = new StringBuilder(); int countryCode = phoneUtil.extractCountryCode(nationalNumber, numberWithoutCountryCallingCode); if (countryCode == 0) { return(false); } nationalNumber.Length = 0; nationalNumber.Append(numberWithoutCountryCallingCode); String newRegionCode = phoneUtil.getRegionCodeForCountryCode(countryCode); if (PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY.Equals(newRegionCode)) { currentMetadata = phoneUtil.getMetadataForNonGeographicalRegion(countryCode); } else if (!newRegionCode.Equals(defaultCountry)) { currentMetadata = getMetadataForRegion(newRegionCode); } String countryCodeString = countryCode.ToString(); prefixBeforeNationalNumber.Append(countryCodeString).Append(SEPARATOR_BEFORE_NATIONAL_NUMBER); // When we have successfully extracted the IDD, the previously extracted NDD should be cleared // because it is no longer valid. extractedNationalPrefix = ""; return(true); }
// Helper method to get the region code for a given phone number, from a list of possible region // codes. If the list contains more than one region, the first region for which the number is // valid is returned. private String getRegionCodeForShortNumberFromRegionList(PhoneNumber number, List <String> regionCodes) { if (regionCodes.Count == 0) { return(null); } else if (regionCodes.Count == 1) { return(regionCodes[0]); } String nationalNumber = phoneUtil.getNationalSignificantNumber(number); foreach (String regionCode in regionCodes) { PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); if (phoneMetadata != null && phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getShortCode())) { // The number is valid for this region. return(regionCode); } } return(null); }
/** * Gets the expected cost category of a short number when dialled from a region (however, nothing * is implied about its validity). If it is important that the number is valid, then its validity * must first be checked using {@link isValidShortNumberForRegion}. Note that emergency numbers * are always considered toll-free. Example usage: * <pre>{@code * ShortNumberInfo shortInfo = ShortNumberInfo.getInstance(); * String shortNumber = "110"; * String regionCode = "FR"; * if (shortInfo.isValidShortNumberForRegion(shortNumber, regionCode)) { * ShortNumberInfo.ShortNumberCost cost = shortInfo.getExpectedCostForRegion(shortNumber, * regionCode); * // Do something with the cost information here. * }}</pre> * * @param shortNumber the short number for which we want to know the expected cost category, * as a string * @param regionDialingFrom the region from which the number is dialed * @return the expected cost category for that region of the short number. Returns UNKNOWN_COST if * the number does not match a cost category. Note that an invalid number may match any cost * category. */ public ShortNumberCost getExpectedCostForRegion(String shortNumber, String regionDialingFrom) { // Note that regionDialingFrom may be null, in which case phoneMetadata will also be null. PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion( regionDialingFrom); if (phoneMetadata == null) { return(ShortNumberCost.UNKNOWN_COST); } // The cost categories are tested in order of decreasing expense, since if for some reason the // patterns overlap the most expensive matching cost category should be returned. if (phoneUtil.isNumberMatchingDesc(shortNumber, phoneMetadata.getPremiumRate())) { return(ShortNumberCost.PREMIUM_RATE); } if (phoneUtil.isNumberMatchingDesc(shortNumber, phoneMetadata.getStandardRate())) { return(ShortNumberCost.STANDARD_RATE); } if (phoneUtil.isNumberMatchingDesc(shortNumber, phoneMetadata.getTollFree())) { return(ShortNumberCost.TOLL_FREE); } if (isEmergencyNumber(shortNumber, regionDialingFrom)) { // Emergency numbers are implicitly toll-free. return(ShortNumberCost.TOLL_FREE); } return(ShortNumberCost.UNKNOWN_COST); }
/** * Tests whether a short number matches a valid pattern in a region. Note that this doesn't verify * the number is actually in use, which is impossible to tell by just looking at the number * itself. * * @param shortNumber the short number to check as a string * @param regionDialingFrom the region from which the number is dialed * @return whether the short number matches a valid pattern */ public bool isValidShortNumberForRegion(String shortNumber, String regionDialingFrom) { PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom); if (phoneMetadata == null) { return(false); } PhoneNumberDesc generalDesc = phoneMetadata.getGeneralDesc(); if (!generalDesc.HasNationalNumberPattern() || !phoneUtil.isNumberMatchingDesc(shortNumber, generalDesc)) { return(false); } PhoneNumberDesc shortNumberDesc = phoneMetadata.getShortCode(); if (!shortNumberDesc.HasNationalNumberPattern()) { logger.log(Level.WARNING, "No short code national number pattern found for region: " + regionDialingFrom); return(false); } return(phoneUtil.isNumberMatchingDesc(shortNumber, shortNumberDesc)); }
public PhoneMetadataCollection addMetadata(PhoneMetadata value) { if (value == null) { throw new NullReferenceException(); } metadata_.Add(value); return(this); }
/** * Given a valid short number, determines whether it is carrier-specific (however, nothing is * implied about its validity). If it is important that the number is valid, then its validity * must first be checked using {@link #isValidShortNumber} or * {@link #isValidShortNumberForRegion}. * * @param number the valid short number to check * @return whether the short number is carrier-specific (assuming the input was a valid short * number). */ public bool isCarrierSpecific(PhoneNumber number) { List <String> regionCodes = phoneUtil.getRegionCodesForCountryCode(number.getCountryCode()); String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); String nationalNumber = phoneUtil.getNationalSignificantNumber(number); PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); return((phoneMetadata != null) && (phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getCarrierSpecific()))); }
public void readExternal(BinaryReader objectInput) { int size = objectInput.readInt(); for (int i = 0; i < size; i++) { PhoneMetadata metadata = new PhoneMetadata(); metadata.readExternal(objectInput); metadata_.Add(metadata); } }
/** * Check whether a short number is a possible number when dialled from a region, given the number * in the form of a string, and the region where the number is dialed from. This provides a more * lenient check than {@link #isValidShortNumberForRegion}. * * @param shortNumber the short number to check as a string * @param regionDialingFrom the region from which the number is dialed * @return whether the number is a possible short number */ public bool isPossibleShortNumberForRegion(String shortNumber, String regionDialingFrom) { PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom); if (phoneMetadata == null) { return(false); } PhoneNumberDesc generalDesc = phoneMetadata.getGeneralDesc(); return(phoneUtil.isNumberPossibleForDesc(shortNumber, generalDesc)); }
// The metadata needed by this class is the same for all regions sharing the same country calling // code. Therefore, we return the metadata for "main" region for this country calling code. private PhoneMetadata getMetadataForRegion(String regionCode) { int countryCallingCode = phoneUtil.getCountryCodeForRegion(regionCode); String mainCountry = phoneUtil.getRegionCodeForCountryCode(countryCallingCode); PhoneMetadata metadata = phoneUtil.getMetadataForRegion(mainCountry); if (metadata != null) { return(metadata); } // Set to a default instance of the metadata. This allows us to function with an incorrect // region code, even if formatting only works for numbers specified with "+". return(EMPTY_METADATA); }
/** * Check whether a short number is a possible number. If a country calling code is shared by * multiple regions, this returns true if it's possible in any of them. This provides a more * lenient check than {@link #isValidShortNumber}. See {@link * #isPossibleShortNumberForRegion(String, String)} for details. * * @param number the short number to check * @return whether the number is a possible short number */ public bool isPossibleShortNumber(PhoneNumber number) { List <String> regionCodes = phoneUtil.getRegionCodesForCountryCode(number.getCountryCode()); String shortNumber = phoneUtil.getNationalSignificantNumber(number); foreach (String region in regionCodes) { PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(region); if (phoneUtil.isNumberPossibleForDesc(shortNumber, phoneMetadata.getGeneralDesc())) { return(true); } } return(false); }
/** * Gets a valid short number for the specified region. * * @param regionCode the region for which an example short number is needed * @return a valid short number for the specified region. Returns an empty string when the * metadata does not contain such information. */ // @VisibleForTesting internal String getExampleShortNumber(String regionCode) { PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); if (phoneMetadata == null) { return(""); } PhoneNumberDesc desc = phoneMetadata.getShortCode(); if (desc.HasExampleNumber()) { return(desc.getExampleNumber()); } return(""); }
internal static bool isNationalPrefixPresentIfRequired(PhoneNumber number, PhoneNumberUtil util) { // First, check how we deduced the country code. If it was written in international format, then // the national prefix is not required. if (number.getCountryCodeSource() != PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY) { return(true); } String phoneNumberRegion = util.getRegionCodeForCountryCode(number.getCountryCode()); PhoneMetadata metadata = util.getMetadataForRegion(phoneNumberRegion); if (metadata == null) { return(true); } // Check if a national prefix should be present when formatting this number. String nationalNumber = util.getNationalSignificantNumber(number); NumberFormat formatRule = util.chooseFormattingRegexForNumber(metadata.numberFormats(), nationalNumber); // To do this, we check that a national prefix formatting rule was present and that it wasn't // just the first-group symbol ($1) with punctuation. if ((formatRule != null) && formatRule.getNationalPrefixFormattingRule().Length > 0) { if (formatRule.isNationalPrefixOptionalWhenFormatting()) { // The national-prefix is optional in these cases, so we don't need to check if it was // present. return(true); } if (PhoneNumberUtil.formattingRuleHasFirstGroupOnly( formatRule.getNationalPrefixFormattingRule())) { // National Prefix not needed for this number. return(true); } // Normalize the remainder. String rawInputCopy = PhoneNumberUtil.normalizeDigitsOnly(number.getRawInput()); StringBuilder rawInput = new StringBuilder(rawInputCopy); // Check if we found a national prefix and/or carrier code at the start of the raw input, and // return the result. return(util.maybeStripNationalPrefixAndCarrierCode(rawInput, metadata, null)); } return(true); }
/** * Clears the internal state of the formatter, so it can be reused. */ public void clear() { currentOutput = ""; accruedInput.Clear(); accruedInputWithoutFormatting.Clear(); formattingTemplate.Clear(); lastMatchPosition = 0; currentFormattingPattern = ""; prefixBeforeNationalNumber.Clear(); extractedNationalPrefix = ""; nationalNumber.Clear(); ableToFormat = true; inputHasFormatting = false; positionToRemember = 0; originalPosition = 0; isCompleteNumber = false; isExpectingCountryCallingCode = false; possibleFormats.Clear(); shouldAddSpaceAfterNationalPrefix = false; if (!currentMetadata.Equals(defaultMetadata)) { currentMetadata = getMetadataForRegion(defaultCountry); } }
/** * Constructs an as-you-type formatter. Should be obtained from {@link * PhoneNumberUtil#getAsYouTypeFormatter}. * * @param regionCode the country/region where the phone number is being entered */ internal AsYouTypeFormatter(String regionCode) { defaultCountry = regionCode; currentMetadata = getMetadataForRegion(defaultCountry); defaultMetadata = currentMetadata; }