/* * 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.googlecontacts; import java.util.*; import java.util.regex.*; import net.java.sip.communicator.service.contactsource.*; import net.java.sip.communicator.service.googlecontacts.*; import net.java.sip.communicator.service.protocol.*; /** * Implements ContactQuery for Google Contacts. * * @author Sebastien Vincent */ public class GoogleContactsQuery extends AsyncContactQuery { /** * Maximum results for Google Contacts query. */ public static final int GOOGLECONTACTS_MAX_RESULTS = 20; /** * Maximum number of results for this instance. */ private final int count; /** * The Google query. */ private GoogleQuery gQuery = null; /** * Initializes a new GoogleContactsQuery instance which is to * perform a specific query on behalf of a specific * contactSource. * * @param contactSource the ContactSourceService which is to * perform the new ContactQuery instance * @param query the Pattern for which contactSource is * being queried * @param count maximum number of results */ protected GoogleContactsQuery(GoogleContactsSourceService contactSource, Pattern query, int count) { super(contactSource, query); this.count = count; } /** * Create a SourceContact from a GoogleContactsEntry. * * @param entry GoogleContactsEntry */ private void onGoogleContactsEntry(GoogleContactsEntry entry) { String displayName = entry.getFullName(); if(displayName == null || displayName.length() == 0) { if((entry.getGivenName() == null || entry.getGivenName().length() == 0) && (entry.getFamilyName() == null || entry.getFamilyName().length() == 0)) { return; } displayName = entry.getGivenName() + " " + entry.getFamilyName(); } List contactDetails = getContactDetails(entry); if (!contactDetails.isEmpty()) { GenericSourceContact sourceContact = new GenericSourceContact( getContactSource(), displayName, contactDetails); try { byte img[] = GoogleContactsServiceImpl.downloadPhoto( ((GoogleContactsEntryImpl)entry).getPhotoLink(), getContactSource().getConnection(). getGoogleService()); sourceContact.setImage(img); } catch (OutOfMemoryError oome) { // Ignore it, the image is not vital. } addQueryResult(sourceContact); } } /** * Performs this AsyncContactQuery in a background Thread. * * @see AsyncContactQuery#run() */ @Override protected void run() { GoogleContactsServiceImpl service = GoogleContactsActivator.getGoogleContactsService(); gQuery = new GoogleQuery(query); GoogleContactsConnection cnx = getContactSource().getConnection(); if(cnx == null) { return; } service.searchContact( cnx, gQuery, count, new GoogleEntryCallback() { public void callback(GoogleContactsEntry entry) { onGoogleContactsEntry(entry); } }); } @Override public synchronized void start() { boolean hasStarted = false; try { super.start(); hasStarted = true; } finally { if (!hasStarted) { getContactSource().removeQuery(this); } } } /** * Gets the contactDetails to be set on a SourceContact. * * @param entry GoogleContactsEntry * @return the contactDetails to be set on a SourceContact */ private List getContactDetails(GoogleContactsEntry entry) { List ret = new LinkedList(); List homeMails = entry.getHomeMails(); List workMails = entry.getWorkMails(); List mobilePhones = entry.getMobilePhones(); List homePhones = entry.getHomePhones(); List workPhones = entry.getWorkPhones(); Map ims = entry.getIMAddresses(); ContactDetail detail = null; for(String mail : homeMails) { List> supportedOpSets = new ArrayList>(1); // can be added as contacts supportedOpSets.add(OperationSetPersistentPresence.class); detail = new ContactDetail(mail, ContactDetail.Category.Email, new ContactDetail.SubCategory[]{ ContactDetail.SubCategory.Home}); detail.setSupportedOpSets(supportedOpSets); ret.add(detail); } for(String mail : workMails) { List> supportedOpSets = new ArrayList>(1); // can be added as contacts supportedOpSets.add(OperationSetPersistentPresence.class); detail = new ContactDetail(mail, ContactDetail.Category.Email, new ContactDetail.SubCategory[]{ ContactDetail.SubCategory.Work}); detail.setSupportedOpSets(supportedOpSets); ret.add(detail); } for(String homePhone : homePhones) { List> supportedOpSets = new ArrayList>(2); supportedOpSets.add(OperationSetBasicTelephony.class); // can be added as contacts supportedOpSets.add(OperationSetPersistentPresence.class); homePhone = GoogleContactsActivator.getPhoneNumberI18nService() .normalize(homePhone); detail = new ContactDetail(homePhone, ContactDetail.Category.Phone, new ContactDetail.SubCategory[]{ ContactDetail.SubCategory.Home}); detail.setSupportedOpSets(supportedOpSets); ret.add(detail); } for(String workPhone : workPhones) { List> supportedOpSets = new ArrayList>(2); supportedOpSets.add(OperationSetBasicTelephony.class); // can be added as contacts supportedOpSets.add(OperationSetPersistentPresence.class); workPhone = GoogleContactsActivator.getPhoneNumberI18nService() .normalize(workPhone); detail = new ContactDetail(workPhone, ContactDetail.Category.Phone, new ContactDetail.SubCategory[]{ ContactDetail.SubCategory.Work}); detail.setSupportedOpSets(supportedOpSets); ret.add(detail); } for(String mobilePhone : mobilePhones) { List> supportedOpSets = new ArrayList>(2); supportedOpSets.add(OperationSetBasicTelephony.class); // can be added as contacts supportedOpSets.add(OperationSetPersistentPresence.class); mobilePhone = GoogleContactsActivator.getPhoneNumberI18nService() .normalize(mobilePhone); detail = new ContactDetail(mobilePhone, ContactDetail.Category.Phone, new ContactDetail.SubCategory[]{ ContactDetail.SubCategory.Mobile}); detail.setSupportedOpSets(supportedOpSets); ret.add(detail); } for(Map.Entry im : ims.entrySet()) { if(im.getValue() != GoogleContactsEntry.IMProtocol.OTHER) { ContactDetail.SubCategory imSubCat; switch(im.getValue()) { case AIM: imSubCat = ContactDetail.SubCategory.AIM; break; case ICQ: imSubCat = ContactDetail.SubCategory.ICQ; break; case YAHOO: imSubCat = ContactDetail.SubCategory.Yahoo; break; case JABBER: imSubCat = ContactDetail.SubCategory.Jabber; break; case MSN: imSubCat = ContactDetail.SubCategory.MSN; break; case GOOGLETALK: imSubCat = ContactDetail.SubCategory.GoogleTalk; break; default: imSubCat = null; break; } detail = new ContactDetail( im.getKey(), ContactDetail.Category.InstantMessaging, new ContactDetail.SubCategory[] { imSubCat }); setIMCapabilities(detail, im.getValue()); // can be added as contacts detail.getSupportedOperationSets().add( OperationSetPersistentPresence.class); ret.add(detail); } } return ret; } /** * Sets the IM capabilities of a specific ContactDetail (e.g. * supportedOpSets). * * @param contactDetail the ContactDetail to set the capabilities * of * @param protocol protocol * @return contactDetail */ private ContactDetail setIMCapabilities( ContactDetail contactDetail, GoogleContactsEntry.IMProtocol protocol) { List> supportedOpSets = new LinkedList>(); Map, String> preferredProtocols = new HashMap, String>(); switch (protocol) { case GOOGLETALK: supportedOpSets.add(OperationSetBasicInstantMessaging.class); preferredProtocols.put( OperationSetBasicInstantMessaging.class, ProtocolNames.AIM); break; case ICQ: supportedOpSets.add(OperationSetBasicInstantMessaging.class); preferredProtocols.put( OperationSetBasicInstantMessaging.class, ProtocolNames.ICQ); break; case JABBER: supportedOpSets.add(OperationSetBasicInstantMessaging.class); preferredProtocols.put( OperationSetBasicInstantMessaging.class, ProtocolNames.JABBER); supportedOpSets.add(OperationSetBasicTelephony.class); preferredProtocols.put( OperationSetBasicTelephony.class, ProtocolNames.JABBER); break; case MSN: supportedOpSets.add(OperationSetBasicInstantMessaging.class); preferredProtocols.put( OperationSetBasicInstantMessaging.class, ProtocolNames.MSN); break; case YAHOO: supportedOpSets.add(OperationSetBasicInstantMessaging.class); preferredProtocols.put( OperationSetBasicInstantMessaging.class, ProtocolNames.YAHOO); break; default: break; } contactDetail.setSupportedOpSets(supportedOpSets); if (!preferredProtocols.isEmpty()) contactDetail.setPreferredProtocols(preferredProtocols); return contactDetail; } /** * Notifies this GoogleContactsQuery that it has stopped performing * in the associated background Thread. * * @param completed true if this ContactQuery has * successfully completed, false if an error has been encountered * during its execution * @see AsyncContactQuery#stopped(boolean) */ @Override protected void stopped(boolean completed) { try { super.stopped(completed); } finally { getContactSource().stopped(this); } } /** * Cancels this ContactQuery. * * @see ContactQuery#cancel() */ @Override public void cancel() { if(gQuery != null) { gQuery.cancel(); } super.cancel(); } }