Separates phone number service, to be a service in separate bundle and improves the number matching when searching for phone numbers.

fix-message-formatting 5189
Damian Minkov 12 years ago
parent a278bda96e
commit db8071c2d4

@ -66,6 +66,7 @@
<classpathentry kind="lib" path="lib/installer-exclude/otr4j.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/pircbot.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/profiler4j-1.0-beta3-SC.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/libphonenumber-5.9.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/sdes4j.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/smack.jar" sourcepath="lib/installer-exclude/smack-src.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/smackx.jar"/>

@ -1047,7 +1047,7 @@
bundle-protocol,bundle-protocol-media,bundle-icq,
bundle-icq-slick,bundle-mock,bundle-smacklib,bundle-jmdnslib,
bundle-jabber,bundle-jabber-slick,bundle-swing-ui,bundle-ui-service,
bundle-jnalib,
bundle-jnalib,bundle-phonenumbers,
bundle-msn,bundle-msn-slick,bundle-yahoo,bundle-yahoo-slick,
bundle-contactlist,meta-contactlist,meta-contactlist-slick,
bundle-plugin-icqaccregwizz,bundle-plugin-jabberaccregwizz,
@ -1529,6 +1529,17 @@ javax.swing.event, javax.swing.border"/>
</jar>
</target>
<!-- BUNDLE-PHONENUMBER-SERVICE -->
<target name="bundle-phonenumbers">
<!-- Creates a bundle containing the icq impl of the protocol provider.-->
<jar compress="false" destfile="${bundles.dest}/phonenumbers.jar"
manifest="${src}/net/java/sip/communicator/impl/phonenumbers/phonenumbers.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/impl/phonenumbers"
prefix="net/java/sip/communicator/impl/phonenumbers"/>
<zipfileset src="${lib.noinst}/libphonenumber-5.9.jar" prefix=""/>
</jar>
</target>
<target name="bundle-jmdnslib">
<!-- Creates a bundle containing the jmdns lib.-->
<jar compress="false" destfile="${bundles.dest}/jmdnslib.jar"

@ -111,6 +111,7 @@ felix.auto.start.49= \
# and the implementations only after
felix.auto.start.50= \
reference:file:sc-bundles/contactlist.jar \
reference:file:sc-bundles/phonenumbers.jar \
reference:file:sc-bundles/json.jar
felix.auto.start.52= \

@ -70,6 +70,11 @@ public class GoogleContactsActivator implements BundleActivator
private static Map<GoogleContactsSourceService, ServiceRegistration> cssList
= new HashMap<GoogleContactsSourceService, ServiceRegistration>();
/**
* The registered PhoneNumberI18nService.
*/
private static PhoneNumberI18nService phoneNumberI18nService;
/**
* Returns a reference to a ConfigurationService implementation currently
* registered in the bundle context or null if no such implementation was
@ -480,4 +485,20 @@ public static void disableContactSource(GoogleContactsConnection cnx)
cssList.remove(found);
}
}
/**
* Returns the PhoneNumberI18nService.
* @return returns the PhoneNumberI18nService.
*/
public static PhoneNumberI18nService getPhoneNumberI18nService()
{
if(phoneNumberI18nService == null)
{
phoneNumberI18nService = ServiceUtils.getService(
bundleContext,
PhoneNumberI18nService.class);
}
return phoneNumberI18nService;
}
}

