/*
* Copyright 2004-2005 Revolution Systems 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.revolsys.ui.html.domain;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.jexl.Expression;
import org.apache.commons.jexl.context.HashMapContext;
import com.revolsys.util.JexlUtil;
public final class PhoneNumber {
/** The default country to use if one was not specified. */
private static Country defaultCountry = Country.getCountry("US");
/**
* Format the phone number using the format for the default country. If the
* phone number does not match the specification for that country the first
* few digits of the phone number will be used to lookup a matching country
* and formatted using that country, if that fails the unformatted phone
* number will be returned.
*
* @param phoneNumber The normalized phone number to format.
* @return The formatted phone number.
*/
public static String format(final String phoneNumber) {
return format(phoneNumber, defaultCountry);
}
/**
* Format the phone number using the National format specification defined for
* the Country. If the phone number does not match the specification for that
* country the first few digits of the phone number will be used to lookup a
* matching country and formatted using that country, if that fails the
* unformatted phone number will be returned.
*
* @param phoneNumber The normalized phone number to format.
* @param country The Country the phone number should be formatted for.
* @return The formatted phone number.
*/
public static String format(final String phoneNumber, final Country country) {
return format(phoneNumber, country, false);
}
/**
* Format the phone number using the specification defined for the Country. If
* the international parameter is set to true then use the International phone
* number format with the country code prefix, otherwise use the National
* phone number format. If the phone number does not match the specification
* for that country the first few digits of the phone number will be used to
* lookup a matching country and formatted using that country's international
* format, if that fails the unformatted phone number will be returned.
*
* @param phoneNumber The normalized phone number to format.
* @param country The Country the phone number should be formatted for.
* @param international True if the phone number should use the international
* format.
* @return The formatted phone number.
*/
public static String format(final String phoneNumber, final Country country,
final boolean international) {
String formattedNumber = null;
if (phoneNumber == null) {
return null;
}
if (country != null) {
if (international) {
formattedNumber = format(phoneNumber, country.getPhoneRegEx(),
country.getPhoneInternationalFormat());
} else {
formattedNumber = format(phoneNumber, country.getPhoneRegEx(),
country.getPhoneNationalFormat());
}
}
if (formattedNumber == null) {
final Country potentialCountry = Country.getCountryByPhoneNumber(phoneNumber);
if (potentialCountry != null) {
formattedNumber = format(phoneNumber, potentialCountry.getPhoneRegEx(),
potentialCountry.getPhoneInternationalFormat());
}
}
if (formattedNumber == null) {
return phoneNumber;
} else {
return formattedNumber;
}
}
/**
* Format the phone number using the National format specification defined for
* the Locale. If the phone number does not match the specification for that
* locale the first few digits of the phone number will be used to lookup a
* matching country and formatted using that locale, if that fails the
* unformatted phone number will be returned.
*
* @param phoneNumber The normalized phone number to format.
* @param locale The Locale the phone number should be formatted for.
* @return The formatted phone number.
*/
public static String format(final String phoneNumber, final Locale locale) {
return format(phoneNumber, Country.getCountry(locale.getCountry()), false);
}
/**
* Parse a phone number using the regular expression and if it matches the
* phone number, format it using the specified format otherwise return null.
*
* @param phoneNumber The normalized phone number to format.
* @param regex The regular expression to match phone numbers.
* @param format The format specification.
* @return The formatted phone number.
*/
public static String format(final String phoneNumber, final String regex, final String format) {
if (phoneNumber != null && regex != null && format != null) {
final Pattern pattern = Pattern.compile(regex);
final Matcher matcher = pattern.matcher(phoneNumber);
if (matcher.matches()) {
final Map values = new HashMap();
for (int i = 1; i <= matcher.groupCount(); i++) {
values.put("n" + i, matcher.group(i));
}
Expression expression;
try {
expression = JexlUtil.newExpression(format);
} catch (final Exception e) {
throw new IllegalArgumentException(
regex + " is not a valid regular expression: " + e.getMessage());
}
final HashMapContext context = new HashMapContext();
context.setVars(values);
try {
return (String)expression.evaluate(context);
} catch (final Exception e) {
throw new IllegalArgumentException(format + " is not a valid format: " + e.getMessage());
}
}
}
return null;
}
public static boolean isValid(final String phoneNumber) {
final String number = normalize(phoneNumber);
return Pattern.matches("^\\d+$", number);
}
/**
* Normalize the phone number removing any non-digit characters.
*
* @param phoneNumber The phone number.
* @return The normalized phone number.
*/
public static String normalize(final String phoneNumber) {
if (phoneNumber != null) {
return phoneNumber.replaceAll("[\\+\\(\\)\\-\\s]+", "");
}
return phoneNumber;
}
/**
* Construct a new PhoneNumber.
*/
private PhoneNumber() {
}
}