/* * 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.service.protocol; import java.util.*; import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; /** * A representation of a Call. The Call class must only be created by users (i.e. * telephony protocols) of the PhoneUIService such as a SIP protocol * implementation. Extensions of this class might have names like SipCall * or H323Call or AnyOtherTelephonyProtocolCall * * @author Emil Ivov * @author Emanuel Onica */ public abstract class Call { private static final Logger logger = Logger.getLogger(Call.class); /** * An identifier uniquely representing the call. */ private final String callID; /** * A list of all listeners currently registered for * <tt>CallChangeEvent</tt>s */ private final List<CallChangeListener> callListeners = new Vector<CallChangeListener>(); /** * A reference to the ProtocolProviderService instance that created us. */ private final ProtocolProviderService protocolProvider; /** * If this flag is set to true according to the account properties * related with the sourceProvider the associated CallSession will start * encrypted by default (where applicable) */ private final boolean defaultEncryption; /** * Creates a new Call instance. * * @param sourceProvider the proto provider that created us. */ protected Call(ProtocolProviderService sourceProvider) { //create the uid this.callID = String.valueOf(System.currentTimeMillis()) + String.valueOf(super.hashCode()); this.protocolProvider = sourceProvider; defaultEncryption = protocolProvider.getAccountID().getAccountPropertyBoolean( ProtocolProviderFactory.DEFAULT_ENCRYPTION, true); } /** * Returns the id of the specified Call. * @return a String uniquely identifying the call. */ public String getCallID() { return callID; } /** * Compares the specified object with this call and returns true if it the * specified object is an instance of a Call object and if the * extending telephony protocol considers the calls represented by both * objects to be the same. * * @param obj the call to compare this one with. * @return true in case both objects are pertaining to the same call and * false otherwise. */ public boolean equals(Object obj) { if(obj == null || !(obj instanceof Call)) return false; return (obj == this) || ((Call)obj).getCallID().equals(getCallID()); } /** * Returns a hash code value for this call. * * @return a hash code value for this call. */ public int hashCode() { return getCallID().hashCode(); } /** * Returns an iterator over all call participants. * @return an Iterator over all participants currently involved in the call. */ public abstract Iterator<CallParticipant> getCallParticipants(); /** * Returns the number of participants currently associated with this call. * @return an <tt>int</tt> indicating the number of participants currently * associated with this call. */ public abstract int getCallParticipantsCount(); /** * Adds a call change listener to this call so that it could receive events * on new call participants, theme changes and others. * * @param listener the listener to register */ public void addCallChangeListener(CallChangeListener listener) { synchronized(callListeners) { if(!callListeners.contains(listener)) this.callListeners.add(listener); } } /** * Removes <tt>listener</tt> to this call so that it won't receive further * <tt>CallChangeEvent</tt>s. * @param listener the listener to register */ public void removeCallChangeListener(CallChangeListener listener) { synchronized(callListeners) { this.callListeners.remove(listener); } } /** * Returns a reference to the <tt>ProtocolProviderService</tt> instance * that created this call. * @return a reference to the <tt>ProtocolProviderService</tt> instance that * created this call. */ public ProtocolProviderService getProtocolProvider() { return this.protocolProvider; } /** * Creates a <tt>CallParticipantEvent</tt> with * <tt>sourceCallParticipant</tt> and <tt>eventID</tt> and dispatches it on * all currently registered listeners. * * @param sourceCallParticipant the source <tt>CallParticipant</tt> for the * newly created event. * @param eventID the ID of the event to create (see CPE member ints) */ protected void fireCallParticipantEvent(CallParticipant sourceCallParticipant, int eventID) { CallParticipantEvent cpEvent = new CallParticipantEvent( sourceCallParticipant, this, eventID); logger.debug("Dispatching a CallParticipant event to " + callListeners.size() +" listeners. event is: " + cpEvent.toString()); Iterator<CallChangeListener> listeners; synchronized(callListeners) { listeners = new ArrayList<CallChangeListener>(callListeners).iterator(); } while(listeners.hasNext()) { CallChangeListener listener = listeners.next(); if(eventID == CallParticipantEvent.CALL_PARTICIPANT_ADDED) listener.callParticipantAdded(cpEvent); else if (eventID == CallParticipantEvent.CALL_PARTICIPANT_REMVOVED) listener.callParticipantRemoved(cpEvent); } } /** * Returns a string textually representing this Call. * * @return a string representation of the object. */ public String toString() { return "Call: id=" + getCallID() + " participants=" + getCallParticipantsCount(); } /** * Creates a <tt>CallChangeEvent</tt> with this class as * <tt>sourceCall</tt>, and the specified <tt>eventID</tt> and old and new * values and dispatches it on all currently registered listeners. * * @param type the type of the event to create (see CallChangeEvent member * ints) * @param oldValue the value of the call property that changed, before the * event had occurred. * @param newValue the value of the call property that changed, after the * event has occurred. */ protected void fireCallChangeEvent( String type, Object oldValue, Object newValue) { CallChangeEvent ccEvent = new CallChangeEvent( this, type, oldValue, newValue); logger.debug("Dispatching a CallChange event to " + callListeners.size() +" listeners. event is: " + ccEvent.toString()); Iterator<CallChangeListener> listeners; synchronized(callListeners) { listeners = new ArrayList<CallChangeListener>(callListeners).iterator(); } while(listeners.hasNext()) { CallChangeListener listener = listeners.next(); if(type.equals(CallChangeEvent.CALL_STATE_CHANGE)) listener.callStateChanged(ccEvent); } } /** * Returns the state that this call is currently in. * * @return a reference to the <tt>CallState</tt> instance that the call is * currently in. */ public abstract CallState getCallState(); /** * Returns the default call encryption flag * * @return the default call encryption flag */ public boolean isDefaultEncrypted() { return defaultEncryption; } }