@ -208,7 +208,8 @@ private List<ContactDetail> getContactDetails(GoogleContactsEntry entry)
supportedOpSets.add(OperationSetBasicTelephony.class);
// can be added as contacts
supportedOpSets.add(OperationSetPersistentPresence.class);
homePhone = PhoneNumberI18nService.normalize(homePhone);
homePhone = GoogleContactsActivator.getPhoneNumberI18nService()
.normalize(homePhone);
detail = new ContactDetail(homePhone,
ContactDetail.Category.Phone,
new ContactDetail.SubCategory[]{
@ -225,7 +226,8 @@ private List<ContactDetail> getContactDetails(GoogleContactsEntry entry)
supportedOpSets.add(OperationSetBasicTelephony.class);
// can be added as contacts
supportedOpSets.add(OperationSetPersistentPresence.class);
workPhone = PhoneNumberI18nService.normalize(workPhone);
workPhone = GoogleContactsActivator.getPhoneNumberI18nService()
.normalize(workPhone);
detail = new ContactDetail(workPhone,
ContactDetail.Category.Phone,
new ContactDetail.SubCategory[]{
@ -242,7 +244,8 @@ private List<ContactDetail> getContactDetails(GoogleContactsEntry entry)
supportedOpSets.add(OperationSetBasicTelephony.class);
// can be added as contacts
supportedOpSets.add(OperationSetPersistentPresence.class);
mobilePhone = PhoneNumberI18nService.normalize(mobilePhone);
mobilePhone = GoogleContactsActivator.getPhoneNumberI18nService()
.normalize(mobilePhone);
detail = new ContactDetail(mobilePhone,
ContactDetail.Category.Phone,
new ContactDetail.SubCategory[]{

@ -121,6 +121,11 @@ public class GuiActivator implements BundleActivator
private static final Map<String, ReplacementService>
replacementSourcesMap = new Hashtable<String, ReplacementService>();
/**
* The registered PhoneNumberI18nService.
*/
private static PhoneNumberI18nService phoneNumberI18nService;
/**
* Indicates if this bundle has been started.
*/
@ -910,4 +915,20 @@ public static MessageHistoryService getMessageHistoryService()
MessageHistoryService.class);
return messageHistoryService;
}
/**
* Returns the PhoneNumberI18nService.
* @return returns the PhoneNumberI18nService.
*/
public static PhoneNumberI18nService getPhoneNumberI18nService()
{
if(phoneNumberI18nService == null)
{
phoneNumberI18nService = ServiceUtils.getService(
bundleContext,
PhoneNumberI18nService.class);
}
return phoneNumberI18nService;
}
}

@ -912,7 +912,8 @@ public static void createCall( String callString,
if (ConfigurationUtils.isNormalizePhoneNumber()
&& !NetworkUtils.isValidIPAddress(callString))
{
callString = PhoneNumberI18nService.normalize(callString);
callString = GuiActivator.getPhoneNumberI18nService()
.normalize(callString);
}
List<ProtocolProviderService> telephonyProviders
@ -2519,8 +2520,8 @@ else if(formats.isEmpty())
if (stringContact != null)
{
stringContact
= PhoneNumberI18nService.normalize(stringContact);
stringContact = GuiActivator.getPhoneNumberI18nService()
.normalize(stringContact);
}
}
@ -3555,7 +3556,8 @@ private static boolean showDesktopSharingWarning()
private static void normalizePhoneNumbers(String callees[])
{
for (int i = 0 ; i < callees.length ; i++)
callees[i] = PhoneNumberI18nService.normalize(callees[i]);
callees[i] = GuiActivator.getPhoneNumberI18nService()
.normalize(callees[i]);
}
/**

@ -58,6 +58,12 @@ public class SearchFilter
private static Map<Integer, Integer> contactSourceOrder
= new HashMap<Integer, Integer>();
/**
* If set, we are searching a phone number and will use the phone number
* service to try matching the numbers.
*/
private boolean isSearchingPhoneNumber = false;
/**
* Creates an instance of <tt>SearchFilter</tt>.
*/
@ -260,6 +266,9 @@ public void setFilterString(String filter)
Pattern.MULTILINE
| Pattern.CASE_INSENSITIVE
| Pattern.UNICODE_CASE);
this.isSearchingPhoneNumber
= GuiActivator.getPhoneNumberI18nService().isPhoneNumber(filter);
}
/**
@ -270,9 +279,10 @@ public void setFilterString(String filter)
*/
private boolean isMatching(String text)
{
if (filterPattern != null)
return filterPattern.matcher(text).find();
return true;
return (filterPattern != null
&& filterPattern.matcher(text).find())
|| (isSearchingPhoneNumber
&& GuiActivator.getPhoneNumberI18nService()
.phoneNumbersMatch(this.filterString, text));
}
}

@ -10,6 +10,7 @@
import net.java.sip.communicator.service.contactsource.*;
import net.java.sip.communicator.service.ldap.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import org.jitsi.service.resources.*;
@ -60,6 +61,11 @@ public static LdapService getLdapService()
private static Map<LdapContactSourceService, ServiceRegistration> cssList =
new HashMap<LdapContactSourceService, ServiceRegistration>();
/**
* The registered PhoneNumberI18nService.
*/
private static PhoneNumberI18nService phoneNumberI18nService;
/**
* Starts the LDAP service
*
@ -231,4 +237,20 @@ public static void unregisterContactSource(LdapDirectory ldapDir)
cssList.remove(found);
}
}
/**
* Returns the PhoneNumberI18nService.
* @return returns the PhoneNumberI18nService.
*/
public static PhoneNumberI18nService getPhoneNumberI18nService()
{
if(phoneNumberI18nService == null)
{
phoneNumberI18nService = ServiceUtils.getService(
bundleContext,
PhoneNumberI18nService.class);
}
return phoneNumberI18nService;
}
}

