diff options
author | Yana Stamcheva <yana@jitsi.org> | 2010-05-03 12:27:34 +0000 |
---|---|---|
committer | Yana Stamcheva <yana@jitsi.org> | 2010-05-03 12:27:34 +0000 |
commit | afcafe3061f9abaa52633b727fe34769d4cc0e04 (patch) | |
tree | a36c09734602576e9a8388794142420f06ce649c /src/net/java/sip/communicator/impl/callhistory | |
parent | c454284e43c6db33c1d13f4a1c9d9e06d7726d9f (diff) | |
download | jitsi-afcafe3061f9abaa52633b727fe34769d4cc0e04.zip jitsi-afcafe3061f9abaa52633b727fe34769d4cc0e04.tar.gz jitsi-afcafe3061f9abaa52633b727fe34769d4cc0e04.tar.bz2 |
- Introduces new contact list data model that allows adding of external contact sources and hence the search in such sources.
- As part of the support for external contact sources, implements a call history external source and its user interface.
- Addresses issue #706 Indicate missed calls
Diffstat (limited to 'src/net/java/sip/communicator/impl/callhistory')
6 files changed, 712 insertions, 102 deletions
diff --git a/src/net/java/sip/communicator/impl/callhistory/CallHistoryActivator.java b/src/net/java/sip/communicator/impl/callhistory/CallHistoryActivator.java index 37118c7..049ca9c 100755 --- a/src/net/java/sip/communicator/impl/callhistory/CallHistoryActivator.java +++ b/src/net/java/sip/communicator/impl/callhistory/CallHistoryActivator.java @@ -6,15 +6,22 @@ */ package net.java.sip.communicator.impl.callhistory; +import java.util.*; + import org.osgi.framework.*; + import net.java.sip.communicator.service.history.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.resources.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.service.callhistory.*; +import net.java.sip.communicator.service.contactsource.*; /** - * Activates the CallHistoryService + * Activates the <tt>CallHistoryService</tt>. * * @author Damian Minkov + * @author Yana Stamcheva */ public class CallHistoryActivator implements BundleActivator @@ -22,18 +29,39 @@ public class CallHistoryActivator private static Logger logger = Logger.getLogger(CallHistoryActivator.class); - private CallHistoryServiceImpl callHistoryService = null; + /** + * The bundle context. + */ + public static BundleContext bundleContext; + + /** + * The <tt>CallHistoryServiceImpl</tt> instantiated in the start method + * of this bundle. + */ + private static CallHistoryServiceImpl callHistoryService = null; + + /** + * The service responsible for resources. + */ + private static ResourceManagementService resourcesService; + + /** + * The map containing all registered + */ + private static final Map<Object, ProtocolProviderFactory> + providerFactoriesMap = new Hashtable<Object, ProtocolProviderFactory>(); /** * Initialize and start call history * - * @param bundleContext BundleContext + * @param bc the <tt>BundleContext</tt> * @throws Exception */ - public void start(BundleContext bundleContext) throws Exception + public void start(BundleContext bc) throws Exception { - try{ + bundleContext = bc; + try{ logger.logEntry(); ServiceReference refHistory = bundleContext.getServiceReference( @@ -53,6 +81,10 @@ public class CallHistoryActivator bundleContext.registerService( CallHistoryService.class.getName(), callHistoryService, null); + bundleContext.registerService( + ContactSourceService.class.getName(), + new CallHistoryContactSource(), null); + logger.info("Call History Service ...[REGISTERED]"); } finally @@ -62,9 +94,89 @@ public class CallHistoryActivator } + /** + * Stops this bundle. + * @param bundleContext the <tt>BundleContext</tt> + * @throws Exception if the stop operation goes wrong + */ public void stop(BundleContext bundleContext) throws Exception { if(callHistoryService != null) callHistoryService.stop(bundleContext); } + + /** + * Returns the instance of <tt>CallHistoryService</tt> created in this + * activator. + * @return the instance of <tt>CallHistoryService</tt> created in this + * activator + */ + public static CallHistoryService getCallHistoryService() + { + return callHistoryService; + } + + /** + * Returns the <tt>ResourceManagementService</tt>, through which we will + * access all resources. + * + * @return the <tt>ResourceManagementService</tt>, through which we will + * access all resources. + */ + public static ResourceManagementService getResources() + { + if (resourcesService == null) + { + ServiceReference serviceReference = bundleContext + .getServiceReference(ResourceManagementService.class.getName()); + + if(serviceReference == null) + return null; + + resourcesService = (ResourceManagementService) bundleContext + .getService(serviceReference); + } + return resourcesService; + } + + /** + * Returns all <tt>ProtocolProviderFactory</tt>s obtained from the bundle + * context. + * + * @return all <tt>ProtocolProviderFactory</tt>s obtained from the bundle + * context + */ + public static Map<Object, ProtocolProviderFactory> + getProtocolProviderFactories() + { + ServiceReference[] serRefs = null; + try + { + // get all registered provider factories + serRefs = + bundleContext.getServiceReferences( + ProtocolProviderFactory.class.getName(), null); + + } + catch (InvalidSyntaxException e) + { + logger.error("LoginManager : " + e); + } + + if (serRefs != null) + { + for (int i = 0; i < serRefs.length; i++) + { + + ProtocolProviderFactory providerFactory + = (ProtocolProviderFactory) bundleContext + .getService(serRefs[i]); + + providerFactoriesMap.put(serRefs[i] + .getProperty(ProtocolProviderFactory.PROTOCOL), + providerFactory); + } + } + return providerFactoriesMap; + } } diff --git a/src/net/java/sip/communicator/impl/callhistory/CallHistoryContactSource.java b/src/net/java/sip/communicator/impl/callhistory/CallHistoryContactSource.java new file mode 100644 index 0000000..74d4249 --- /dev/null +++ b/src/net/java/sip/communicator/impl/callhistory/CallHistoryContactSource.java @@ -0,0 +1,153 @@ +/* + * SIP Communicator, 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.callhistory; + +import java.util.*; + +import net.java.sip.communicator.service.callhistory.*; +import net.java.sip.communicator.service.contactsource.*; + +/** + * The <tt>CallHistoryContactSource</tt> is the contact source for the call + * history. + * + * @author Yana Stamcheva + */ +public class CallHistoryContactSource implements ContactSourceService +{ + /** + * The display name of this contact source. + */ + private static final String CALL_HISTORY_NAME = "Call history"; + + /** + * Returns the display name of this contact source. + * @return the display name of this contact source + */ + public String getDisplayName() + { + return CALL_HISTORY_NAME; + } + + /** + * Queries this contact source for the given <tt>searchString</tt>. + * @param queryString the string to search for + * @return the created query + */ + public ContactQuery queryContactSource(String queryString) + { + if (queryString != null && queryString.length() > 0) + return new CallHistoryQuery( + CallHistoryActivator.getCallHistoryService() + .findByPeer(queryString)); + else + return new CallHistoryQuery( + CallHistoryActivator.getCallHistoryService() + .findLast(50)); + } + + /** + * The <tt>CallHistoryQuery</tt> contains information about a current query + * to the contact source. + */ + private class CallHistoryQuery implements ContactQuery + { + /** + * A list of all registered query listeners. + */ + private final List<ContactQueryListener> queryListeners + = new LinkedList<ContactQueryListener>(); + + /** + * A list of all source contact results. + */ + private final List<SourceContact> sourceContacts + = new LinkedList<SourceContact>(); + + /** + * Creates a <tt>CallHistoryQuery</tt>. + * @param callRecords a collection of the result call records + */ + public CallHistoryQuery(Collection<CallRecord> callRecords) + { + Iterator<CallRecord> recordsIter = callRecords.iterator(); + + while (recordsIter.hasNext()) + { + sourceContacts.add( + new CallHistorySourceContact( + CallHistoryContactSource.this, + recordsIter.next())); + } + } + + /** + * Adds the given <tt>ContactQueryListener</tt> to the list of query + * listeners. + * @param l the <tt>ContactQueryListener</tt> to add + */ + public void addContactQueryListener(ContactQueryListener l) + { + synchronized (queryListeners) + { + queryListeners.add(l); + } + } + + /** + * This query could not be canceled. + */ + public void cancel() + { + + } + + /** + * Removes the given <tt>ContactQueryListener</tt> from the list of + * query listeners. + * @param l the <tt>ContactQueryListener</tt> to remove + */ + public void removeContactQueryListener(ContactQueryListener l) + { + synchronized (queryListeners) + { + queryListeners.remove(l); + } + } + + /** + * Returns a list containing the results of this query. + * @return a list containing the results of this query + */ + public List<SourceContact> getQueryResults() + { + return sourceContacts; + } + + /** + * Returns the <tt>ContactSourceService</tt>, where this query was first + * initiated. + * @return the <tt>ContactSourceService</tt>, where this query was first + * initiated + */ + public ContactSourceService getContactSource() + { + return CallHistoryContactSource.this; + } + } + + /** + * Returns the identifier of this contact source. Some of the common + * identifiers are defined here (For example the CALL_HISTORY identifier + * should be returned by all call history implementations of this interface) + * @return the identifier of this contact source + */ + public String getIdentifier() + { + return CALL_HISTORY; + } +} diff --git a/src/net/java/sip/communicator/impl/callhistory/CallHistoryServiceImpl.java b/src/net/java/sip/communicator/impl/callhistory/CallHistoryServiceImpl.java index 48fbbb6..93d83f4 100644 --- a/src/net/java/sip/communicator/impl/callhistory/CallHistoryServiceImpl.java +++ b/src/net/java/sip/communicator/impl/callhistory/CallHistoryServiceImpl.java @@ -42,8 +42,9 @@ public class CallHistoryServiceImpl Logger.getLogger(CallHistoryServiceImpl.class); private static String[] STRUCTURE_NAMES = - new String[] { "callStart", "callEnd", "dir", "callParticipantIDs", - "callParticipantStart", "callParticipantEnd","callParticipantStates" }; + new String[] { "accountUID", "callStart", "callEnd", "dir", + "callParticipantIDs", "callParticipantStart", + "callParticipantEnd", "callParticipantStates" }; private static HistoryRecordStructure recordStructure = new HistoryRecordStructure(STRUCTURE_NAMES); @@ -59,8 +60,10 @@ public class CallHistoryServiceImpl private Object syncRoot_HistoryService = new Object(); - private final Map<CallHistorySearchProgressListener, SearchProgressWrapper> progressListeners = - new Hashtable<CallHistorySearchProgressListener, SearchProgressWrapper>(); + private final Map<CallHistorySearchProgressListener, SearchProgressWrapper> + progressListeners + = new Hashtable<CallHistorySearchProgressListener, + SearchProgressWrapper>(); private final List<CallRecordImpl> currentCallRecords = new Vector<CallRecordImpl>(); @@ -68,22 +71,29 @@ public class CallHistoryServiceImpl private final CallChangeListener historyCallChangeListener = new HistoryCallChangeListener(); + private HistoryReader historyReader; + + /** + * Returns the underlying history service. + * @return the underlying history service + */ public HistoryService getHistoryService() { return historyService; } /** - * Returns all the calls made by all the contacts - * in the supplied metacontact after the given date + * Returns all the calls made by all the contacts in the supplied + * <tt>contact</tt> after the given date. * * @param contact MetaContact which contacts participate in * the returned calls * @param startDate Date the start date of the calls - * @return Collection of CallRecords with CallPeerRecord + * @return the <tt>CallHistoryQuery</tt>, corresponding to this find * @throws RuntimeException */ - public Collection<CallRecord> findByStartDate(MetaContact contact, Date startDate) + public Collection<CallRecord> findByStartDate( + MetaContact contact, Date startDate) throws RuntimeException { throw new UnsupportedOperationException("Not implemented yet!"); @@ -93,7 +103,7 @@ public class CallHistoryServiceImpl * Returns all the calls made after the given date * * @param startDate Date the start date of the calls - * @return Collection of CallRecords with CallPeerRecord + * @return the <tt>CallHistoryQuery</tt>, corresponding to this find * @throws RuntimeException */ public Collection<CallRecord> findByStartDate(Date startDate) @@ -104,16 +114,16 @@ public class CallHistoryServiceImpl { // the default ones History history = this.getHistory(null, null); - HistoryReader reader = history.getReader(); - addHistorySearchProgressListeners(reader, 1); + historyReader = history.getReader(); + addHistorySearchProgressListeners(historyReader, 1); QueryResultSet<HistoryRecord> rs - = reader.findByStartDate(startDate); + = historyReader.findByStartDate(startDate); while (rs.hasNext()) { HistoryRecord hr = rs.next(); result.add(convertHistoryRecordToCallRecord(hr)); } - removeHistorySearchProgressListeners(reader); + removeHistorySearchProgressListeners(historyReader); } catch (IOException ex) { @@ -133,7 +143,8 @@ public class CallHistoryServiceImpl * @return Collection of CallRecords with CallPeerRecord * @throws RuntimeException */ - public Collection<CallRecord> findByEndDate(MetaContact contact, Date endDate) + public Collection<CallRecord> findByEndDate(MetaContact contact, + Date endDate) throws RuntimeException { throw new UnsupportedOperationException("Not implemented yet!"); @@ -146,22 +157,25 @@ public class CallHistoryServiceImpl * @return Collection of CallRecords with CallPeerRecord * @throws RuntimeException */ - public Collection<CallRecord> findByEndDate(Date endDate) throws RuntimeException + public Collection<CallRecord> findByEndDate(Date endDate) + throws RuntimeException { - TreeSet<CallRecord> result = new TreeSet<CallRecord>(new CallRecordComparator()); + TreeSet<CallRecord> result + = new TreeSet<CallRecord>(new CallRecordComparator()); try { // the default ones History history = this.getHistory(null, null); - HistoryReader reader = history.getReader(); - addHistorySearchProgressListeners(reader, 1); - QueryResultSet<HistoryRecord> rs = reader.findByEndDate(endDate); + historyReader = history.getReader(); + addHistorySearchProgressListeners(historyReader, 1); + QueryResultSet<HistoryRecord> rs + = historyReader.findByEndDate(endDate); while (rs.hasNext()) { HistoryRecord hr = rs.next(); result.add(convertHistoryRecordToCallRecord(hr)); } - removeHistorySearchProgressListeners(reader); + removeHistorySearchProgressListeners(historyReader); } catch (IOException ex) { @@ -181,7 +195,8 @@ public class CallHistoryServiceImpl * @return Collection of CallRecords with CallPeerRecord * @throws RuntimeException */ - public Collection<CallRecord> findByPeriod(MetaContact contact, Date startDate, Date endDate) + public Collection<CallRecord> findByPeriod(MetaContact contact, + Date startDate, Date endDate) throws RuntimeException { throw new UnsupportedOperationException("Not implemented yet!"); @@ -195,24 +210,25 @@ public class CallHistoryServiceImpl * @return Collection of CallRecords with CallPeerRecord * @throws RuntimeException */ - public Collection<CallRecord> findByPeriod(Date startDate, Date endDate) throws - RuntimeException + public Collection<CallRecord> findByPeriod(Date startDate, Date endDate) + throws RuntimeException { - TreeSet<CallRecord> result = new TreeSet<CallRecord>(new CallRecordComparator()); + TreeSet<CallRecord> result + = new TreeSet<CallRecord>(new CallRecordComparator()); try { // the default ones History history = this.getHistory(null, null); - HistoryReader reader = history.getReader(); - addHistorySearchProgressListeners(reader, 1); + historyReader = history.getReader(); + addHistorySearchProgressListeners(historyReader, 1); QueryResultSet<HistoryRecord> rs - = reader.findByPeriod(startDate, endDate); + = historyReader.findByPeriod(startDate, endDate); while (rs.hasNext()) { HistoryRecord hr = rs.next(); result.add(convertHistoryRecordToCallRecord(hr)); } - removeHistorySearchProgressListeners(reader); + removeHistorySearchProgressListeners(historyReader); } catch (IOException ex) { @@ -247,13 +263,14 @@ public class CallHistoryServiceImpl */ public Collection<CallRecord> findLast(int count) throws RuntimeException { - TreeSet<CallRecord> result = new TreeSet<CallRecord>(new CallRecordComparator()); + TreeSet<CallRecord> result + = new TreeSet<CallRecord>(new CallRecordComparator()); try { // the default ones History history = this.getHistory(null, null); - QueryResultSet<HistoryRecord> rs - = history.getReader().findLast(count); + historyReader = history.getReader(); + QueryResultSet<HistoryRecord> rs = historyReader.findLast(count); while (rs.hasNext()) { HistoryRecord hr = rs.next(); @@ -277,21 +294,22 @@ public class CallHistoryServiceImpl public Collection<CallRecord> findByPeer(String address) throws RuntimeException { - TreeSet<CallRecord> result = new TreeSet<CallRecord>(new CallRecordComparator()); + TreeSet<CallRecord> result + = new TreeSet<CallRecord>(new CallRecordComparator()); try { // the default ones History history = this.getHistory(null, null); - HistoryReader reader = history.getReader(); - addHistorySearchProgressListeners(reader, 1); + historyReader = history.getReader(); + addHistorySearchProgressListeners(historyReader, 1); QueryResultSet<HistoryRecord> rs - = reader.findByKeyword(address, "callParticipantIDs"); + = historyReader.findByKeyword(address, "callParticipantIDs"); while (rs.hasNext()) { HistoryRecord hr = rs.next(); result.add(convertHistoryRecordToCallRecord(hr)); } - removeHistorySearchProgressListeners(reader); + removeHistorySearchProgressListeners(historyReader); } catch (IOException ex) { @@ -364,19 +382,21 @@ public class CallHistoryServiceImpl String propName = hr.getPropertyNames()[i]; String value = hr.getPropertyValues()[i]; - if(propName.equals(STRUCTURE_NAMES[0])) - result.setStartTime(new Date(Long.parseLong(value))); + if (propName.equals(STRUCTURE_NAMES[0])) + result.setProtocolProvider(getProtocolProvider(value)); else if(propName.equals(STRUCTURE_NAMES[1])) - result.setEndTime(new Date(Long.parseLong(value))); + result.setStartTime(new Date(Long.parseLong(value))); else if(propName.equals(STRUCTURE_NAMES[2])) - result.setDirection(value); + result.setEndTime(new Date(Long.parseLong(value))); else if(propName.equals(STRUCTURE_NAMES[3])) - callPeerIDs = getCSVs(value); + result.setDirection(value); else if(propName.equals(STRUCTURE_NAMES[4])) - callPeerStart = getCSVs(value); + callPeerIDs = getCSVs(value); else if(propName.equals(STRUCTURE_NAMES[5])) - callPeerEnd = getCSVs(value); + callPeerStart = getCSVs(value); else if(propName.equals(STRUCTURE_NAMES[6])) + callPeerEnd = getCSVs(value); + else if(propName.equals(STRUCTURE_NAMES[7])) callPeerStates = getStates(value); } @@ -557,10 +577,12 @@ public class CallHistoryServiceImpl * @param source Contact * @param destination Contact */ - private void writeCall(CallRecord callRecord, Contact source, - Contact destination) + private void writeCall( CallRecordImpl callRecord, + Contact source, + Contact destination) { - try { + try + { History history = this.getHistory(source, destination); HistoryWriter historyWriter = history.getWriter(); @@ -589,6 +611,8 @@ public class CallHistoryServiceImpl } historyWriter.addRecord(new String[] { + callRecord.getSourceCall().getProtocolProvider() + .getAccountID().getAccountUniqueID(), String.valueOf(callRecord.getStartTime().getTime()), String.valueOf(callRecord.getEndTime().getTime()), callRecord.getDirection(), @@ -596,8 +620,10 @@ public class CallHistoryServiceImpl callPeerStartTime.toString(), callPeerEndTime.toString(), callPeerStates.toString()}, - new Date()); // this date is when the history record is written - } catch (IOException e) + new Date()); // this date is when the history + // record is written + } + catch (IOException e) { logger.error("Could not add call to history", e); } @@ -646,9 +672,11 @@ public class CallHistoryServiceImpl */ public void serviceChanged(ServiceEvent serviceEvent) { - Object sService = bundleContext.getService(serviceEvent.getServiceReference()); + Object sService + = bundleContext.getService(serviceEvent.getServiceReference()); - logger.trace("Received a service event for: " + sService.getClass().getName()); + logger.trace("Received a service event for: " + + sService.getClass().getName()); // we don't care if the source service is not a protocol provider if (! (sService instanceof ProtocolProviderService)) @@ -667,13 +695,12 @@ public class CallHistoryServiceImpl { this.handleProviderRemoved( (ProtocolProviderService) sService); } - } /** * Used to attach the Call History Service to existing or - * just registered protocol provider. Checks if the provider has implementation - * of OperationSetBasicTelephony + * just registered protocol provider. Checks if the provider has + * implementation of OperationSetBasicTelephony * * @param provider ProtocolProviderService */ @@ -779,34 +806,6 @@ public class CallHistoryServiceImpl } /** - * Gets all the history readers for the contacts in the given MetaContact - * - * @param contact MetaContact - * @return Hashtable - */ - private Map<Contact, HistoryReader> getHistoryReaders(MetaContact contact) - { - Map<Contact, HistoryReader> readers = - new Hashtable<Contact, HistoryReader>(); - Iterator<Contact> iter = contact.getContacts(); - while (iter.hasNext()) - { - Contact item = iter.next(); - - try - { - History history = this.getHistory(null, item); - readers.put(item, history.getReader()); - } - catch (IOException e) - { - logger.error("Could not read history", e); - } - } - return readers; - } - - /** * CallListener implementation for incoming calls * @param event CallEvent */ @@ -830,17 +829,8 @@ public class CallHistoryServiceImpl */ public void callEnded(CallEvent event) { - CallRecordImpl callRecord = findCallRecord(event.getSourceCall()); - - // no such call - if (callRecord == null) - return; - - callRecord.setEndTime(new Date()); - - writeCall(callRecord, null, null); - - currentCallRecords.remove(callRecord); + // We store the call in the callStateChangeEvent where we + // have more information on the previous state of the call. } /** @@ -1027,9 +1017,11 @@ public class CallHistoryServiceImpl */ private int getProgressMapping(int historyProgress) { - currentProgress += (historyProgress - lastHistoryProgress)/contactCount; + currentProgress + += (historyProgress - lastHistoryProgress)/contactCount; - if(historyProgress == HistorySearchProgressListener.PROGRESS_MAXIMUM_VALUE) + if(historyProgress + == HistorySearchProgressListener.PROGRESS_MAXIMUM_VALUE) { currentContactCount++; lastHistoryProgress = 0; @@ -1074,18 +1066,93 @@ public class CallHistoryServiceImpl /** * Receive events for adding or removing peers from a call */ - private class HistoryCallChangeListener - extends CallChangeAdapter + private class HistoryCallChangeListener implements CallChangeListener { + /** + * Indicates that a new call peer has joined the source call. + * + * @param evt the <tt>CallPeerEvent</tt> containing the source call + * and call peer. + */ public void callPeerAdded(CallPeerEvent evt) { handlePeerAdded(evt.getSourceCallPeer()); } + /** + * Indicates that a call peer has left the source call. + * + * @param evt the <tt>CallPeerEvent</tt> containing the source call + * and call peer. + */ public void callPeerRemoved(CallPeerEvent evt) { handlePeerRemoved(evt.getSourceCallPeer(), evt.getSourceCall()); } + + /** + * A dummy implementation of this listener's callStateChanged() method. + * + * @param evt the <tt>CallChangeEvent</tt> instance containing the source + * calls and its old and new state. + */ + public void callStateChanged(CallChangeEvent evt) + { + CallRecordImpl callRecord = findCallRecord(evt.getSourceCall()); + + // no such call + if (callRecord == null) + return; + + if (evt.getNewValue().equals(CallState.CALL_ENDED) + && evt.getOldValue().equals(CallState.CALL_INITIALIZATION)) + { + callRecord.setEndTime(callRecord.getStartTime()); + } + else + callRecord.setEndTime(new Date()); + + writeCall(callRecord, null, null); + + currentCallRecords.remove(callRecord); + } + } + + /** + * Returns the <tt>ProtocolProviderService</tt> corresponding to the given + * account identifier. + * @param accountUID the identifier of the account. + * @return the <tt>ProtocolProviderService</tt> corresponding to the given + * account identifier + */ + private ProtocolProviderService getProtocolProvider(String accountUID) + { + for (ProtocolProviderFactory providerFactory + : CallHistoryActivator.getProtocolProviderFactories().values()) + { + ServiceReference serRef; + + for (AccountID accountID : providerFactory.getRegisteredAccounts()) + { + if (accountID.getAccountUniqueID().equals(accountUID)) + { + serRef = providerFactory.getProviderForAccount(accountID); + + return (ProtocolProviderService) CallHistoryActivator + .bundleContext.getService(serRef); + } + } + } + return null; + } + + /** + * Cancels the current find. If there's no find going on, then does nothing. + */ + public void cancelCurrentFind() + { + if (historyReader != null) + historyReader.cancelCurrentFind(); } } diff --git a/src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java b/src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java new file mode 100644 index 0000000..b9f7c8c --- /dev/null +++ b/src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java @@ -0,0 +1,266 @@ +/* + * SIP Communicator, 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.callhistory; + +import java.util.*; + +import net.java.sip.communicator.service.callhistory.*; +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +/** + * The <tt>CallHistorySourceContact</tt> is an implementation of the + * <tt>SourceContact</tt> interface based on a <tt>CallRecord</tt>. + * + * @author Yana Stamcheva + */ +public class CallHistorySourceContact implements SourceContact +{ + /** + * The parent <tt>CallHistoryContactSource</tt>, where this contact is + * contained. + */ + private final CallHistoryContactSource contactSource; + + /** + * The corresponding call record. + */ + private final CallRecord callRecord; + + /** + * The incoming call icon. + */ + private static final byte[] incomingIcon + = CallHistoryActivator.getResources() + .getImageInBytes("service.gui.icons.INCOMING_CALL"); + + /** + * The outgoing call icon. + */ + private static byte[] outgoingIcon + = CallHistoryActivator.getResources() + .getImageInBytes("service.gui.icons.OUTGOING_CALL"); + + /** + * The missed call icon. + */ + private static byte[] missedCallIcon + = CallHistoryActivator.getResources() + .getImageInBytes("service.gui.icons.MISSED_CALL"); + + /** + * A list of all contact details. + */ + private final List<ContactDetail> contactDetails + = new LinkedList<ContactDetail>(); + + /** + * The display name of this contact. + */ + private String displayName = ""; + + /** + * The display details of this contact. + */ + private final String displayDetails; + + /** + * Creates an instance of <tt>CallHistorySourceContact</tt> + * @param contactSource + * @param callRecord + */ + public CallHistorySourceContact(CallHistoryContactSource contactSource, + CallRecord callRecord) + { + this.contactSource = contactSource; + this.callRecord = callRecord; + + this.initPeerDetails(); + + this.displayDetails + = CallHistoryActivator.getResources() + .getI18NString("service.gui.AT") + ": " + + getDateString(callRecord.getStartTime().getTime()) + + " " + CallHistoryActivator.getResources() + .getI18NString("service.gui.DURATION") + ": " + + GuiUtils.formatTime( + GuiUtils.substractDates( + callRecord.getEndTime(), callRecord.getStartTime())); + } + + /** + * Initializes peer details. + */ + private void initPeerDetails() + { + Iterator<CallPeerRecord> recordsIter + = callRecord.getPeerRecords().iterator(); + + while (recordsIter.hasNext()) + { + String peerAddress = recordsIter.next().getPeerAddress(); + + if (displayName.length() > 0) + displayName += "," + peerAddress; + else + displayName += peerAddress; + + if (peerAddress != null) + { + ContactDetail contactDetail = new ContactDetail(peerAddress); + + Map<Class<? extends OperationSet>, ProtocolProviderService> + preferredProviders = null; + if (callRecord.getProtocolProvider() != null) + { + preferredProviders + = new Hashtable<Class<? extends OperationSet>, + ProtocolProviderService>(); + + preferredProviders.put( OperationSetBasicTelephony.class, + callRecord.getProtocolProvider()); + + contactDetail + .setPreferredProviders(preferredProviders); + } + + // Set supported operation sets. + LinkedList<Class<? extends OperationSet>> supportedOpSets + = new LinkedList<Class<? extends OperationSet>>(); + + supportedOpSets.add(OperationSetBasicTelephony.class); + contactDetail.setSupportedOpSets(supportedOpSets); + + contactDetails.add(contactDetail); + } + } + } + + /** + * Returns a list of available contact details. + * @return a list of available contact details + */ + public List<ContactDetail> getContactDetails() + { + return new LinkedList<ContactDetail>(contactDetails); + } + + /** + * Returns the parent <tt>ContactSourceService</tt> from which this contact + * came from. + * @return the parent <tt>ContactSourceService</tt> from which this contact + * came from + */ + public ContactSourceService getContactSource() + { + return contactSource; + } + + /** + * Returns the display details of this search contact. This could be any + * important information that should be shown to the user. + * + * @return the display details of the search contact + */ + public String getDisplayDetails() + { + return displayDetails; + } + + /** + * Returns the display name of this search contact. This is a user-friendly + * name that could be shown in the user interface. + * + * @return the display name of this search contact + */ + public String getDisplayName() + { + return displayName; + } + + /** + * An image (or avatar) corresponding to this search contact. If such is + * not available this method will return null. + * + * @return the byte array of the image or null if no image is available + */ + public byte[] getImage() + { + if (callRecord.getDirection().equals(CallRecord.IN)) + { + if (callRecord.getStartTime().equals(callRecord.getEndTime())) + return missedCallIcon; + else + return incomingIcon; + } + else if (callRecord.getDirection().equals(CallRecord.OUT)) + return outgoingIcon; + + return null; + } + + /** + * Returns a list of all <tt>ContactDetail</tt>s supporting the given + * <tt>OperationSet</tt> class. + * @param operationSet the <tt>OperationSet</tt> class we're looking for + * @return a list of all <tt>ContactDetail</tt>s supporting the given + * <tt>OperationSet</tt> class + */ + public List<ContactDetail> getContactDetails( + Class<? extends OperationSet> operationSet) + { + // We support only call details. + if (!operationSet.equals(OperationSetBasicTelephony.class)) + return null; + + return new LinkedList<ContactDetail>(contactDetails); + } + + /** + * Returns the preferred <tt>ContactDetail</tt> for a given + * <tt>OperationSet</tt> class. + * @param operationSet the <tt>OperationSet</tt> class, for which we would + * like to obtain a <tt>ContactDetail</tt> + * @return the preferred <tt>ContactDetail</tt> for a given + * <tt>OperationSet</tt> class + */ + public ContactDetail getPreferredContactDetail( + Class<? extends OperationSet> operationSet) + { + // We support only call details. + if (!operationSet.equals(OperationSetBasicTelephony.class)) + return null; + + return contactDetails.get(0); + } + + /** + * Returns the date string to show for the given date. + * + * @param date the date to format + * @return the date string to show for the given date + */ + public static String getDateString(long date) + { + String time = GuiUtils.formatTime(date); + + // If the current date we don't go in there and we'll return just the + // time. + if (GuiUtils.compareDatesOnly(date, System.currentTimeMillis()) < 0) + { + StringBuffer dateStrBuf = new StringBuffer(); + + GuiUtils.formatDate(date, dateStrBuf); + dateStrBuf.append(" "); + dateStrBuf.append(time); + return dateStrBuf.toString(); + } + + return time; + } +} diff --git a/src/net/java/sip/communicator/impl/callhistory/CallRecordImpl.java b/src/net/java/sip/communicator/impl/callhistory/CallRecordImpl.java index c52728a..bda0907 100644 --- a/src/net/java/sip/communicator/impl/callhistory/CallRecordImpl.java +++ b/src/net/java/sip/communicator/impl/callhistory/CallRecordImpl.java @@ -96,4 +96,13 @@ public class CallRecordImpl { this.direction = direction; } + + /** + * Sets the given <tt>ProtocolProviderService</tt> used for the call. + * @param pps the <tt>ProtocolProviderService</tt> to set + */ + public void setProtocolProvider(ProtocolProviderService pps) + { + this.protocolProvider = pps; + } } diff --git a/src/net/java/sip/communicator/impl/callhistory/callhistory.manifest.mf b/src/net/java/sip/communicator/impl/callhistory/callhistory.manifest.mf index b8db32f..44a6baf 100644 --- a/src/net/java/sip/communicator/impl/callhistory/callhistory.manifest.mf +++ b/src/net/java/sip/communicator/impl/callhistory/callhistory.manifest.mf @@ -14,6 +14,9 @@ Import-Package: org.osgi.framework, net.java.sip.communicator.service.protocol, net.java.sip.communicator.service.protocol.icqconstants, net.java.sip.communicator.service.protocol.event, + net.java.sip.communicator.service.contactsource, + net.java.sip.communicator.service.resources Export-Package: net.java.sip.communicator.service.callhistory, net.java.sip.communicator.service.callhistory.event -Metadata-Location: /net/java/sip/communicator/impl/msghistory/callhistory.metadata.xml +Metadata-Location: net.java.sip.communicator.impl.msghistory, + callhistory.metadata.xml |