/* * 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.protocol.sip; import net.java.sip.communicator.service.protocol.*; import javax.sip.*; import javax.sip.address.*; import java.util.*; /** * A simple, straightforward implementation of a SIP Contact. Since * the SIP protocol is not a real one, we simply store all contact details * in class fields. You should know that when implementing a real protocol, * the contact implementation would rather encapsulate contact objects from * the protocol stack and group property values should be returned after * consulting the encapsulated object. * * @author Emil Ivov * @author Benoit Pradelle */ public class ContactSipImpl implements Contact { /** * The id of the contact. */ private Address sipAddress = null; /** * The display name of the contact. */ private String displayName = null; /** * The provider that created us. */ private ProtocolProviderServiceSipImpl parentProvider = null; /** * The group that belong to. */ private ContactGroupSipImpl parentGroup = null; /** * The presence status of the contact. */ private PresenceStatus presenceStatus; /** * Determines whether this contact is persistent, i.e. member of the contact * list or whether it is here only temporarily. */ private boolean isPersistent = true; /** * Determines whether the contact has been resolved (i.e. we have a * confirmation that it is still on the server contact list). */ private boolean isResolved = false; /** * Determines whether this contact can be resolved or if he will be * never resolved (for example if he doesn't support SIMPLE) */ private boolean isResolvable = true; /** * Stores the dialog used for receiving the contact status */ private Dialog clientDialog = null; /** * Stores the dialog used for communicate our status to this contact */ private Dialog serverDialog = null; /** * The task which will send a final NOTIFY when a timeout occur in the * subscription of this contact. If the contact isn't subscribed at us, * this will remain null. */ private TimerTask timeoutTask = null; /** * The task which will refresh the subscription we've made with this * contact. If we didn't subscribe to this contact, it will remain null. */ private TimerTask resfreshTask = null; /** * Creates an instance of a meta contact with the specified string used * as a name and identifier. * * @param contactAddress the identifier of this contact * (also used as a name). * @param parentProvider the provider that created us. */ public ContactSipImpl( Address contactAddress, ProtocolProviderServiceSipImpl parentProvider) { this.sipAddress = contactAddress; displayName = contactAddress.getDisplayName(); if(displayName == null || displayName.trim().length() == 0) displayName = getAddress(); this.parentProvider = parentProvider; this.presenceStatus = parentProvider.getSipStatusEnum() .getStatus(SipStatusEnum.UNKNOWN); } /** * This method is only called when the contact is added to a new * <tt>ContactGroupSipImpl</tt> by the * <tt>ContactGroupSipImpl</tt> itself. * * @param newParentGroup the <tt>ContactGroupSipImpl</tt> that is now * parent of this <tt>ContactSipImpl</tt> */ void setParentGroup(ContactGroupSipImpl newParentGroup) { this.parentGroup = newParentGroup; } /** * Returns a String that can be used for identifying the contact. * * @return a String id representing and uniquely identifying the contact. */ public String getAddress() { SipURI sipURI = (SipURI)sipAddress.getURI(); return sipURI.getUser() + "@" + sipURI.getHost(); } /** * Returns the jain-sip Address instance that this contact is wrapping. * * @return the jain-sip Address instance that this contact is wrapping. */ public Address getSipAddress() { return sipAddress; } /** * Returns a String that could be used by any user interacting modules * for referring to this contact. * * @return a String that can be used for referring to this contact when * interacting with the user. */ public String getDisplayName() { return (displayName == null) ? getAddress() : displayName; } /** * Sets a String that could be used by any user interacting modules * for referring to this contact. * * @param displayName a human readable name to use for this contact. */ public void setDisplayName(String displayName) { this.displayName = displayName; } /** * Returns a byte array containing an image (most often a photo or an * avatar) that the contact uses as a representation. * * @return byte[] an image representing the contact. */ public byte[] getImage() { return null; } /** * Returns the status of the contact. * * @return always IcqStatusEnum.ONLINE. */ public PresenceStatus getPresenceStatus() { return this.presenceStatus; } /** * Sets <tt>sipPresenceStatus</tt> as the PresenceStatus that this * contact is currently in. * @param sipPresenceStatus the <tt>SipPresenceStatus</tt> * currently valid for this contact. */ public void setPresenceStatus(PresenceStatus sipPresenceStatus) { this.presenceStatus = sipPresenceStatus; } /** * Returns a reference to the protocol provider that created the contact. * * @return a refererence to an instance of the ProtocolProviderService */ public ProtocolProviderService getProtocolProvider() { return parentProvider; } /** * Determines whether or not this contact represents our own identity. * * @return true in case this is a contact that represents ourselves and * false otherwise. */ public boolean isLocal() { return false; } /** * Returns the group that contains this contact. * @return a reference to the <tt>ContactGroupSipImpl</tt> that * contains this contact. */ public ContactGroup getParentContactGroup() { return this.parentGroup; } /** * Returns a string representation of this contact, containing most of its * representative details. * * @return a string representation of this contact. */ public String toString() { StringBuffer buff = new StringBuffer("ContactSipImpl[ DisplayName=") .append(getDisplayName()).append("]"); return buff.toString(); } /** * Determines whether or not this contact is being stored by the server. * Non persistent contacts are common in the case of simple, non-persistent * presence operation sets. They could however also be seen in persistent * presence operation sets when for example we have received an event * from someone not on our contact list. Non persistent contacts are * volatile even when coming from a persistent presence op. set. They would * only exist until the application is closed and will not be there next * time it is loaded. * * @return true if the contact is persistent and false otherwise. */ public boolean isPersistent() { return isPersistent; } /** * Specifies whether or not this contact is being stored by the server. * Non persistent contacts are common in the case of simple, non-persistent * presence operation sets. They could however also be seen in persistent * presence operation sets when for example we have received an event * from someone not on our contact list. Non persistent contacts are * volatile even when coming from a persistent presence op. set. They would * only exist until the application is closed and will not be there next * time it is loaded. * * @param isPersistent true if the contact is persistent and false * otherwise. */ public void setPersistent(boolean isPersistent) { this.isPersistent = isPersistent; } /** * Returns null as no persistent data is required and the contact address is * sufficient for restoring the contact. * <p> * @return null as no such data is needed. */ public String getPersistentData() { return null; } /** * Returns the current timeout task associated with this contact. * * @return the current timeout task of this contact */ public TimerTask getTimeoutTask() { return this.timeoutTask; } /** * Sets the timeout task associated with this contact * * @param timeoutTask The timeout task to set */ public void setTimeoutTask(TimerTask timeoutTask) { this.timeoutTask = timeoutTask; } /** * Returns the current refresh task associated with this contact. * * @return The resfresh task */ public TimerTask getResfreshTask() { return this.resfreshTask; } /** * Changes the current refresh task of this contact. * * @param resfreshTask The resfresh task to set */ public void setResfreshTask(TimerTask resfreshTask) { this.resfreshTask = resfreshTask; } /** * Sets the client dialog associated with this contact. * The client dialog is the dialog we use to retrieve the presence * state of this contact. * * @param clientDialog the new clientDialog to use */ public void setClientDialog(Dialog clientDialog) { this.clientDialog = clientDialog; } /** * Returns the client dialog associated with this contact. * The client dialog is the dialog we use to retrieve the presence * state of this contact. * * @return the clientDialog associated with the contact */ public Dialog getClientDialog() { return this.clientDialog; } /** * Sets the server dialog associated with this contact. * The server dialog is the dialog we use to send our presence status * to this contact. * * @param serverDialog the new clientDialog to use */ public void setServerDialog(Dialog serverDialog) { this.serverDialog = serverDialog; } /** * Returns the server dialog associated with this contact. * The server dialog is the dialog we use to send our presence status * to this contact. * * @return the clientDialog associated with the contact */ public Dialog getServerDialog() { return this.serverDialog; } /** * Determines whether or not this contact has been resolved against the * server. Unresolved contacts are used when initially loading a contact * list that has been stored in a local file until the presence operation * set has managed to retrieve all the contact list from the server and has * properly mapped contacts to their on-line buddies. * * @return true if the contact has been resolved (mapped against a buddy) * and false otherwise. */ public boolean isResolved() { return this.isResolved; } /** * Makes the contact resolved or unresolved. * * @param resolved true to make the contact resolved; false to * make it unresolved */ public void setResolved(boolean resolved) { this.isResolved = resolved; } /** * Determines whether or not this contact can be resolved against the * server. * * @return true if the contact can be resolved (mapped against a buddy) * and false otherwise. */ public boolean isResolvable() { return this.isResolvable; } /** * Makes the contact resolvable or unresolvable. * * @param resolvable true to make the contact resolvable; false to * make it unresolvable */ public void setResolvable(boolean resolvable) { this.isResolvable = resolvable; } /** * Indicates whether some other object is "equal to" this one which in terms * of contacts translates to having equal ids. The resolved status of the * contacts deliberately ignored so that contacts would be declared equal * even if it differs. * <p> * @param obj the reference object with which to compare. * @return <code>true</code> if this contact has the same id as that of the * <code>obj</code> argument. */ public boolean equals(Object obj) { if (obj == null || ! (obj instanceof ContactSipImpl || obj instanceof String)) return false; if(obj instanceof String) { String sobj = (String)obj; if(getAddress().equalsIgnoreCase(sobj)) return true; SipURI sipURI = (SipURI)sipAddress.getURI(); if(sipURI.getUser().equalsIgnoreCase(sobj)) return true; return false; } ContactSipImpl sipContact = (ContactSipImpl) obj; return this.getAddress().equals(sipContact.getAddress()); } /** * Returns the presence operation set that this contact belongs * to. * * @return the <tt>OperationSetPresenceSipImpl</tt> that * this contact belongs to. */ public OperationSetPresenceSipImpl getParentPresenceOperationSet() { return (OperationSetPresenceSipImpl) parentProvider .getOperationSet(OperationSetPresence.class); } /** * Return the current status message of this contact. * * @return null as the protocol has currently no support of status messages */ public String getStatusMessage() { return null; } }