@ -149,7 +149,9 @@ private List<ContactDetail> getContactDetails(LdapPersonFound person)
Set<String> mobilePhones = person.getMobilePhone();
Set<String> homePhones = person.getHomePhone();
Set<String> workPhones = person.getWorkPhone();
ContactDetail detail = null;
ContactDetail detail;
PhoneNumberI18nService phoneNumberI18nService
= LdapActivator.getPhoneNumberI18nService();
for(String mail : mailAddresses)
{
@ -161,7 +163,7 @@ private List<ContactDetail> getContactDetails(LdapPersonFound person)
for(String homePhone : homePhones)
{
homePhone = PhoneNumberI18nService.normalize(homePhone);
homePhone = phoneNumberI18nService.normalize(homePhone);
detail = new ContactDetail(homePhone,
ContactDetail.Category.Phone,
new ContactDetail.SubCategory[]{
@ -175,7 +177,7 @@ private List<ContactDetail> getContactDetails(LdapPersonFound person)
for(String workPhone : workPhones)
{
workPhone = PhoneNumberI18nService.normalize(workPhone);
workPhone = phoneNumberI18nService.normalize(workPhone);
detail = new ContactDetail(workPhone,
ContactDetail.Category.Phone,
new ContactDetail.SubCategory[]{
@ -189,7 +191,7 @@ private List<ContactDetail> getContactDetails(LdapPersonFound person)
for(String mobilePhone : mobilePhones)
{
mobilePhone = PhoneNumberI18nService.normalize(mobilePhone);
mobilePhone = phoneNumberI18nService.normalize(mobilePhone);
detail = new ContactDetail(mobilePhone,
ContactDetail.Category.Phone,
new ContactDetail.SubCategory[]{

@ -0,0 +1,241 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.phonenumbers;
import com.google.i18n.phonenumbers.*;
import net.java.sip.communicator.service.protocol.*;
import org.jitsi.service.configuration.*;
import java.util.regex.*;
/**
* Implements <tt>PhoneNumberI18nService</tt> which aids the parsing, formatting
* and validating of international phone numbers.
*
* @author Lyubomir Marinov
* @author Vincent Lucas
* @author Damian Minkov
*/
public class PhoneNumberI18nServiceImpl
implements PhoneNumberI18nService
{
/**
* The configuration service.
*/
private static ConfigurationService configService
= ProtocolProviderActivator.getConfigurationService();
/**
* Characters which have to be removed from a phone number in order to
* normalized it.
*/
private static final Pattern removedCharactersToNormalizedPhoneNumber
= Pattern.compile("[-\\(\\)\\.\\\\\\/ ]");
/**
* Characters which have to be removed from a number (which is not a phone
* number, such as a sip id, a jabber id, etc.) in order to normalized it.
*/
private static final Pattern removedCharactersToNormalizedIdentifier
= Pattern.compile("[\\(\\) ]");
/**
* The list of characters corresponding to the number 2 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber2
= Pattern.compile("[abc]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 3 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber3
= Pattern.compile("[def]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 4 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber4
= Pattern.compile("[ghi]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 5 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber5
= Pattern.compile("[jkl]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 6 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber6
= Pattern.compile("[mno]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 7 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber7
= Pattern.compile("[pqrs]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 8 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber8
= Pattern.compile("[tuv]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 9 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber9
= Pattern.compile("[wxyz]", Pattern.CASE_INSENSITIVE);
/**
* Normalizes a <tt>String</tt> which may be a phone number or a identifier
* by removing useless characters and, if necessary, replacing the alpahe
* characters in corresponding dial pad numbers.
*
* @param possibleNumber a <tt>String</tt> which may represents a phone
* number or an identifier to normalize.
*
* @return a <tt>String</tt> which is a normalized form of the specified
* <tt>possibleNumber</tt>.
*/
public String normalize(String possibleNumber)
{
String normalizedNumber;
if(isPhoneNumber(possibleNumber))
{
normalizedNumber = normalizePhoneNumber(possibleNumber);
}
else
{
normalizedNumber = normalizeIdentifier(possibleNumber);
}
return normalizedNumber;
}
/**
* Normalizes a <tt>String</tt> phone number by converting alpha characters
* to their respective digits on a keypad and then stripping non-digit
* characters.
*
* @param phoneNumber a <tt>String</tt> which represents a phone number to
* normalize
*
* @return a <tt>String</tt> which is a normalized form of the specified
* <tt>phoneNumber</tt>
*
* @see net.java.sip.communicator.impl.phonenumbers.PhoneNumberI18nServiceImpl#normalize(String)
*/
private static String normalizePhoneNumber(String phoneNumber)
{
phoneNumber = convertAlphaCharactersInNumber(phoneNumber);
return removedCharactersToNormalizedPhoneNumber
.matcher(phoneNumber).replaceAll("");
}
/**
* Removes useless characters from a identifier (which is not a phone
* number) in order to normalized it.
*
* @param id The identifier string with some useless characters like: " ",
* "(", ")".
*
* @return The normalized identifier.
*/
private static String normalizeIdentifier(String id)
{
return removedCharactersToNormalizedIdentifier
.matcher(id).replaceAll("");
}
/**
* Determines whether two <tt>String</tt> phone numbers match.
*
* @param aPhoneNumber a <tt>String</tt> which represents a phone number to
* match to <tt>bPhoneNumber</tt>
* @param bPhoneNumber a <tt>String</tt> which represents a phone number to
* match to <tt>aPhoneNumber</tt>
* @return <tt>true</tt> if the specified <tt>String</tt>s match as phone
* numbers; otherwise, <tt>false</tt>
*/
public boolean phoneNumbersMatch(String aPhoneNumber, String bPhoneNumber)
{
PhoneNumberUtil.MatchType match = PhoneNumberUtil.getInstance()
.isNumberMatch(aPhoneNumber, bPhoneNumber);
return match != PhoneNumberUtil.MatchType.NOT_A_NUMBER
&& match != PhoneNumberUtil.MatchType.NO_MATCH;
}
/**
* Indicates if the given string is possibly a phone number.
*
* @param possibleNumber the string to be verified
* @return <tt>true</tt> if the possibleNumber is a phone number,
* <tt>false</tt> - otherwise
*/
public boolean isPhoneNumber(String possibleNumber)
{
// If the string does not contains an "@", this may be a phone number.
if(possibleNumber.indexOf('@') == -1)
{
// If the string does not contain any alphabetical characters, then
// this is a phone number.
if(!possibleNumber.matches(".*[a-zA-Z].*"))
{
return true;
}
else
{
// Removes the " ", "(" and ")" in order to search the "+"
// character at the beginning at the string.
String tmpPossibleNumber
= possibleNumber.replaceAll(" \\(\\)", "");
// If the property is enabled and the string starts with a "+",
// then we consider that this is a phone number.
if(configService.getBoolean(
"impl.gui.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS",
true)
&& tmpPossibleNumber.startsWith("+"))
{
return true;
}
}
}
// Else the string is not a phone number.
return false;
}
/**
* Changes all alphabetical characters into numbers, following phone dial
* pad disposition.
*
* @param phoneNumber The phone number string with some alphabetical
* characters.
*
* @return The phone number with all alphabetical caracters replaced with
* the corresponding dial pad number.
*/
private static String convertAlphaCharactersInNumber(String phoneNumber)
{
phoneNumber
= charactersFordialPadNumber2.matcher(phoneNumber).replaceAll("2");
phoneNumber
= charactersFordialPadNumber3.matcher(phoneNumber).replaceAll("3");
phoneNumber
= charactersFordialPadNumber4.matcher(phoneNumber).replaceAll("4");
phoneNumber
= charactersFordialPadNumber5.matcher(phoneNumber).replaceAll("5");
phoneNumber
= charactersFordialPadNumber6.matcher(phoneNumber).replaceAll("6");
phoneNumber
= charactersFordialPadNumber7.matcher(phoneNumber).replaceAll("7");
phoneNumber
= charactersFordialPadNumber8.matcher(phoneNumber).replaceAll("8");
return charactersFordialPadNumber9.matcher(phoneNumber).replaceAll("9");
}
}

@ -0,0 +1,44 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.phonenumbers;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import org.osgi.framework.*;
/**
* Activates PhoneNumberI18nService implementation.
*
* @author Damian Minkov
*/
public class PhoneNumberServiceActivator
implements BundleActivator
{
/**
* Our logging.
*/
private static Logger logger
= Logger.getLogger(PhoneNumberServiceActivator.class);
@Override
public void start(BundleContext bundleContext)
throws Exception
{
bundleContext.registerService(
PhoneNumberI18nService.class.getName(),
new PhoneNumberI18nServiceImpl(),
null);
if (logger.isInfoEnabled())
logger.info("Packet Logging Service ...[REGISTERED]");
}
@Override
public void stop(BundleContext bundleContext)
throws Exception
{}
}

@ -0,0 +1,12 @@
Bundle-Activator: net.java.sip.communicator.impl.phonenumbers.PhoneNumberServiceActivator
Bundle-Name: PhoneNumbers service
Bundle-Description: A bundle that provides arsing, formatting and validating of international phone numbers.
Bundle-Vendor: jitsi.org
Bundle-Version: 0.0.1
Bundle-SymbolicName: net.java.sip.communicator.phonenumbers
Export-Package: com.google.i18n.phonenumbers
Import-Package: org.osgi.framework,
org.jitsi.service.configuration,
net.java.sip.communicator.service.protocol,
net.java.sip.communicator.util

@ -112,6 +112,11 @@ public class JabberActivator
*/
private static VersionService versionService = null;
/**
* The registered PhoneNumberI18nService.
*/
private static PhoneNumberI18nService phoneNumberI18nService;
/**
* Called when this bundle is started so the Framework can perform the
* bundle-specific activities necessary to start this bundle.
@ -421,4 +426,20 @@ public static VersionService getVersionService()
}
return versionService;
}
/**
* Returns the PhoneNumberI18nService.
* @return returns the PhoneNumberI18nService.
*/
public static PhoneNumberI18nService getPhoneNumberI18nService()
{
if(phoneNumberI18nService == null)
{
phoneNumberI18nService = ServiceUtils.getService(
bundleContext,
PhoneNumberI18nService.class);
}
return phoneNumberI18nService;
}
}

@ -61,7 +61,8 @@ public boolean doesDetailBelong(Contact contact, String detailAddress)
while (phonesIter.hasNext())
{
String phone = phonesIter.next();
String normalizedPhone = PhoneNumberI18nService.normalize(phone);
String normalizedPhone = JabberActivator.getPhoneNumberI18nService()
.normalize(phone);
if (phone.equals(detailAddress)
|| normalizedPhone.equals(detailAddress)

@ -106,6 +106,11 @@ public class AddrBookActivator
*/
private static List<ProtocolProviderService> providers
= new ArrayList<ProtocolProviderService>();
/**
* The registered PhoneNumberI18nService.
*/
private static PhoneNumberI18nService phoneNumberI18nService;
/**
* The registration change listener.
@ -524,4 +529,20 @@ public static List<ProtocolProviderService> getProtocolProviders()
return result;
}
/**
* Returns the PhoneNumberI18nService.
* @return returns the PhoneNumberI18nService.
*/
public static PhoneNumberI18nService getPhoneNumberI18nService()
{
if(phoneNumberI18nService == null)
{
phoneNumberI18nService = ServiceUtils.getService(
bundleContext,
PhoneNumberI18nService.class);
}
return phoneNumberI18nService;
}
}

@ -589,7 +589,8 @@ private List<ContactDetail> getContactDetails(Object[] values, String id)
{
if (kABPhoneProperty == property)
stringValue
= PhoneNumberI18nService.normalize(stringValue);
= AddrBookActivator.getPhoneNumberI18nService()
.normalize(stringValue);
contactDetails.add(
setCapabilities(
@ -645,8 +646,9 @@ private void parseMultiDetails(
{
if (kABPhoneProperty == property)
{
stringSubValue = PhoneNumberI18nService
.normalize(stringSubValue);
stringSubValue
= AddrBookActivator.getPhoneNumberI18nService()
.normalize(stringSubValue);
}
Object l = multiValue[multiValueIndex + 1];

@ -999,7 +999,8 @@ public static List<ContactDetail> getContactDetails(Object[] values)
{
if(isPhoneNumber(property))
stringValue
= PhoneNumberI18nService.normalize(stringValue);
= AddrBookActivator.getPhoneNumberI18nService()
.normalize(stringValue);
MsOutlookAddrBookContactDetail contactDetail
= new MsOutlookAddrBookContactDetail(

@ -51,6 +51,11 @@ public class PNContactSourceActivator
*/
private static ResourceManagementService resources = null;
/**
* The registered PhoneNumberI18nService.
*/
private static PhoneNumberI18nService phoneNumberI18nService;
/**
* Starts this bundle.
*
@ -214,4 +219,20 @@ private static void handleProviderRemoved(
if (phoneProviders.contains(protocolProvider))
phoneProviders.remove(protocolProvider);
}
/**
* Returns the PhoneNumberI18nService.
* @return returns the PhoneNumberI18nService.
*/
public static PhoneNumberI18nService getPhoneNumberI18nService()
{
if(phoneNumberI18nService == null)
{
phoneNumberI18nService = ServiceUtils.getService(
bundleContext,
PhoneNumberI18nService.class);
}
return phoneNumberI18nService;
}
}

@ -44,6 +44,11 @@ public class PhoneNumberContactQuery
= Collections.synchronizedList(
new LinkedList<OperationSetPersistentPresence>());
/**
* Is the query searching for phone number.
*/
private final boolean isQueryPhoneNumber;
/**
* Creates an instance of <tt>PhoneNumberContactQuery</tt> by specifying
* the parent contact source, the query string to match and the maximum
@ -63,6 +68,10 @@ public PhoneNumberContactQuery( PhoneNumberContactSource contactSource,
this.queryString = queryString;
this.contactCount = contactCount;
this.isQueryPhoneNumber
= PNContactSourceActivator.getPhoneNumberI18nService()
.isPhoneNumber(queryString);
}
/**
@ -204,7 +213,13 @@ else if(d instanceof VideoDetail)
if(StringUtils.isNullOrEmpty(queryString)
|| query.matcher(numberString).find()
|| query.matcher(contactName).find()
|| query.matcher(contactAddress).find())
|| query.matcher(contactAddress).find()
|| (isQueryPhoneNumber
&& PNContactSourceActivator
.getPhoneNumberI18nService()
.phoneNumbersMatch(
queryString, numberString))
)
{
ArrayList<ContactDetail> contactDetails
= new ArrayList<ContactDetail>();

@ -10,6 +10,7 @@
import net.java.sip.communicator.service.contactsource.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import org.jitsi.service.configuration.*;
@ -31,6 +32,11 @@ public class ThunderbirdActivator
private static Map<ThunderbirdContactSourceService, ServiceRegistration>
registrations;
/**
* The registered PhoneNumberI18nService.
*/
private static PhoneNumberI18nService phoneNumberI18nService;
/**
* Gets the configuration service.
* @return the configuration service.
@ -148,4 +154,20 @@ public void stop(BundleContext bundleContext) throws Exception
registrations = null;
}
/**
* Returns the PhoneNumberI18nService.
* @return returns the PhoneNumberI18nService.
*/
public static PhoneNumberI18nService getPhoneNumberI18nService()
{
if(phoneNumberI18nService == null)
{
phoneNumberI18nService = ServiceUtils.getService(
bundleContext,
PhoneNumberI18nService.class);
}
return phoneNumberI18nService;
}
}

@ -234,7 +234,8 @@ private void addPhoneDetail(List<ContactDetail> details, Row r,
return;
}
phone = PhoneNumberI18nService.normalize(phone);
phone
= ThunderbirdActivator.getPhoneNumberI18nService().normalize(phone);
ContactDetail detail =
new ContactDetail(phone, ContactDetail.Category.Phone,
new ContactDetail.SubCategory[]

@ -153,7 +153,7 @@ protected boolean addQueryResult(SourceContact sourceContact)
*/
protected String getPhoneNumberQuery()
{
if ((phoneNumberQuery != null) && !queryIsConvertedToPhoneNumber)
if ((phoneNumberQuery == null) && !queryIsConvertedToPhoneNumber)
{
try
{
@ -170,6 +170,16 @@ protected String getPhoneNumberQuery()
phoneNumberQuery
= pattern.substring(1, patternLength - 1);
}
else if ((patternLength > 4)
&& (pattern.charAt(0) == '\\')
&& (pattern.charAt(1) == 'Q')
&& (pattern.charAt(patternLength - 2) == '\\')
&& (pattern.charAt(patternLength - 1) == 'E'))
{
phoneNumberQuery
= pattern.substring(2, patternLength - 2);
}
}
}
finally
@ -304,8 +314,8 @@ protected boolean phoneNumberMatches(String phoneNumber)
boolean phoneNumberMatches = false;
if (query
.matcher(PhoneNumberI18nService.normalize(phoneNumber))
.find())
.matcher(ContactSourceActivator.getPhoneNumberI18nService()
.normalize(phoneNumber)).find())
{
phoneNumberMatches = true;
}
@ -330,7 +340,8 @@ protected boolean phoneNumberMatches(String phoneNumber)
try
{
phoneNumberMatches
= PhoneNumberI18nService.phoneNumbersMatch(
= ContactSourceActivator.getPhoneNumberI18nService()
.phoneNumbersMatch(
phoneNumberQuery,
phoneNumber);
}

@ -0,0 +1,57 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.contactsource;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import org.osgi.framework.*;
/**
* @author Damian Minkov
*/
public class ContactSourceActivator
implements BundleActivator
{
/**
* OSGi bundle context.
*/
public static BundleContext bundleContext;
/**
* The registered PhoneNumberI18nService.
*/
private static PhoneNumberI18nService phoneNumberI18nService;
@Override
public void start(BundleContext bundleContext)
throws Exception
{
this.bundleContext = bundleContext;
}
@Override
public void stop(BundleContext bundleContext)
throws Exception
{}
/**
* Returns the PhoneNumberI18nService.
* @return returns the PhoneNumberI18nService.
*/
public static PhoneNumberI18nService getPhoneNumberI18nService()
{
if(phoneNumberI18nService == null)
{
phoneNumberI18nService = ServiceUtils.getService(
bundleContext,
PhoneNumberI18nService.class);
}
return phoneNumberI18nService;
}
}

@ -1,4 +1,5 @@
Bundle-Name: Contact Source Service Interfaces
Bundle-Activator: net.java.sip.communicator.service.contactsource.ContactSourceActivator
Bundle-Name: Contact Source Service Interfaces
Bundle-Description: ContactSource Service.
Bundle-Vendor: jitsi.org
Bundle-Version: 0.0.1

@ -6,86 +6,16 @@
*/
package net.java.sip.communicator.service.protocol;
import java.util.regex.*;
import org.jitsi.service.configuration.*;
/**
* Implements <tt>PhoneNumberI18nService</tt> which aids the parsing, formatting
* and validating of international phone numbers.
*
* @author Lyubomir Marinov
* @author Vincent Lucas
* @author Damian Minkov
*/
public abstract class PhoneNumberI18nService
public interface PhoneNumberI18nService
{
/**
* The configuration service.
*/
private static ConfigurationService configService
= ProtocolProviderActivator.getConfigurationService();
/**
* Characters which have to be removed from a phone number in order to
* normalized it.
*/
private static final Pattern removedCharactersToNormalizedPhoneNumber
= Pattern.compile("[-\\(\\)\\.\\\\\\/ ]");
/**
* Characters which have to be removed from a number (which is not a phone
* number, such as a sip id, a jabber id, etc.) in order to normalized it.
*/
private static final Pattern removedCharactersToNormalizedIdentifier
= Pattern.compile("[\\(\\) ]");
/**
* The list of characters corresponding to the number 2 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber2
= Pattern.compile("[abc]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 3 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber3
= Pattern.compile("[def]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 4 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber4
= Pattern.compile("[ghi]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 5 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber5
= Pattern.compile("[jkl]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 6 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber6
= Pattern.compile("[mno]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 7 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber7
= Pattern.compile("[pqrs]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 8 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber8
= Pattern.compile("[tuv]", Pattern.CASE_INSENSITIVE);
/**
* The list of characters corresponding to the number 9 in a phone dial pad.
*/
private static final Pattern charactersFordialPadNumber9
= Pattern.compile("[wxyz]", Pattern.CASE_INSENSITIVE);
/**
* Normalizes a <tt>String</tt> which may be a phone number or a identifier
* by removing useless characters and, if necessary, replacing the alpahe
@ -97,56 +27,7 @@ public abstract class PhoneNumberI18nService
* @return a <tt>String</tt> which is a normalized form of the specified
* <tt>possibleNumber</tt>.
*/
public static String normalize(String possibleNumber)
{
String normalizedNumber;
if(isPhoneNumber(possibleNumber))
{
normalizedNumber = normalizePhoneNumber(possibleNumber);
}
else
{
normalizedNumber = normalizeIdentifier(possibleNumber);
}
return normalizedNumber;
}
/**
* Normalizes a <tt>String</tt> phone number by converting alpha characters
* to their respective digits on a keypad and then stripping non-digit
* characters.
*
* @param phoneNumber a <tt>String</tt> which represents a phone number to
* normalize
*
* @return a <tt>String</tt> which is a normalized form of the specified
* <tt>phoneNumber</tt>
*
* @see PhoneNumberI18nService#normalize(String)
*/
private static String normalizePhoneNumber(String phoneNumber)
{
phoneNumber = convertAlphaCharactersInNumber(phoneNumber);
return removedCharactersToNormalizedPhoneNumber
.matcher(phoneNumber).replaceAll("");
}
/**
* Removes useless characters from a identifier (which is not a phone
* number) in order to normalized it.
*
* @param id The identifier string with some useless characters like: " ",
* "(", ")".
*
* @return The normalized identifier.
*/
private static String normalizeIdentifier(String id)
{
return removedCharactersToNormalizedIdentifier
.matcher(id).replaceAll("");
}
public String normalize(String possibleNumber);
/**
* Determines whether two <tt>String</tt> phone numbers match.
@ -158,15 +39,7 @@ private static String normalizeIdentifier(String id)
* @return <tt>true</tt> if the specified <tt>String</tt>s match as phone
* numbers; otherwise, <tt>false</tt>
*/
public static boolean phoneNumbersMatch(
String aPhoneNumber,
String bPhoneNumber)
{
String aPhoneNumberNormalized = normalize(aPhoneNumber);
String bPhoneNumberNormalized = normalize(bPhoneNumber);
return aPhoneNumberNormalized.equals(bPhoneNumberNormalized);
}
public boolean phoneNumbersMatch(String aPhoneNumber, String bPhoneNumber);
/**
* Indicates if the given string is possibly a phone number.
@ -175,64 +48,5 @@ public static boolean phoneNumbersMatch(
* @return <tt>true</tt> if the possibleNumber is a phone number,
* <tt>false</tt> - otherwise
*/
public static boolean isPhoneNumber(String possibleNumber)
{
// If the string does not contains an "@", this may be a phone number.
if(possibleNumber.indexOf('@') == -1)
{
// If the string does not contain any alphabetical characters, then
// this is a phone number.
if(!possibleNumber.matches(".*[a-zA-Z].*"))
{
return true;
}
else
{
// Removes the " ", "(" and ")" in order to search the "+"
// character at the beginning at the string.
String tmpPossibleNumber
= possibleNumber.replaceAll(" \\(\\)", "");
// If the property is enabled and the string starts with a "+",
// then we consider that this is a phone number.
if(configService.getBoolean(
"impl.gui.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS",
true)
&& tmpPossibleNumber.startsWith("+"))
{
return true;
}
}
}
// Else the string is not a phone number.
return false;
}
/**
* Changes all alphabetical characters into numbers, following phone dial
* pad disposition.
*
* @param phoneNumber The phone number string with some alphabetical
* characters.
*
* @return The phone number with all alphabetical caracters replaced with
* the corresponding dial pad number.
*/
private static String convertAlphaCharactersInNumber(String phoneNumber)
{
phoneNumber
= charactersFordialPadNumber2.matcher(phoneNumber).replaceAll("2");
phoneNumber
= charactersFordialPadNumber3.matcher(phoneNumber).replaceAll("3");
phoneNumber
= charactersFordialPadNumber4.matcher(phoneNumber).replaceAll("4");
phoneNumber
= charactersFordialPadNumber5.matcher(phoneNumber).replaceAll("5");
phoneNumber
= charactersFordialPadNumber6.matcher(phoneNumber).replaceAll("6");
phoneNumber
= charactersFordialPadNumber7.matcher(phoneNumber).replaceAll("7");
phoneNumber
= charactersFordialPadNumber8.matcher(phoneNumber).replaceAll("8");
return charactersFordialPadNumber9.matcher(phoneNumber).replaceAll("9");
}
public boolean isPhoneNumber(String possibleNumber);
}

Loading…
Cancel
Save