/******************************************************************************* * Copyright (c) 2005, 2007 Remy Suen * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Remy Suen <remy.suen@gmail.com> - initial API and implementation ******************************************************************************/ package org.eclipse.ecf.protocol.msn; import java.net.URLDecoder; import java.util.*; import org.eclipse.ecf.protocol.msn.events.IContactListener; import org.eclipse.ecf.protocol.msn.internal.encode.StringUtils; /** * <p> * This class represents a contact that a user has on his or her MSN list. * </p> * * <p> * <b>Note:</b> This class/interface is part of an interim API that is still * under development and expected to change significantly before reaching * stability. It is being made available at this early stage to solicit feedback * from pioneering adopters on the understanding that any code that uses this * API will almost certainly be broken (repeatedly) as the API evolves. * </p> */ public final class Contact { /** * The list of listeners that is attached to this. */ private final ArrayList listeners; /** * The list of groups that this contact is in. */ private final ArrayList groups; /** * The email address that is associated with this contact. */ private final String email; /** * The guid of this contact. */ private final String guid; /** * The displayed name of this contact, this is typically different from * their {@link #email}. */ private String name; /** * The personal message that the contact is currently displaying. */ private String personalMessage; /** * The current status of this user. * * @see Status#ONLINE Status.ONLINE and others */ private Status status; /** * Creates a new Contact with the given name and email address. * @param email * the user's email address * @param name * the contact's MSN nickname in raw format, the name will be URL * decoded accordingly */ Contact(String email, String name) { this(email, name, null); } Contact(String email, String name, String guid) { this.name = URLDecoder.decode(name); this.email = email; this.guid = guid; this.status = Status.OFFLINE; listeners = new ArrayList(); groups = new ArrayList(); } /** * Invokes the {@link IContactListener#statusChanged(Status)} method on * every listener within {@link #listeners}. This method is automatically * invoked when {@link #setStatus(Status)} is called. * * @param newStatus * the status that this contact has now switched to */ private void fireStatusChanged(Status newStatus) { synchronized (listeners) { for (int i = 0; i < listeners.size(); i++) { ((IContactListener) listeners.get(i)).statusChanged(newStatus); } } } /** * Invokes the {@link IContactListener#nameChanged(String)} method on every * listener within {@link #listeners}. This method is automatically invoked * when {@link #setDisplayName(String)} is called. * * @param newName * the new name of this contact */ private void fireNameChanged(String newName) { synchronized (listeners) { for (int i = 0; i < listeners.size(); i++) { ((IContactListener) listeners.get(i)).nameChanged(newName); } } } private void firePersonalMessageChanged(String message) { synchronized (listeners) { for (int i = 0; i < listeners.size(); i++) { ((IContactListener) listeners.get(i)).personalMessageChanged(message); } } } void add(Group group) { groups.add(group); } void remove() { for (int i = 0; i < groups.size(); i++) { ((Group) groups.get(i)).remove(this); } groups.clear(); } /** * Retrieves the groups that this contact is a part of. * * @return a collection of the groups that this contact is a member of */ public Collection getGroups() { return Collections.unmodifiableCollection(groups); } /** * Sets this contact's status to the given status. Developers are highly * discouraged from calling this method since if the user's status actually * did change, the {@link IContactListener#nameChanged(String)} method will * be invoked on all the listeners attached to this contact. * * @param status * the status that this contact is now in */ void setStatus(Status status) { if (this.status != status) { this.status = status; fireStatusChanged(status); } } /** * Retrieves the current status of this contact. * * @return the status that this contact currently is in */ public Status getStatus() { return status; } /** * Sets the user name of this contact with the given name. Developers are * highly discouraged from calling this method since if the value of * <code>newName</code> differs from the current name, the * {@link IContactListener#nameChanged(String)} method will be invoked on * all the listeners attached to this contact. * * @param newName * the new user name of this Contact */ void setDisplayName(String newName) { newName = URLDecoder.decode(newName); if (!newName.equals(name)) { this.name = newName; fireNameChanged(newName); } } /** * Gets the displayed name of this contact. * * @return the name that this contact uses */ public String getDisplayName() { return name; } /** * Changes the contact's personal message to the provided message if the two * messages differ. * * @param message * the message the contact may have set to */ void setPersonalMessage(String message) { message = StringUtils.xmlDecode(message); if (!message.equals(personalMessage)) { personalMessage = message; firePersonalMessageChanged(message); } } /** * Returns the personal message that this contact is currently using. * * @return the personal message in use */ public String getPersonalMessage() { return personalMessage; } /** * Returns the email address of the user. * * @return the user's email address */ public String getEmail() { return email; } String getGuid() { return guid; } /** * Adds a IContactListener to this contact. * * @param listener * the listener to be added */ public void addContactListener(IContactListener listener) { if (listener != null) { synchronized (listeners) { if (!listeners.contains(listener)) { listeners.add(listener); } } } } /** * Removes a IContactListener from this contact. * * @param listener * the listener to be removed */ public void removeContactListener(IContactListener listener) { if (listener != null) { synchronized (listeners) { listeners.remove(listener); } } } /** * Returns this contact's email address that's being used for identification * purposes in MSN. * * @return the contact's email address */ public String toString() { return email; } /** * Returns whether the specified object is equal to this. An object is equal * to this if it is also a <tt>Contact</tt> and its email addresses is * equal to this contact's email address. * @param obj * * @return <code>true</code> if the argument is a <tt>Contact</tt> and * also has the same email address as this */ public boolean equals(Object obj) { if (this == obj) { return true; } else if (obj instanceof Contact) { return email.equals(((Contact) obj).email); } else { return false; } } /** * Returns a unique integer hash code for this contact. * * @return a integer hash code that represents this contact */ public int hashCode() { return 31 * -1 + email.hashCode(); } }