// ============================================================================ // // Copyright (C) 2006-2016 qiongli Inc. - www.qiongli.com // // This source code is available under agreement available at // %InstallDIR%\features\org.qiongli.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt // // You should have received a copy of the agreement // along with this program; if not, write to qiongli SA // 9 rue Pages 92150 Suresnes, France // // ============================================================================ package org.talend.dataquality.standardization.phone; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import com.google.i18n.phonenumbers.PhoneNumberToCarrierMapper; import com.google.i18n.phonenumbers.PhoneNumberToTimeZonesMapper; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberType; import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; import com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder; /** * DOC qiongli class global comment. Detailled comment */ public class PhoneNumberHandlerBase { private static final Logger LOG = Logger.getLogger(PhoneNumberHandlerBase.class); private static PhoneNumberUtil GOOGLE_PHONE_UTIL = PhoneNumberUtil.getInstance(); /** * * Parses a string or number and returns it in proto buffer format. * * @param data A String or Number * @param regionCode we are expecting the number to be from. This is only used if the number being parsed is not * written in international format. The country_code for the number in this case would be stored as that of the * default region supplied. If the number is guaranteed to start with a '+' followed by the country calling code, * then "ZZ" or null can be supplied. like as "+86 12345678912" * @return */ protected static PhoneNumber parseToPhoneNumber(Object data, String regionCode) { if (data == null || StringUtils.isBlank(data.toString())) { return null; } PhoneNumber phonenumber = null; try { phonenumber = GOOGLE_PHONE_UTIL.parse(data.toString(), regionCode); } catch (Exception e) { LOG.error("Phone number parsing exception with " + data, e); //$NON-NLS-1$ return null; } return phonenumber; } /** * * whether a phone number is valid for a certain region. * * @param data the data that we want to validate * @param regionCode the regionCode that we want to validate the phone number from * @return a boolean that indicates whether the number is of a valid pattern */ public static boolean isValidPhoneNumber(Object data, String regionCode) { PhoneNumber phonenumber = null; try { phonenumber = GOOGLE_PHONE_UTIL.parse(data.toString(), regionCode); } catch (Exception e) { LOG.error(e.getMessage(), e); return false; } return GOOGLE_PHONE_UTIL.isValidNumberForRegion(phonenumber, regionCode); } /** * * Check whether a phone number is a possible number given a number in the form of a object, and the region where * the number could be dialed from. * * @param data the data that we want to validate * @param regionCode the regionCode that we are expecting the number to be dialed from. * @return */ public static boolean isPossiblePhoneNumber(Object data, String regionCode) { if (data == null || StringUtils.isBlank(data.toString())) { return false; } return GOOGLE_PHONE_UTIL.isPossibleNumber(data.toString(), regionCode); } /** * * Formats a phone number to E164 form . * * @param data the data that we want to validate * @param regionCode the regionCode that we are expecting the number to be dialed from * @return the formatted phone number like as "+12423651234" */ public static String formatE164(Object data, String regionCode) { PhoneNumber phonemuber = parseToPhoneNumber(data, regionCode); if (phonemuber == null) { return StringUtils.EMPTY; } return GOOGLE_PHONE_UTIL.format(phonemuber, PhoneNumberFormat.E164); } /** * * Formats a phone number to International form. * * @param data the data that we want to validate * @param regionCode the regionCode that we are expecting the number to be dialed from * @return the formatted phone number like as "+1 242-365-1234" */ public static String formatInternational(Object data, String regionCode) { PhoneNumber phonemuber = parseToPhoneNumber(data, regionCode); if (phonemuber == null) { return StringUtils.EMPTY; } return GOOGLE_PHONE_UTIL.format(phonemuber, PhoneNumberFormat.INTERNATIONAL); } /** * * Formats a phone number to National form . * * @param data the data that we want to validate * @param regionCode the regionCode that we are expecting the number to be dialed from * @return the formatted phone number like as "(242) 365-1234" */ public static String formatNational(Object data, String regionCode) { PhoneNumber phonemuber = parseToPhoneNumber(data, regionCode); if (phonemuber == null) { return StringUtils.EMPTY; } return GOOGLE_PHONE_UTIL.format(phonemuber, PhoneNumberFormat.NATIONAL); } /** * * Formats a phone number to RFC396 form . * * @param data the data that we want to validate * @param regionCode the regionCode that we are expecting the number to be dialed from * @return the formatted phone number like as "tel:+1-242-365-1234" */ public static String formatRFC396(Object data, String regionCode) { PhoneNumber phonemuber = parseToPhoneNumber(data, regionCode); if (phonemuber == null) { return StringUtils.EMPTY; } return GOOGLE_PHONE_UTIL.format(phonemuber, PhoneNumberFormat.RFC3966); } /** * * get all supported regions. * * @return */ public static Set<String> getSupportedRegions() { return GOOGLE_PHONE_UTIL.getSupportedRegions(); } /** * * Get country code by the region code * * @param regionCode * @return */ public static int getCountryCodeForRegion(String regionCode) { return GOOGLE_PHONE_UTIL.getCountryCodeForRegion(regionCode); } /** * * DOC qiongli Comment method "getPhoneNumberType". * * @param data * @param regionCode * @return */ public static PhoneNumberTypeEnum getPhoneNumberType(Object data, String regionCode) { PhoneNumber number = parseToPhoneNumber(data, regionCode); if (number != null) { PhoneNumberType numberType = GOOGLE_PHONE_UTIL.getNumberType(number); switch (numberType) { case FIXED_LINE: return PhoneNumberTypeEnum.FIXED_LINE; case MOBILE: return PhoneNumberTypeEnum.MOBILE; case FIXED_LINE_OR_MOBILE: return PhoneNumberTypeEnum.FIXED_LINE_OR_MOBILE; case PAGER: return PhoneNumberTypeEnum.PAGER; case PERSONAL_NUMBER: return PhoneNumberTypeEnum.PERSONAL_NUMBER; case TOLL_FREE: return PhoneNumberTypeEnum.TOLL_FREE; case PREMIUM_RATE: return PhoneNumberTypeEnum.PREMIUM_RATE; case SHARED_COST: return PhoneNumberTypeEnum.SHARED_COST; case UAN: return PhoneNumberTypeEnum.UAN; case VOICEMAIL: return PhoneNumberTypeEnum.VOICEMAIL; case VOIP: return PhoneNumberTypeEnum.VOIP; default: } } return PhoneNumberTypeEnum.UNKNOWN; } /** * * whether a phone number contain a valid region. * * @param data a phone number String or number. the data string must be guaranteed to start with a '+' followed by * the country calling code. like as "+1 242-365-1234" or "+12423651234" * @return */ public static boolean containsValidRegionCode(Object data) { String regionCode = extractRegionCode(data); return regionCode != null && getSupportedRegions().contains(regionCode); } /** * * get a region code from an phone number. * * @param phoneData a phone number String or number. the data string must be guaranteed to start with a '+' followed * by the country calling code. like as "+1 242-365-1234" or "+12423651234" * @return */ public static String extractRegionCode(Object phoneData) { PhoneNumber phoneNumber = parseToPhoneNumber(phoneData, null); if (phoneNumber != null) { return GOOGLE_PHONE_UTIL.getRegionCodeForNumber(phoneNumber); } return StringUtils.EMPTY; } /** * * get a country code from an phone number. * * @param phoneData a phone number String or number. the data string must be guaranteed to start with a '+' followed * by the country calling code. like as "+1 242-365-1234" or "+12423651234" * @return */ public static int extractCountrycode(Object phoneData) { PhoneNumber phoneNumber = parseToPhoneNumber(phoneData, null); if (phoneNumber != null) { return phoneNumber.getCountryCode(); } return 0; } /** * * Returns a text description for the given phone number, in the language provided. The description might consist of * the name of the country where the phone number is from, or the name of the geographical area the phone number is * from if more detailed information is available. * * @param data * @param regionCode the regionCode that we are expecting the number to be dialed from * @param languageCode the language code for which the description should be written.the 'Locale.ENGLISH' is the * most commonly used * @return */ public static String getGeocoderDescriptionForNumber(Object data, String regionCode, Locale languageCode) { PhoneNumber number = parseToPhoneNumber(data, regionCode); if (number != null) { return PhoneNumberOfflineGeocoder.getInstance().getDescriptionForNumber(number, languageCode); } return StringUtils.EMPTY; } /** * * Gets the name of the carrier for the given phone number, in the language provided.The carrier name is the one the * number was originally allocated to, however if the country supports mobile number portability the number might * not belong to the returned carrier anymore. If no mapping is found an empty string is returned. * * @param data the phone number for which we want to get a carrier name * @param regionCode the regionCode that we are expecting the number to be dialed from * @param languageCode the language code for which the description should be written.the 'Locale.ENGLISH' is the * most commonly used * @return */ public static String getCarrierNameForNumber(Object data, String regionCode, Locale languageCode) { PhoneNumber number = parseToPhoneNumber(data, regionCode); if (number == null) { return StringUtils.EMPTY; } return PhoneNumberToCarrierMapper.getInstance().getNameForNumber(number, languageCode); } /** * * Returns a list of time zones to which a phone number belongs. when the PhoneNumber is invalid ,return UNKONW TIME * ZONE;when the PhoneNumberType is Not FIXED_LINE,MOBILE,FIXED_LINE_OR_MOBILE,return the list of time zones * corresponding to the country calling code; or else,return the list of corresponding time zones * * @param data the phone number for which we want to get a list of Time zones * @param regionCode * @return */ public static List<String> getTimeZonesForNumber(Object data, String regionCode) { PhoneNumber number = parseToPhoneNumber(data, regionCode); if (number == null) { List<String> unknowTimeZoneLs = new ArrayList<>(1); unknowTimeZoneLs.add(PhoneNumberToTimeZonesMapper.getUnknownTimeZone()); return unknowTimeZoneLs; } return PhoneNumberToTimeZonesMapper.getInstance().getTimeZonesForNumber(number); } }