All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.globalmentor.itu.TelephoneNumber Maven / Gradle / Ivy

The newest version!
/*
 * Copyright © 1996-2012 GlobalMentor, Inc. 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.globalmentor.itu;

import java.net.URI;
import java.util.*;
import java.util.regex.*;

import com.globalmentor.collections.*;
import com.globalmentor.java.CharSequences;
import com.globalmentor.java.Characters;
import com.globalmentor.java.Longs;

import static com.globalmentor.java.Characters.*;
import com.globalmentor.java.Objects;
import com.globalmentor.net.Resource;

import static com.globalmentor.java.Objects.*;
import static com.globalmentor.java.StringBuilders.*;
import static com.globalmentor.java.Strings.*;

import com.globalmentor.text.ArgumentSyntaxException;

import static com.globalmentor.text.RegularExpressions.*;
import static com.globalmentor.text.TextFormatter.*;

/**
 * International public telecommunication number for geographic areas as defined in ITU-T E.164, "The international public telecommunication numbering plan".
 * The default formatting is a string in ITU-T E.164 format with no delimiters except for the introductory international prefix symbol, if any. The label form
 * of the telephone number is formatted according to ITU-T E.123,
 * "Notation for national and international telephone numbers, e-mail addresses and Web addresses".
 * 
 * 

* Following ITU-T E.164, a telephone number is considered to have the following parts: Country Code (CC) and National (Significant) Number (NSN). The NSN is * further divided into National Destination Code (NDC) and Subscriber Number (SN). *

* *

* This implementation does not support extensions. *

*

* The NDC and SN digits will be canonicized for the following country codes: *

*
    *
  • 1 (US, CA)
  • *
* TODO update comments to match the TEL URI RFC 3966 * @author Garret Wilson */ public class TelephoneNumber implements Resource, Comparable { /** The international prefix symbol of a telephone number ('+'). */ public static final char INTERNATIONAL_PREFIX_SYMBOL = '+'; /** The separator for international telephone number components (' '). */ public static final char COMPONENT_SEPARATOR = ' '; /** Symbols allowed for spacing between components. */ public static final Characters SPACING_SYMBOLS = new Characters('-', '.', COMPONENT_SEPARATOR); /** The regular expression pattern for splitting out components based upon spacing symbols. */ protected static final Pattern SPACING_PATTERN = Pattern.compile(createCharacterClass(SPACING_SYMBOLS) + "+"); /** * The regular expression pattern for a Country Code (CC): '+' followed by one to three digits. The first matching group will be the actual country code * digits. */ public static final Pattern CC_PATTERN = Pattern.compile(escapePatternString(String.valueOf(INTERNATIONAL_PREFIX_SYMBOL)) + "(\\d{1,3})"); //E.164 6.2.1 /** * The regular expression pattern for a National Destination Code (NDC): up to 14 digits, optionally surrounded by parenthesis. The first matching group, if * non-null, will be the actual national destination code digits without parenthesis, and the second matching group, if non-null, * will be the actual national destination code digits with parenthesis. */ public static final Pattern NDC_PATTERN = Pattern.compile("(\\d{1,14})|(?:\\((\\d{1,14})\\))"); //E.164 6.2.1 /** The regular expression pattern for a Subscriber Number (SN) component: up to 14 digits. */ public static final Pattern SN_COMPONENT_PATTERN = Pattern.compile("\\d{1,14}"); //E.164 6.2.1 /** * Strings of country codes that are shorter than three digits long; taken from List of ITU-T Recommendation E-164 Assigned Country Codes (Position on * 15 April 2009), Annex to ITU Operational Bulletin No. 930 – 15.IV.2009. */ private static final Set SHORT_CC_STRINGS = Sets.immutableSetOf("1", "20", "27", "30", "31", "32", "33", "34", "36", "39", "40", "41", "43", "44", "45", "46", "47", "48", "49", "51", "52", "53", "54", "55", "56", "56", "58", "60", "61", "62", "63", "64", "65", "66", "7", "81", "82", "84", "86", "90", "91", "92", "93", "94", "95", "98"); /** The canonical string form of the telephone number, with no delimiters except the beginning international prefix symbol if this is a global number. */ private final String string; /** * Returns whether this telephone number is a global telephone number. This method returns true if there is a known country code. * @return true if this is a global telephone number, else false if it is only a local telephone number. */ public boolean isGlobal() { return cc >= 0; } /** The Country Code (CC) for geographic areas, or -1 if this is a local number. */ private final int cc; /** @return The Country Code (CC) for geographic areas, or -1 if this is a local number. */ public int getCountryCode() { return cc; } /** @return The Country Code (CC) string for geographic areas, or null if this is a local number. */ public String getCountryCodeString() { return cc >= 0 ? Integer.toString(cc) : null; } /** The National Significant Number. */ private final long nsn; /** * Returns the National Significant Number (NSN). Every valid telephone number has an NSN. The NSN may or may not be further divided into its components, * based upon whether these component divisions are known. Similarly the telephone number may or may not have a separate country code provided. * @return The National Significant Number (NSN). */ public long getNationalNumber() { return nsn; } /** @return The National Significant Number (NSN) in canonical string format without delimiters. */ public String getNationalNumberString() { return Long.toString(nsn); } /** The National Destination Code (NDC), or -1 if there is no NDC. */ private final long ndc; /** @return The National Destination Code (NDC), or -1 if there is no NDC. */ public long getNationalDestinationCode() { return ndc; } /** @return The National Destination Code (NDC) string, or null if there is no NDC. */ public String getNationalDestinationCodeString() { return ndc >= 0 ? Long.toString(ndc) : null; } /** The Subscriber Number (SN). */ //TODO bring back, maybe private final long sn; /** @return The Subscriber Number (SN). */ //TODO bring back, maybe public long getSN() {return sn;} /** The components of the Subscriber Number (SN). */ private long[] snComponents; /** @return The components of the Subscriber Number (SN). */ public long[] getSubscriberNumberComponents() { return snComponents.clone(); } /** The component strings of the Subscriber Number (SN). */ private String[] snComponentStrings; /** @return The component strings of the Subscriber Number (SN). */ public String[] getSubscriberNumberComponentStrings() { return snComponentStrings.clone(); } /** * Constructs a string with the Subscriber Number (SN), separating the components with the given delimiter. * @param delimiter The delimiter to use to separate the subscriber number components, or {@link Characters#UNDEFINED_CHAR} if no delimiter should be used. * @return A string representing the subscriber number. * @see Characters#UNDEFINED_CHAR */ public String getSubscriberNumberString(final char delimiter) { return formatList(delimiter, getSubscriberNumberComponentStrings()); //format the SN components into a list } /** @return A string representing the Subscriber Number (SN) with component separated by spaces as specified in ITU-T E.123. */ public String getSubscriberNumberString() { return getSubscriberNumberString(COMPONENT_SEPARATOR); //create the subscriber number, using a space as a delimiter } /** * Constructs a telephone number from its separate components. * @param cc The country code for geographic areas, or null if the country code is not known * @param ndc The national destination code; if no subscriber number components are given, this will be considered the national significant number. * @param snComponents The strings representing the SN components. * @throws NullPointerException if there are no SN components and the NDC is null. * @throws ArgumentSyntaxException Thrown if the value violates ITU-T E.164 or ITU-T E.123. */ public TelephoneNumber(final String cc, final String ndc, final String... snComponents) throws ArgumentSyntaxException { final StringBuilder stringBuilder = new StringBuilder(); if(cc != null) { //if a country code was given if(!SHORT_CC_STRINGS.contains(cc) && cc.length() != 3) { //we must have a record of the country code, or it must be a three-digit country code throw new IllegalArgumentException("Invalid Country Code: " + cc); } this.cc = Integer.parseInt(cc); //store the country code stringBuilder.append(INTERNATIONAL_PREFIX_SYMBOL).append(cc); } else { //if no country code was given this.cc = -1; } final StringBuilder nsnStringBuilder = new StringBuilder(); if(snComponents.length > 0) { //if there are SN components if(ndc != null) { //store the NDC if we have one this.ndc = Long.parseLong(ndc); nsnStringBuilder.append(ndc); } else { this.ndc = -1; } this.snComponentStrings = snComponents.clone(); //save a copy of the SN component strings final int snComponentCount = snComponents.length; //see how many SN components there are this.snComponents = new long[snComponentCount]; //create an array of SN components for(int i = 0; i < snComponentCount; ++i) { //for each SN component final String snComponent = snComponents[i]; this.snComponents[i] = Long.parseLong(snComponent); //parse this SN component value from the SN component string nsnStringBuilder.append(snComponent); } } else { //if there are no SN components nsnStringBuilder.append(checkInstance(ndc, "Missing National Significant Number.")); //we only know the NSN this.ndc = -1; //we don't know the NDC this.snComponents = Longs.NO_LONGS; //we don't know any SN components this.snComponentStrings = NO_STRINGS; } this.nsn = Long.parseLong(nsnStringBuilder.toString()); this.string = stringBuilder.append(nsnStringBuilder).toString(); } /** * Constructs a telephone number from a string with no default country code. The string must either be a global number beginning with '+' or a local number. * The National Destination Code (NDC) may optionally be surrounded by parentheses. The components of the number may be separated by '-', '.', or ' '. * @param input The character sequence to be parsed into a telephone number. * @throws NullPointerException if the given character sequence is null. * @throws ArgumentSyntaxException if the value violates ITU-T E.164 or ITU-T E.123. */ public TelephoneNumber(final CharSequence input) throws ArgumentSyntaxException { this(input, null); //construct the telephone number with no default country code } /** * Constructs a telephone number by parsing the given string, with a default country code. The string must either be a global number beginning with '+' or a * local number. The National Destination Code (NDC) may optionally be surrounded by parentheses. The components of the number may be separated by '-', '.', * or ' '. * @param telephoneNumber The character sequence to be parsed into a telephone number. * @param defaultCC The Country Code (CC) to use by default, or null if no default country code is provided. * @throws NullPointerException if the given character sequence is null. * @throws ArgumentSyntaxException if the value violates ITU-T E.164 or ITU-T E.123. */ public TelephoneNumber(final CharSequence telephoneNumber, final CountryCode defaultCC) throws ArgumentSyntaxException { this(telephoneNumber, defaultCC != null ? defaultCC.getValue() : -1); //construct the telephone number with the default country code value, if given } /** * Constructs a telephone number from a character sequence in canonical format, with a default country code. The string must either be a global number * beginning with '+' or a local number. The National Destination Code (NDC) may optionally be surrounded by parentheses. The components of the number may be * separated by '-', '.', or ' '. * @param telephoneNumber The character sequence to be parsed into a telephone number. * @param defaultCC The Country Code (CC) to use by default, or -1 if no default country code is provided. * @throws NullPointerException if the given character sequence is null. * @throws ArgumentSyntaxException if the value violates ITU-T E.164 or ITU-T E.123. */ public TelephoneNumber(final CharSequence telephoneNumber, final int defaultCC) throws ArgumentSyntaxException { if(CharSequences.contains(telephoneNumber, SPACING_SYMBOLS)) { throw new ArgumentSyntaxException("Spacing symbols not allowed in canonical telephone number: " + telephoneNumber); } string = telephoneNumber.toString(); //get the first and only component if(CharSequences.startsWith(string, INTERNATIONAL_PREFIX_SYMBOL)) { //if this is an international number, parse out the country code String ccString = CharSequences.getStartsWith(string.substring(1), SHORT_CC_STRINGS); //see if the country code is a short string if(ccString == null) { //if the country code is a long string if(string.length() < 4) { //there must be enough room for a three-digit country code throw new IllegalArgumentException("Invalid Country Code: " + string.substring(1)); } ccString = string.substring(1, 4); //extract the three-digit country code } cc = Integer.parseInt(ccString); //parse the country code nsn = Long.parseLong(string.substring(ccString.length() + 1)); //the NSN is the rest of the number after the '+' and the country code; we don't know its subcomponents } else { //if this is a national number cc = defaultCC; //we don't know the country code; use the default, if any nsn = Long.parseLong(string); //the NSN is all we have, really } ndc = -1; //we don't know the NDC snComponents = Longs.NO_LONGS; //we don't know any SN components snComponentStrings = NO_STRINGS; } /** * Canonicizes the components of the telephone number, if possible, based upon the country code. This implementation canonicizes numbers in country code 1. * @throws ArgumentSyntaxException if the telephone number is not correct for the country code. */ /*TODO migrate to getLabelString() protected void canonicize() throws ArgumentSyntaxException { switch(getCC()) { //see which country code we have case 1: //US and Canada if(ndc < 100 && ndc > 999 || snComponents.length != 2 || snComponents[0] < 100 || snComponents[0] > 999 || snComponents[1] < 1000 || snComponents[1] > 9999) { //if the number isn't in the form (XXX) XXX-XXXX final StringBuilder stringBuilder = new StringBuilder(); //create a string builder final String ndcString = getNDCString(); //get the NDC, if any if(ndcString != null) { //if there is an NDC stringBuilder.append(ndcString); //append the NDC } append(stringBuilder, getSNComponentStrings()); //append the SN components if(stringBuilder.length() != 10) { //if there aren't 10 digits altogether throw new ArgumentSyntaxException("Incorrect number of digits for country code 1 telephone number: " + stringBuilder); } setNDCString(stringBuilder.substring(0, 3)); //save the NDC (area code): digits 1-3 setSNComponentStrings(stringBuilder.substring(3, 6), stringBuilder.substring(6, 10)); //save the SN components and SN component strings } break; } } */ /** * Constructs a string representation of the telephone number in international format according to ITU-T E.123 using the given delimiter. This method must * only be called on a global telephone number. * @param delimiter The delimiter to use to separate the telephone number components, or {@link Characters#UNDEFINED_CHAR} if no delimiter should be used. * @return An international string representation of the telephone number using the specified delimiter. * @throws IllegalStateException if this is not a global telephone number. * @see Characters#UNDEFINED_CHAR * @see #isGlobal() */ protected String getInternationalString(final char delimiter) { if(!isGlobal()) { //if this isn't a global telephone number throw new IllegalStateException("International string cannot be constructed for a local telephone number."); } final StringBuilder stringBuilder = new StringBuilder(); //create a string buffer to hold the telephone number stringBuilder.append(INTERNATIONAL_PREFIX_SYMBOL).append(getCountryCodeString()); //append the country code if(delimiter != UNDEFINED_CHAR) { //if the delimiter is not the null character stringBuilder.append(delimiter); //add the delimiter } final long ndc = getNationalDestinationCode(); //get the national destination code, if there is one; don't use the string, as it may be prefixed by zeros if(ndc >= 0) { //if there is an NDC stringBuilder.append(ndc); //append the national destination code if(delimiter != UNDEFINED_CHAR) { //if the delimiter is not the null character stringBuilder.append(delimiter); //add the delimiter } } stringBuilder.append(getSubscriberNumberString(delimiter)); //append the subscriber number, using the given delimiter return stringBuilder.toString(); //return the telephone number we constructed } /** * Constructs a string representation of the telephone number in national format according to ITU-T E.123 using the given delimiter. If a simple national * string is requested, no parentheses are used for the NDC and the given delimiter is used following the NDC. Otherwise, a space is used after the NDC, * regardless of the delimiter requested. * @param delimiter The delimiter to use to separate the telephone number components, or {@link Characters#UNDEFINED_CHAR} if no delimiter should be used. * @param simple false if the NDC should be surrounded by parentheses. * @return A national string representation of the telephone number using the specified delimiter. * @see Characters#UNDEFINED_CHAR */ protected String getNationalString(final char delimiter, final boolean simple) { final StringBuilder stringBuilder = new StringBuilder(); //create a string buffer to hold the telephone number final String ndcString = getNationalDestinationCodeString(); //get the national destination code, if there is one if(ndcString != null) { //if there is an NDC string if(!simple) { //if this should not be simple stringBuilder.append('('); //( } stringBuilder.append(ndcString); //append the national destination code if(simple) { //if this should be a simple national string if(delimiter != UNDEFINED_CHAR) { //if the delimiter is not the null character stringBuilder.append(delimiter); //add the delimiter } } else { //if this should not be simple stringBuilder.append(')'); //) stringBuilder.append(' '); //separate the NDC with a space, regardless of the requested delimiter } } stringBuilder.append(getSubscriberNumberString(delimiter)); //append the subscriber number, using the given delimiter return stringBuilder.toString(); //return the telephone number we constructed } /** * Constructs a string representation of the telephone number in national format according to ITU-T E.123 using the given delimiter. A space is used after the * NDC, regardless of the delimiter requested. * @param delimiter The delimiter to use to separate the telephone number components, or {@link Characters#UNDEFINED_CHAR} if no delimiter should be used. * @return A national string representation of the telephone number using the specified delimiter. * @see Characters#UNDEFINED_CHAR */ public String getNationalString(final char delimiter) { //TODO rename to format return getNationalString(delimiter, false); //return a normal national string using the delimiter } /** * Constructs a string representation of the telephone number in national format according to ITU-T E.123 using the recommended component separator, a space. * @return A national string representation of the telephone number. * @see #COMPONENT_SEPARATOR */ public String getNationalString() { //TODO rename to format return getNationalString(COMPONENT_SEPARATOR); //return the national string, using a space as a delimiter } /** * Constructs a simple string representation of the telephone number in national format using the given delimiter. * @param delimiter The delimiter to use to separate the telephone number components, or {@link Characters#UNDEFINED_CHAR} if no delimiter should be used. * @return A national string representation of the telephone number using the specified delimiter. * @see Characters#UNDEFINED_CHAR */ public String getSimpleNationalString(final char delimiter) { //TODO rename to format return getNationalString(delimiter, true); //return a normal national string using the delimiter } /** * Constructs a simple string representation of the telephone number in national format with no delimiter. * @return A national string representation of the telephone number. * @see CharacterConstants#UNDEFINED_CHAR */ /*TODO del; loses information public String getPlainNationalString() { return getSimpleNationalString(UNDEFINED_CHAR); //return a simple national string using no delimiter } */ /** * Constructs a human-readable string representation of the telephone number in international format if possible. * @param delimiter The delimiter to use to separate the telephone number components, or {@link Characters#UNDEFINED_CHAR} if no delimiter should be used. * @return A string representation of the telephone number using the specified delimiter. */ public String getLabel(final char delimiter) { if(isGlobal()) { //if this is a global telephone number return getInternationalString(delimiter); //return an international string } else { //if this is a local telephone number return getNationalString(delimiter); //return a national string } } /** * Constructs a human-readable string representation of the telephone number as specified in ITU-T E.123, using international format if possible. * @return A string representation of the telephone number as specified in ITU-T E.123. * @see #COMPONENT_SEPARATOR */ public String getLabel() { return getLabel(COMPONENT_SEPARATOR); //return the string, using a space as a delimiter } /** * Constructs a simple string representation of the telephone number in international format if possible. * @param delimiter The delimiter to use to separate the telephone number components, or {@link Characters#UNDEFINED_CHAR} if no delimiter should be used. * @return A simple string representation of the telephone number using the specified delimiter. * @see #getSimpleNationalString(char) */ public String getSimpleString(final char delimiter) { if(isGlobal()) { //if this is a global telephone number return getInternationalString(delimiter); //return an international string } else { //if this is a local telephone number return getSimpleNationalString(delimiter); //return a national string } } /** * Constructs a string representation of the telephone number with no delimiter, using international format if possible. * @return A plain string representation of the telephone number. */ /*TODO del; loses information public String getPlainString() { if(isGlobal()) { //if this is a global telephone number return getInternationalString(UNDEFINED_CHAR); //return an international string without any delimiter } else { //if this is a local telephone number return getPlainNationalString(); //return a plain national string } } */ /** @return A hash code representing this object. */ public int hashCode() { return Objects.getHashCode(getCountryCode(), getNationalDestinationCodeString(), getSubscriberNumberComponentStrings()); //return a hash code for the country code, NDC string, and SN component strings } /** * Determines if this object is equivalent to another object. This method considers another object equivalent if it is another telephone number with the same * Country Code and National Significant Number. * @return true if the given object is an equivalent telephone number. */ public boolean equals(final Object object) { if(this == object) { return true; } if(!(object instanceof TelephoneNumber)) { //if the other object is a telephone number return false; } final TelephoneNumber telephoneNumber = (TelephoneNumber)object; //get the other object as a telephone number return getCountryCode() == telephoneNumber.getCountryCode() && getNationalNumber() == telephoneNumber.getNationalNumber(); } /** * Compares this object with the specified object for order. This implementation compares first country code and then National Significant Number. * @param telephoneNumber The object to be compared. * @return A negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. */ public int compareTo(final TelephoneNumber telephoneNumber) { int result = getCountryCode() - telephoneNumber.getCountryCode(); if(result == 0) { result = Longs.compare(getNationalNumber(), telephoneNumber.getNationalNumber()); } return result; } /** * Returns the E.164 canonical representation of the telephone number, with no delimiters except the beginning international prefix symbol if this is a global * number. * @return The canonical string representation of the telephone number. */ public String getCanonicalString() { return string; } /** * Returns a string representation of the telephone number. *

* This implementation returns the E.164 canonical version of the telephone number, with no delimiters except the beginning international prefix symbol if * this is a global number. *

* @return A string representation of the telephone number. * @see #getCanonicalString() */ public String toString() { return getCanonicalString(); } //Resource /** @return The resource identifier URI, or null if the identifier is not known. */ public URI getURI() { //TODO decide if we want to implement resource return URI.create("tel:" + getSimpleString('-')); //construct the reference URI TODO fix to work with TEL URI RFC } /** * Parses a telephone number into a canonical telephone number, with no default country code. The string must either be a global number beginning with '+' or * a local number. The National Destination Code (NDC) may optionally be surrounded by parentheses. The components of the number may be separated by '-', '.', * or ' '. * @param telephoneNumber The character sequence to be parsed into a telephone number. * @return A canonical telephone number. * @throws NullPointerException if the given character sequence is null. * @throws ArgumentSyntaxException if the value violates ITU-T E.164 or ITU-T E.123. */ public static TelephoneNumber parse(CharSequence telephoneNumber) throws ArgumentSyntaxException { return parse(telephoneNumber, -1); } /** * Parses a telephone number into a canonical telephone number, with a default country code. The string must either be a global number beginning with '+' or a * local number. The National Destination Code (NDC) may optionally be surrounded by parentheses. The components of the number may be separated by '-', '.', * or ' '. * @param telephoneNumber The character sequence to be parsed into a telephone number. * @param defaultCC The Country Code (CC) to use by default, or -1 if no default country code is provided. * @return A canonical telephone number. * @throws NullPointerException if the given character sequence is null. * @throws ArgumentSyntaxException if the value violates ITU-T E.164 or ITU-T E.123. */ public static TelephoneNumber parse(CharSequence telephoneNumber, final int defaultCC) throws ArgumentSyntaxException { final StringBuilder telephoneNumberStringBuilder = new StringBuilder( checkInstance(telephoneNumber, "Telephone number character sequence must not be null.")); //we may need to manipulate the telephone number, first String ccString; if(CharSequences.startsWith(telephoneNumberStringBuilder, INTERNATIONAL_PREFIX_SYMBOL)) { //if this is an international number, parse out the country code ccString = CharSequences.getStartsWith(telephoneNumberStringBuilder, 1, SHORT_CC_STRINGS); //see if the country code is a short string if(ccString == null) { //if the country code is a long string if(telephoneNumberStringBuilder.length() < 4) { //there must be enough room for a three-digit country code throw new IllegalArgumentException("Invalid Country Code: " + telephoneNumberStringBuilder.substring(1)); } ccString = telephoneNumberStringBuilder.substring(1, 4); //extract the three-digit country code } telephoneNumberStringBuilder.delete(0, ccString.length() + 1); //remove the country code and delimiter from the beginning } else { //if there is no country code ccString = defaultCC >= 0 ? Integer.toString(defaultCC) : null; //use the default } boolean ndcIndicated = false; final int leftParenthesisIndex = indexOf(telephoneNumberStringBuilder, '('); //see if there is a left parenthesis in the string if(leftParenthesisIndex >= 0) { //if there is a left parenthesis ndcIndicated = true; telephoneNumberStringBuilder.setCharAt(leftParenthesisIndex, COMPONENT_SEPARATOR); //replace the left parenthesis with a separator } final int rightParenthesisIndex = indexOf(telephoneNumberStringBuilder, ')'); //see if there is a right parenthesis in the string if(rightParenthesisIndex >= 0) { //if there is a right parenthesis telephoneNumberStringBuilder.setCharAt(rightParenthesisIndex, COMPONENT_SEPARATOR); //replace the right parenthesis with a separator } if(((leftParenthesisIndex >= 0) != (rightParenthesisIndex >= 0)) || leftParenthesisIndex > rightParenthesisIndex) { throw new ArgumentSyntaxException("Mismatched parentheses: " + telephoneNumber); } trim(telephoneNumberStringBuilder, SPACING_SYMBOLS); //remove all delimiters from the beginning and end of the string, or they will produce empty components final String[] components = SPACING_PATTERN.split(telephoneNumberStringBuilder); //get the components of the telephone number, using any modifications we made up front //TODO del Log.trace("Found components", Arrays.toString(components)); final String ndcString; final String[] snComponentStrings; final int componentCount = components.length; //find out the number of components if(componentCount == 0) { //if there are no components at all throw new ArgumentSyntaxException("No National Significant Number: " + telephoneNumber); } else if(componentCount == 1) { //if the components aren't separated if(ndcIndicated == true) { throw new IllegalArgumentException("NDC indicated but no subscriber number components provided."); } ndcString = components[0]; //use the rest of the number as the "NDC" to indicate the NSN snComponentStrings = NO_STRINGS; } else { //if there are components if(ndcIndicated == true) { ndcString = components[0]; //the first component is the NDC snComponentStrings = com.globalmentor.java.Arrays.createCopy(components, 1); //use the other components for the SN components } else { //if no NDC was indicated ndcString = null; //no NDC was indicated snComponentStrings = components.clone(); } } return new TelephoneNumber(ccString, ndcString, snComponentStrings); //create the telephone number } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy