public Builder Clear()
 {
     result = new PhoneMetadata();
     return this;
 }
 /**
  * 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(" ");
     return true;
 }
            public PhoneMetadata BuildPartial()
            {
                if (result == null) {
                  throw new global::System.InvalidOperationException("build() has already been called on this Builder");
                }

                PhoneMetadata returnMe = result;
                result = null;
                return returnMe;
            }
 /**
  * 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
  */
 public AsYouTypeFormatter(String regionCode)
 {
     digitPattern = new Regex(digitPlaceholder, RegexOptions.Compiled);
     defaultCountry = regionCode;
     currentMetaData = GetMetadataForRegion(defaultCountry);
     defaultMetaData = currentMetaData;
 }
 /**
  * Clears the internal state of the formatter, so it can be reused.
  */
 public void Clear()
 {
     currentOutput = "";
     accruedInput.Length = 0;
     accruedInputWithoutFormatting.Length = 0;
     formattingTemplate.Length = 0;
     lastMatchPosition = 0;
     currentFormattingPattern = "";
     prefixBeforeNationalNumber.Length = 0;
     nationalPrefixExtracted = "";
     nationalNumber.Length = 0;
     ableToFormat = true;
     inputHasFormatting = false;
     positionToRemember = 0;
     originalPosition = 0;
     isInternationalFormatting = false;
     isExpectingCountryCallingCode = false;
     possibleFormats.Clear();
     if (!currentMetaData.Equals(defaultMetaData))
     {
         currentMetaData = GetMetadataForRegion(defaultCountry);
     }
 }
 /**
 * Strips any national prefix (such as 0, 1) present in the number provided.
 *
 * @param number  the normalized telephone number that we wish to strip any national
 *     dialing prefix from
 * @param metadata  the metadata for the region that we think this number is from
 * @param carrierCode  a place to insert the carrier code if one is extracted
 * @return true if a national prefix or carrier code (or both) could be extracted.
 */
 public bool MaybeStripNationalPrefixAndCarrierCode(
     StringBuilder number, PhoneMetadata metadata, StringBuilder carrierCode)
 {
     int numberLength = number.Length;
     String possibleNationalPrefix = metadata.NationalPrefixForParsing;
     if (numberLength == 0 || possibleNationalPrefix.Length == 0)
     {
         // Early return for numbers of zero length.
         return false;
     }
     // Attempt to parse the first digits as a national prefix.
     var prefixMatcher = regexCache.GetPatternForRegex(possibleNationalPrefix);
     var prefixMatch = prefixMatcher.MatchBeginning(number.ToString()); //XXX: ToString
     if (prefixMatch.Success)
     {
         var nationalNumberRule =
             regexCache.GetPatternForRegex(metadata.GeneralDesc.NationalNumberPattern);
         // Check if the original number is viable.
         bool isViableOriginalNumber = nationalNumberRule.MatchAll(number.ToString()).Success;
         // prefixMatcher.group(numOfGroups) == null implies nothing was captured by the capturing
         // groups in possibleNationalPrefix; therefore, no transformation is necessary, and we just
         // remove the national prefix.
         int numOfGroups = prefixMatch.Groups.Count;
         String transformRule = metadata.NationalPrefixTransformRule;
         if (transformRule == null || transformRule.Length == 0 ||
             !prefixMatch.Groups[numOfGroups - 1].Success)
         {
             // If the original number was viable, and the resultant number is not, we return.
             if (isViableOriginalNumber &&
                 !nationalNumberRule.MatchAll(number.ToString().Substring(prefixMatch.Index + prefixMatch.Length)).Success)
                 return false;
             if (carrierCode != null && numOfGroups > 1 && prefixMatch.Groups[numOfGroups - 1].Success)
                 carrierCode.Append(prefixMatch.Groups[1].Value);
             number.Remove(0, prefixMatch.Index + prefixMatch.Length);
             return true;
         }
         else
         {
             // Check that the resultant number is still viable. If not, return. Check this by copying
             // the string buffer and making the transformation on the copy first.
             StringBuilder transformedNumber = new StringBuilder(
                 prefixMatcher.Replace(number.ToString(), transformRule, 1)); //XXX: ToString
             if (isViableOriginalNumber &&
                 !nationalNumberRule.MatchAll(transformedNumber.ToString()).Success)
                 return false;
             if (carrierCode != null && numOfGroups > 2)
                 carrierCode.Append(prefixMatcher.Match(number.ToString()).Groups[1].Value);
             number.Length = 0;
             number.Append(transformedNumber.ToString());
             return true;
         }
     }
     return false;
 }
        /**
         * Extracts the pattern for the national format.
         *
         * @throws  RuntimeException if multiple or no formats have been encountered.
         * @return  the national format string.
         */
        // @VisibleForTesting
        public static String LoadNationalFormat(PhoneMetadata.Builder metadata, XmlElement numberFormatElement,
                                         NumberFormat.Builder format)
        {
            SetLeadingDigitsPatterns(numberFormatElement, format);
            format.SetPattern(ValidateRE(numberFormatElement.GetAttribute(PATTERN)));

            var formatPattern = numberFormatElement.GetElementsByTagName(FORMAT);
            if (formatPattern.Count != 1)
            {
                //LOGGER.log(Level.SEVERE,
                //           "Only one format pattern for a numberFormat element should be defined.");
                throw new Exception("Invalid number of format patterns for country: " +
                                    metadata.Id);
            }
            String nationalFormat = formatPattern[0].InnerText;
            format.SetFormat(nationalFormat);
            return nationalFormat;
        }
        /**
        *  Extracts the available formats from the provided DOM element. If it does not contain any
        *  nationalPrefixFormattingRule, the one passed-in is retained. The nationalPrefix,
        *  nationalPrefixFormattingRule and nationalPrefixOptionalWhenFormatting values are provided from
        *  the parent (territory) element.
        */
        // @VisibleForTesting
        public static void LoadAvailableFormats(PhoneMetadata.Builder metadata,
                                         XmlElement element, String nationalPrefix,
                                         String nationalPrefixFormattingRule,
                                         bool nationalPrefixOptionalWhenFormatting)
        {
            String carrierCodeFormattingRule = "";
            if (element.HasAttribute(CARRIER_CODE_FORMATTING_RULE))
            {
                carrierCodeFormattingRule = ValidateRE(
                    GetDomesticCarrierCodeFormattingRuleFromElement(element, nationalPrefix));
            }
            var numberFormatElements = element.GetElementsByTagName(NUMBER_FORMAT);
            bool hasExplicitIntlFormatDefined = false;

            int numOfFormatElements = numberFormatElements.Count;
            if (numOfFormatElements > 0)
            {
                foreach (XmlElement numberFormatElement in numberFormatElements)
                {
                    var format = new NumberFormat.Builder();

                    if (numberFormatElement.HasAttribute(NATIONAL_PREFIX_FORMATTING_RULE))
                    {
                        format.SetNationalPrefixFormattingRule(
                            GetNationalPrefixFormattingRuleFromElement(numberFormatElement, nationalPrefix));
                        format.SetNationalPrefixOptionalWhenFormatting(
                            numberFormatElement.HasAttribute(NATIONAL_PREFIX_OPTIONAL_WHEN_FORMATTING));

                    }
                    else
                    {
                        format.SetNationalPrefixFormattingRule(nationalPrefixFormattingRule);
                        format.SetNationalPrefixOptionalWhenFormatting(nationalPrefixOptionalWhenFormatting);
                    }
                    if (numberFormatElement.HasAttribute("carrierCodeFormattingRule"))
                    {
                        format.SetDomesticCarrierCodeFormattingRule(ValidateRE(
                            GetDomesticCarrierCodeFormattingRuleFromElement(
                                numberFormatElement, nationalPrefix)));
                    }
                    else
                    {
                        format.SetDomesticCarrierCodeFormattingRule(carrierCodeFormattingRule);
                    }

                    // Extract the pattern for the national format.
                    String nationalFormat =
                        LoadNationalFormat(metadata, numberFormatElement, format);
                    metadata.AddNumberFormat(format);

                    if (LoadInternationalFormat(metadata, numberFormatElement, nationalFormat))
                    {
                        hasExplicitIntlFormatDefined = true;
                    }
                }
                // Only a small number of regions need to specify the intlFormats in the xml. For the majority
                // of countries the intlNumberFormat metadata is an exact copy of the national NumberFormat
                // metadata. To minimize the size of the metadata file, we only keep intlNumberFormats that
                // actually differ in some way to the national formats.
                if (!hasExplicitIntlFormatDefined)
                {
                    metadata.ClearIntlNumberFormat();
                }
            }
        }
        // @VisibleForTesting
        public static void LoadGeneralDesc(PhoneMetadata.Builder metadata, XmlElement element, bool liteBuild)
        {
            var generalDesc = ProcessPhoneNumberDescElement(null, element, GENERAL_DESC, liteBuild);
            metadata.SetGeneralDesc(generalDesc);

            metadata.SetFixedLine(ProcessPhoneNumberDescElement(generalDesc, element, FIXED_LINE, liteBuild));
            metadata.SetMobile(ProcessPhoneNumberDescElement(generalDesc, element, MOBILE, liteBuild));
            metadata.SetTollFree(ProcessPhoneNumberDescElement(generalDesc, element, TOLL_FREE, liteBuild));
            metadata.SetPremiumRate(ProcessPhoneNumberDescElement(generalDesc, element, PREMIUM_RATE, liteBuild));
            metadata.SetSharedCost(ProcessPhoneNumberDescElement(generalDesc, element, SHARED_COST, liteBuild));
            metadata.SetVoip(ProcessPhoneNumberDescElement(generalDesc, element, VOIP, liteBuild));
            metadata.SetPersonalNumber(ProcessPhoneNumberDescElement(generalDesc, element,
                                                                     PERSONAL_NUMBER, liteBuild));
            metadata.SetPager(ProcessPhoneNumberDescElement(generalDesc, element, PAGER, liteBuild));
            metadata.SetUan(ProcessPhoneNumberDescElement(generalDesc, element, UAN, liteBuild));
            metadata.SetVoicemail(ProcessPhoneNumberDescElement(generalDesc, element, VOICEMAIL, liteBuild));
            metadata.SetEmergency(ProcessPhoneNumberDescElement(generalDesc, element, EMERGENCY, liteBuild));
            metadata.SetNoInternationalDialling(ProcessPhoneNumberDescElement(generalDesc, element,
                                                                              NO_INTERNATIONAL_DIALLING, liteBuild));
            metadata.SetSameMobileAndFixedLinePattern(
                metadata.Mobile.NationalNumberPattern.Equals(
                metadata.FixedLine.NationalNumberPattern));
        }
        private PhoneNumberType GetNumberTypeHelper(String nationalNumber, PhoneMetadata metadata)
        {
            var generalNumberDesc = metadata.GeneralDesc;
            if (!generalNumberDesc.HasNationalNumberPattern ||
                !IsNumberMatchingDesc(nationalNumber, generalNumberDesc))
                return PhoneNumberType.UNKNOWN;

            if (IsNumberMatchingDesc(nationalNumber, metadata.PremiumRate))
                return PhoneNumberType.PREMIUM_RATE;

            if (IsNumberMatchingDesc(nationalNumber, metadata.TollFree))
                return PhoneNumberType.TOLL_FREE;

            if (IsNumberMatchingDesc(nationalNumber, metadata.SharedCost))
                return PhoneNumberType.SHARED_COST;

            if (IsNumberMatchingDesc(nationalNumber, metadata.Voip))
                return PhoneNumberType.VOIP;

            if (IsNumberMatchingDesc(nationalNumber, metadata.PersonalNumber))
                return PhoneNumberType.PERSONAL_NUMBER;

            if (IsNumberMatchingDesc(nationalNumber, metadata.Pager))
                return PhoneNumberType.PAGER;

            if (IsNumberMatchingDesc(nationalNumber, metadata.Uan))
                return PhoneNumberType.UAN;

            if (IsNumberMatchingDesc(nationalNumber, metadata.Voicemail))
                return PhoneNumberType.VOICEMAIL;

            var isFixedLine = IsNumberMatchingDesc(nationalNumber, metadata.FixedLine);
            if (isFixedLine)
            {
                if (metadata.SameMobileAndFixedLinePattern)
                    return PhoneNumberType.FIXED_LINE_OR_MOBILE;
                else if (IsNumberMatchingDesc(nationalNumber, metadata.Mobile))
                    return PhoneNumberType.FIXED_LINE_OR_MOBILE;
                return PhoneNumberType.FIXED_LINE;
            }
            // Otherwise, test to see if the number is mobile. Only do this if certain that the patterns for
            // mobile and fixed line aren't the same.
            if (!metadata.SameMobileAndFixedLinePattern &&
                IsNumberMatchingDesc(nationalNumber, metadata.Mobile))
                return PhoneNumberType.MOBILE;
            return PhoneNumberType.UNKNOWN;
        }
 /**
 * Appends the formatted extension of a phone number to formattedNumber, if the phone number had
 * an extension specified.
 */
 private void MaybeAppendFormattedExtension(PhoneNumber number, PhoneMetadata metadata,
     PhoneNumberFormat numberFormat, StringBuilder formattedNumber)
 {
     if (number.HasExtension && number.Extension.Length > 0)
     {
         if (numberFormat == PhoneNumberFormat.RFC3966)
         {
             formattedNumber.Append(RFC3966_EXTN_PREFIX).Append(number.Extension);
         }
         else
         {
             if (metadata.HasPreferredExtnPrefix)
                 formattedNumber.Append(metadata.PreferredExtnPrefix).Append(number.Extension);
             else
                 formattedNumber.Append(DEFAULT_EXTN_PREFIX).Append(number.Extension);
         }
     }
 }
 PhoneNumberDesc GetNumberDescByType(PhoneMetadata metadata, PhoneNumberType type)
 {
     switch (type)
     {
         case PhoneNumberType.PREMIUM_RATE:
             return metadata.PremiumRate;
         case PhoneNumberType.TOLL_FREE:
             return metadata.TollFree;
         case PhoneNumberType.MOBILE:
             return metadata.Mobile;
         case PhoneNumberType.FIXED_LINE:
         case PhoneNumberType.FIXED_LINE_OR_MOBILE:
             return metadata.FixedLine;
         case PhoneNumberType.SHARED_COST:
             return metadata.SharedCost;
         case PhoneNumberType.VOIP:
             return metadata.Voip;
         case PhoneNumberType.PERSONAL_NUMBER:
             return metadata.PersonalNumber;
         case PhoneNumberType.PAGER:
             return metadata.Pager;
         case PhoneNumberType.UAN:
             return metadata.Uan;
         case PhoneNumberType.VOICEMAIL:
             return metadata.Voicemail;
         default:
             return metadata.GeneralDesc;
     }
 }
 // Note in some regions, the national number can be written in two completely different ways
 // depending on whether it forms part of the NATIONAL format or INTERNATIONAL format. The
 // numberFormat parameter here is used to specify which format to use for those cases. If a
 // carrierCode is specified, this will be inserted into the formatted string to replace $CC.
 private String FormatNsn(String number,
     PhoneMetadata metadata,
     PhoneNumberFormat numberFormat,
     String carrierCode)
 {
     var intlNumberFormats = metadata.IntlNumberFormatList;
     // When the intlNumberFormats exists, we use that to format national number for the
     // INTERNATIONAL format instead of using the numberDesc.numberFormats.
     var availableFormats =
         (intlNumberFormats.Count == 0 || numberFormat == PhoneNumberFormat.NATIONAL)
         ? metadata.NumberFormatList
         : metadata.IntlNumberFormatList;
     NumberFormat formattingPattern = ChooseFormattingPatternForNumber(availableFormats, number);
     return (formattingPattern == null)
         ? number
         : FormatNsnUsingPattern(number, formattingPattern, numberFormat, carrierCode);
 }
 // Simple wrapper of formatNsn for the common case of no carrier code.
 private String FormatNsn(String number, PhoneMetadata metadata, PhoneNumberFormat numberFormat)
 {
     return FormatNsn(number, metadata, numberFormat, null);
 }
 public Builder MergeFrom(PhoneMetadata other)
 {
     if (other == global::PhoneNumbers.PhoneMetadata.DefaultInstance) return this;
     if (other.HasGeneralDesc) {
       MergeGeneralDesc(other.GeneralDesc);
     }
     if (other.HasFixedLine) {
       MergeFixedLine(other.FixedLine);
     }
     if (other.HasMobile) {
       MergeMobile(other.Mobile);
     }
     if (other.HasTollFree) {
       MergeTollFree(other.TollFree);
     }
     if (other.HasPremiumRate) {
       MergePremiumRate(other.PremiumRate);
     }
     if (other.HasSharedCost) {
       MergeSharedCost(other.SharedCost);
     }
     if (other.HasPersonalNumber) {
       MergePersonalNumber(other.PersonalNumber);
     }
     if (other.HasVoip) {
       MergeVoip(other.Voip);
     }
     if (other.HasPager) {
       MergePager(other.Pager);
     }
     if (other.HasUan) {
       MergeUan(other.Uan);
     }
     if (other.HasEmergency) {
       MergeEmergency(other.Emergency);
     }
     if (other.HasVoicemail) {
       MergeVoicemail(other.Voicemail);
     }
     if (other.HasShortCode) {
       MergeShortCode(other.ShortCode);
     }
     if (other.HasStandardRate) {
       MergeStandardRate(other.StandardRate);
     }
     if (other.HasCarrierSpecific) {
       MergeCarrierSpecific(other.CarrierSpecific);
     }
     if (other.HasNoInternationalDialling) {
       MergeNoInternationalDialling(other.NoInternationalDialling);
     }
     if (other.HasId) {
       Id = other.Id;
     }
     if (other.HasCountryCode) {
       CountryCode = other.CountryCode;
     }
     if (other.HasInternationalPrefix) {
       InternationalPrefix = other.InternationalPrefix;
     }
     if (other.HasPreferredInternationalPrefix) {
       PreferredInternationalPrefix = other.PreferredInternationalPrefix;
     }
     if (other.HasNationalPrefix) {
       NationalPrefix = other.NationalPrefix;
     }
     if (other.HasPreferredExtnPrefix) {
       PreferredExtnPrefix = other.PreferredExtnPrefix;
     }
     if (other.HasNationalPrefixForParsing) {
       NationalPrefixForParsing = other.NationalPrefixForParsing;
     }
     if (other.HasNationalPrefixTransformRule) {
       NationalPrefixTransformRule = other.NationalPrefixTransformRule;
     }
     if (other.HasSameMobileAndFixedLinePattern) {
       SameMobileAndFixedLinePattern = other.SameMobileAndFixedLinePattern;
     }
     if (other.numberFormat_.Count != 0) {
        result.numberFormat_.AddRange(other.numberFormat_);
     }
     if (other.intlNumberFormat_.Count != 0) {
        result.intlNumberFormat_.AddRange(other.intlNumberFormat_);
     }
     if (other.HasMainCountryForCode) {
       MainCountryForCode = other.MainCountryForCode;
     }
     if (other.HasLeadingDigits) {
       LeadingDigits = other.LeadingDigits;
     }
     if (other.HasLeadingZeroPossible) {
       LeadingZeroPossible = other.LeadingZeroPossible;
     }
     if (other.HasMobileNumberPortableRegion) {
       MobileNumberPortableRegion = other.MobileNumberPortableRegion;
     }
     return this;
 }
        /**
        * Extracts the pattern for international format. If there is no intlFormat, default to using the
        * national format. If the intlFormat is set to "NA" the intlFormat should be ignored.
        *
        * @throws  RuntimeException if multiple intlFormats have been encountered.
        * @return  whether an international number format is defined.
        */
        // @VisibleForTesting
        public static bool LoadInternationalFormat(PhoneMetadata.Builder metadata,
            XmlElement numberFormatElement,
            String nationalFormat)
        {
            NumberFormat.Builder intlFormat = new NumberFormat.Builder();
            SetLeadingDigitsPatterns(numberFormatElement, intlFormat);
            intlFormat.SetPattern(numberFormatElement.GetAttribute(PATTERN));
            var intlFormatPattern = numberFormatElement.GetElementsByTagName(INTL_FORMAT);
            bool hasExplicitIntlFormatDefined = false;

            if (intlFormatPattern.Count > 1)
            {
                //LOGGER.log(Level.SEVERE,
                //          "A maximum of one intlFormat pattern for a numberFormat element should be " +
                //           "defined.");
                throw new Exception("Invalid number of intlFormat patterns for country: " +
                                    metadata.Id);
            }
            else if (intlFormatPattern.Count == 0)
            {
                // Default to use the same as the national pattern if none is defined.
                intlFormat.SetFormat(nationalFormat);
            }
            else
            {
                String intlFormatPatternValue = intlFormatPattern[0].InnerText;
                if (!intlFormatPatternValue.Equals("NA"))
                {
                    intlFormat.SetFormat(intlFormatPatternValue);
                }
                hasExplicitIntlFormatDefined = true;
            }

            if (intlFormat.HasFormat)
            {
                metadata.AddIntlNumberFormat(intlFormat);
            }
            return hasExplicitIntlFormatDefined;
        }
 public static Builder CreateBuilder(PhoneMetadata prototype)
 {
     return (Builder) new Builder().MergeFrom(prototype);
 }
        /**
        * Tries to extract a country calling code from a number. This method will return zero if no
        * country calling code is considered to be present. Country calling codes are extracted in the
        * following ways:
        * <ul>
        *  <li> by stripping the international dialing prefix of the region the person is dialing from,
        *       if this is present in the number, and looking at the next digits
        *  <li> by stripping the '+' sign if present and then looking at the next digits
        *  <li> by comparing the start of the number and the country calling code of the default region.
        *       If the number is not considered possible for the numbering plan of the default region
        *       initially, but starts with the country calling code of this region, validation will be
        *       reattempted after stripping this country calling code. If this number is considered a
        *       possible number, then the first digits will be considered the country calling code and
        *       removed as such.
        * </ul>
        * It will throw a NumberParseException if the number starts with a '+' but the country calling
        * code supplied after this does not match that of any known region.
        *
        * @param number  non-normalized telephone number that we wish to extract a country calling
        *     code from - may begin with '+'
        * @param defaultRegionMetadata  metadata about the region this number may be from
        * @param nationalNumber  a string buffer to store the national significant number in, in the case
        *     that a country calling code was extracted. The number is appended to any existing contents.
        *     If no country calling code was extracted, this will be left unchanged.
        * @param keepRawInput  true if the country_code_source and preferred_carrier_code fields of
        *     phoneNumber should be populated.
        * @param phoneNumber  the PhoneNumber object where the country_code and country_code_source need
        *     to be populated. Note the country_code is always populated, whereas country_code_source is
        *     only populated when keepCountryCodeSource is true.
        * @return  the country calling code extracted or 0 if none could be extracted
        */
        public int MaybeExtractCountryCode(String number, PhoneMetadata defaultRegionMetadata,
            StringBuilder nationalNumber, bool keepRawInput, PhoneNumber.Builder phoneNumber)
        {
            if (number.Length == 0)
                return 0;
            StringBuilder fullNumber = new StringBuilder(number);
            // Set the default prefix to be something that will never match.
            String possibleCountryIddPrefix = "NonMatch";
            if (defaultRegionMetadata != null)
            {
                possibleCountryIddPrefix = defaultRegionMetadata.InternationalPrefix;
            }

            CountryCodeSource countryCodeSource =
                MaybeStripInternationalPrefixAndNormalize(fullNumber, possibleCountryIddPrefix);
            if (keepRawInput)
            {
                phoneNumber.SetCountryCodeSource(countryCodeSource);
            }
            if (countryCodeSource != CountryCodeSource.FROM_DEFAULT_COUNTRY)
            {
                if (fullNumber.Length <= MIN_LENGTH_FOR_NSN)
                {
                    throw new NumberParseException(ErrorType.TOO_SHORT_AFTER_IDD,
                           "Phone number had an IDD, but after this was not "
                           + "long enough to be a viable phone number.");
                }
                int potentialCountryCode = ExtractCountryCode(fullNumber, nationalNumber);
                if (potentialCountryCode != 0)
                {
                    phoneNumber.SetCountryCode(potentialCountryCode);
                    return potentialCountryCode;
                }

                // If this fails, they must be using a strange country calling code that we don't recognize,
                // or that doesn't exist.
                throw new NumberParseException(ErrorType.INVALID_COUNTRY_CODE,
                    "Country calling code supplied was not recognised.");
            }
            else if (defaultRegionMetadata != null)
            {
                // Check to see if the number starts with the country calling code for the default region. If
                // so, we remove the country calling code, and do some checks on the validity of the number
                // before and after.
                int defaultCountryCode = defaultRegionMetadata.CountryCode;
                String defaultCountryCodeString = defaultCountryCode.ToString();
                String normalizedNumber = fullNumber.ToString();
                if (normalizedNumber.StartsWith(defaultCountryCodeString))
                {
                    StringBuilder potentialNationalNumber =
                        new StringBuilder(normalizedNumber.Substring(defaultCountryCodeString.Length));
                    PhoneNumberDesc generalDesc = defaultRegionMetadata.GeneralDesc;
                    var validNumberPattern =
                        regexCache.GetPatternForRegex(generalDesc.NationalNumberPattern);
                    MaybeStripNationalPrefixAndCarrierCode(
                        potentialNationalNumber, defaultRegionMetadata, null /* Don't need the carrier code */);
                    var possibleNumberPattern =
                        regexCache.GetPatternForRegex(generalDesc.PossibleNumberPattern);
                    // If the number was not valid before but is valid now, or if it was too long before, we
                    // consider the number with the country calling code stripped to be a better result and
                    // keep that instead.
                    if ((!validNumberPattern.MatchAll(fullNumber.ToString()).Success &&             //XXX: ToString
                     validNumberPattern.MatchAll(potentialNationalNumber.ToString()).Success) ||    //XXX: ToString
                     TestNumberLengthAgainstPattern(possibleNumberPattern, fullNumber.ToString())
                          == ValidationResult.TOO_LONG)
                    {
                        nationalNumber.Append(potentialNationalNumber);
                        if (keepRawInput)
                            phoneNumber.SetCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN);
                        phoneNumber.SetCountryCode(defaultCountryCode);
                        return defaultCountryCode;
                    }
                }
            }
            // No country calling code present.
            phoneNumber.SetCountryCode(0);
            return 0;
        }