/** * 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. */ public static void LoadAvailableFormats(PhoneMetadata.Builder metadata, XElement element, string nationalPrefix, string nationalPrefixFormattingRule, bool nationalPrefixOptionalWhenFormatting) { var carrierCodeFormattingRule = ""; if (element.HasAttribute(CARRIER_CODE_FORMATTING_RULE)) carrierCodeFormattingRule = ValidateRE( GetDomesticCarrierCodeFormattingRuleFromElement(element, nationalPrefix)); var numberFormatElements = element.GetElementsByTagName(NUMBER_FORMAT).ToList(); var hasExplicitIntlFormatDefined = false; var numOfFormatElements = numberFormatElements.Count; if (numOfFormatElements > 0) { foreach (var 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. var 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(); } }
/** * 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(); } } }
/** * Formats a phone number in the specified format using client-defined formatting rules. Note that * if the phone number has a country calling code of zero or an otherwise invalid country calling * code, we cannot work out things like whether there should be a national prefix applied, or how * to format extensions, so we return the national significant number with no formatting applied. * * @param number the phone number to be formatted * @param numberFormat the format the phone number should be formatted into * @param userDefinedFormats formatting rules specified by clients * @return the formatted phone number */ public String FormatByPattern(PhoneNumber number, PhoneNumberFormat numberFormat, List<NumberFormat> userDefinedFormats) { int countryCallingCode = number.CountryCode; var nationalSignificantNumber = GetNationalSignificantNumber(number); // Note getRegionCodeForCountryCode() is used because formatting information for regions which // share a country calling code is contained by only one region for performance reasons. For // example, for NANPA regions it will be contained in the metadata for US. var regionCode = GetRegionCodeForCountryCode(countryCallingCode); if (!HasValidCountryCallingCode(countryCallingCode)) return nationalSignificantNumber; PhoneMetadata metadata = GetMetadataForRegionOrCallingCode(countryCallingCode, regionCode); StringBuilder formattedNumber = new StringBuilder(20); NumberFormat formattingPattern = ChooseFormattingPatternForNumber(userDefinedFormats, nationalSignificantNumber); if (formattingPattern == null) { // If no pattern above is matched, we format the number as a whole. formattedNumber.Append(nationalSignificantNumber); } else { var numFormatCopy = new NumberFormat.Builder(); // Before we do a replacement of the national prefix pattern $NP with the national prefix, we // need to copy the rule so that subsequent replacements for different numbers have the // appropriate national prefix. numFormatCopy.MergeFrom(formattingPattern); String nationalPrefixFormattingRule = formattingPattern.NationalPrefixFormattingRule; if (nationalPrefixFormattingRule.Length > 0) { String nationalPrefix = metadata.NationalPrefix; if (nationalPrefix.Length > 0) { // Replace $NP with national prefix and $FG with the first group ($1). nationalPrefixFormattingRule = NP_PATTERN.Replace(nationalPrefixFormattingRule, nationalPrefix, 1); nationalPrefixFormattingRule = FG_PATTERN.Replace(nationalPrefixFormattingRule, "$$1", 1); numFormatCopy.SetNationalPrefixFormattingRule(nationalPrefixFormattingRule); } else { // We don't want to have a rule for how to format the national prefix if there isn't one. numFormatCopy.ClearNationalPrefixFormattingRule(); } } formattedNumber.Append( FormatNsnUsingPattern(nationalSignificantNumber, numFormatCopy.Build(), numberFormat)); } MaybeAppendFormattedExtension(number, metadata, numberFormat, formattedNumber); PrefixNumberWithCountryCallingCode(countryCallingCode, numberFormat, formattedNumber); return formattedNumber.ToString(); }
/** * Formats a phone number in the specified format using client-defined formatting rules. Note that * if the phone number has a country calling code of zero or an otherwise invalid country calling * code, we cannot work out things like whether there should be a national prefix applied, or how * to format extensions, so we return the national significant number with no formatting applied. * * @param number the phone number to be formatted * @param numberFormat the format the phone number should be formatted into * @param userDefinedFormats formatting rules specified by clients * @return the formatted phone number */ public String FormatByPattern(PhoneNumber number, PhoneNumberFormat numberFormat, List<NumberFormat> userDefinedFormats) { int countryCallingCode = number.CountryCode; var nationalSignificantNumber = GetNationalSignificantNumber(number); // Note getRegionCodeForCountryCode() is used because formatting information for regions which // share a country calling code is contained by only one region for performance reasons. For // example, for NANPA regions it will be contained in the metadata for US. var regionCode = GetRegionCodeForCountryCode(countryCallingCode); if (!HasValidRegionCode(regionCode, countryCallingCode, nationalSignificantNumber)) return nationalSignificantNumber; var userDefinedFormatsCopy = new List<NumberFormat>(userDefinedFormats.Count); foreach (var numFormat in userDefinedFormats) { var nationalPrefixFormattingRule = numFormat.NationalPrefixFormattingRule; if (nationalPrefixFormattingRule.Length > 0) { // Before we do a replacement of the national prefix pattern $NP with the national prefix, // we need to copy the rule so that subsequent replacements for different numbers have the // appropriate national prefix. var numFormatCopy = new NumberFormat.Builder(); numFormatCopy.MergeFrom(numFormat); var nationalPrefix = GetMetadataForRegion(regionCode).NationalPrefix; if (nationalPrefix.Length > 0) { // Replace $NP with national prefix and $FG with the first group ($1). nationalPrefixFormattingRule = NP_PATTERN.Replace(nationalPrefixFormattingRule, nationalPrefix, 1); nationalPrefixFormattingRule = FG_PATTERN.Replace(nationalPrefixFormattingRule, "$$1", 1); numFormatCopy.SetNationalPrefixFormattingRule(nationalPrefixFormattingRule); } else { // We don't want to have a rule for how to format the national prefix if there isn't one. numFormatCopy.ClearNationalPrefixFormattingRule(); } userDefinedFormatsCopy.Add(numFormatCopy.Build()); } else { // Otherwise, we just add the original rule to the modified list of formats. userDefinedFormatsCopy.Add(numFormat); } } var formattedNumber = new StringBuilder(FormatAccordingToFormats(nationalSignificantNumber, userDefinedFormatsCopy, numberFormat)); MaybeGetFormattedExtension(number, regionCode, numberFormat, formattedNumber); FormatNumberByFormat(countryCallingCode, numberFormat, formattedNumber); return formattedNumber.ToString(); }
/** * 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. */ public static void LoadAvailableFormats(PhoneMetadata.Builder metadata, XElement element, string nationalPrefix, string nationalPrefixFormattingRule, bool nationalPrefixOptionalWhenFormatting) { var carrierCodeFormattingRule = ""; if (element.HasAttribute(CARRIER_CODE_FORMATTING_RULE)) { carrierCodeFormattingRule = ValidateRE( GetDomesticCarrierCodeFormattingRuleFromElement(element, nationalPrefix)); } var availableFormats = element.Element("availableFormats"); var hasExplicitIntlFormatDefined = false; if (availableFormats != null && availableFormats.HasElements) { foreach (var numberFormatElement in availableFormats.Elements()) { var format = new NumberFormat.Builder(); if (numberFormatElement.HasAttribute(NATIONAL_PREFIX_FORMATTING_RULE)) { format.SetNationalPrefixFormattingRule( GetNationalPrefixFormattingRuleFromElement(numberFormatElement, nationalPrefix)); } else if (!nationalPrefixFormattingRule.Equals("")) { format.SetNationalPrefixFormattingRule(nationalPrefixFormattingRule); } if (numberFormatElement.HasAttribute(NATIONAL_PREFIX_OPTIONAL_WHEN_FORMATTING)) { format.SetNationalPrefixOptionalWhenFormatting( bool.Parse(numberFormatElement.Attribute(NATIONAL_PREFIX_OPTIONAL_WHEN_FORMATTING).Value)); } else if (format.NationalPrefixOptionalWhenFormatting != nationalPrefixOptionalWhenFormatting) { // Inherit from the parent field if it is not already the same as the default. format.SetNationalPrefixOptionalWhenFormatting(nationalPrefixOptionalWhenFormatting); } if (numberFormatElement.HasAttribute("carrierCodeFormattingRule")) { format.SetDomesticCarrierCodeFormattingRule(ValidateRE( GetDomesticCarrierCodeFormattingRuleFromElement( numberFormatElement, nationalPrefix))); } else if (!carrierCodeFormattingRule.Equals("")) { format.SetDomesticCarrierCodeFormattingRule(carrierCodeFormattingRule); } // Extract the pattern for the national format. var 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(); } } }