diff --git a/jingle/extension/source/org/jivesoftware/smackx/jingle/JingleManager.java b/jingle/extension/source/org/jivesoftware/smackx/jingle/JingleManager.java
index 5ebdf94df..88af48df2 100644
--- a/jingle/extension/source/org/jivesoftware/smackx/jingle/JingleManager.java
+++ b/jingle/extension/source/org/jivesoftware/smackx/jingle/JingleManager.java
@@ -24,6 +24,7 @@ import org.jivesoftware.smack.*;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
+import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
@@ -261,10 +262,13 @@ public class JingleManager implements JingleSessionListener {
public void entriesDeleted(Collection addresses) {
}
- public void presenceChanged(String XMPPAddress) {
+ public void presenceChanged(Presence presence) {
+ String xmppAddress = presence.getFrom();
JingleSession aux = null;
for (JingleSession jingleSession : jingleSessions) {
- if (jingleSession.getInitiator().equals(XMPPAddress) || jingleSession.getResponder().equals(XMPPAddress)) {
+ if (jingleSession.getInitiator().equals(xmppAddress) ||
+ jingleSession.getResponder().equals(xmppAddress))
+ {
aux = jingleSession;
}
}
diff --git a/source/org/jivesoftware/smack/Roster.java b/source/org/jivesoftware/smack/Roster.java
index 4a4ffdd95..5661772b9 100644
--- a/source/org/jivesoftware/smack/Roster.java
+++ b/source/org/jivesoftware/smack/Roster.java
@@ -403,28 +403,33 @@ public class Roster implements ConnectionListener {
}
/**
- * Returns the presence info for a particular user, or null if the user
- * is unavailable (offline) or if no presence information is available, such as
- * when you are not subscribed to the user's presence updates.
+ * Returns the presence info for a particular user. If the user is offline, or
+ * if no presence data is available (such as when you are not subscribed to the
+ * user's presence updates), unavailable presence will be returned.
*
- * If the user has several presences (one for each resource) then answer the presence
- * with the highest priority.
+ * If the user has several presences (one for each resource), then the presence with
+ * highest priority will be returned. If multiple presences have the same priority,
+ * the one with the "most available" presence mode will be returned. In order,
+ * that's {@link Presence.Mode#chat free to chat}, {@link Presence.Mode#available available},
+ * {@link Presence.Mode#away away}, {@link Presence.Mode#xa extended away}, and
+ * {@link Presence.Mode#dnd do not disturb}.
*
* Note that presence information is received asynchronously. So, just after logging
- * in to the server, presence values for users in the roster might be null
+ * in to the server, presence values for users in the roster may be unavailable
* even if they are actually online. In other words, the value returned by this
* method should only be treated as a snapshot in time, and may not accurately reflect
* other user's presence instant by instant. If you need to track presence over time,
* such as when showing a visual representation of the roster, consider using a
* {@link RosterListener}.
*
- * @param user a fully qualified xmpp ID. The address could be in any valid format (e.g.
- * "domain/resource", "user@domain" or "user@domain/resource").
- * @return the user's current presence, or null if the user is unavailable
+ * @param user an XMPP ID. The address could be in any valid format (e.g.
+ * "domain/resource", "user@domain" or "user@domain/resource"). Any resource
+ * information that's part of the ID will be discarded.
+ * @return the user's current presence, or unavailable presence if the user is offline
* or if no presence information is available..
*/
public Presence getPresence(String user) {
- String key = getPresenceMapKey(user);
+ String key = getPresenceMapKey(StringUtils.parseBareAddress(user));
Map userPresences = presenceMap.get(key);
if (userPresences == null) {
return null;
@@ -436,29 +441,41 @@ public class Roster implements ConnectionListener {
for (String resource : userPresences.keySet()) {
Presence p = userPresences.get(resource);
+ // Chose presence with highest priority first.
if (presence == null || p.getPriority() > presence.getPriority()) {
presence = p;
}
+ // If equal priority, choose "most available" by the mode value.
+ else if (p.getPriority() == presence.getPriority()) {
+ if (p.getMode().compareTo(presence.getMode()) < 0) {
+ presence = p;
+ }
+ }
+ }
+ if (presence == null) {
+ return new Presence(Presence.Type.unavailable);
+ }
+ else {
+ return presence;
}
- return presence;
}
}
/**
- * Returns the presence info for a particular user's resource, or null if the user
- * is unavailable (offline) or if no presence information is available, such as
+ * Returns the presence info for a particular user's resource, or unavailable presence
+ * if the user is offline or if no presence information is available, such as
* when you are not subscribed to the user's presence updates.
*
- * @param userResource a fully qualified xmpp ID including a resource.
- * @return the user's current presence, or null if the user is unavailable
- * or if no presence information is available.
+ * @param userWithResource a fully qualified XMPP ID including a resource (user@domain/resource).
+ * @return the user's current presence, or unavailable presence if the user is offline
+ * or if no presence information is available.
*/
- public Presence getPresenceResource(String userResource) {
- String key = getPresenceMapKey(userResource);
- String resource = StringUtils.parseResource(userResource);
+ public Presence getPresenceResource(String userWithResource) {
+ String key = getPresenceMapKey(userWithResource);
+ String resource = StringUtils.parseResource(userWithResource);
Map userPresences = presenceMap.get(key);
if (userPresences == null) {
- return null;
+ return new Presence(Presence.Type.unavailable);
}
else {
return userPresences.get(resource);
@@ -466,20 +483,20 @@ public class Roster implements ConnectionListener {
}
/**
- * Returns an iterator (of Presence objects) for all the user's current presences
- * or null if the user is unavailable (offline) or if no presence information
+ * Returns an iterator (of Presence objects) for all of a user's current presences
+ * or an unavailable presence if the user is unavailable (offline) or if no presence information
* is available, such as when you are not subscribed to the user's presence updates.
*
- * @param user a fully qualified xmpp ID, e.g. jdoe@example.com
+ * @param user a XMPP ID, e.g. jdoe@example.com.
* @return an iterator (of Presence objects) for all the user's current presences,
- * or null if the user is unavailable or if no presence information
+ * or an unavailable presence if the user is offline or if no presence information
* is available.
*/
public Iterator getPresences(String user) {
String key = getPresenceMapKey(user);
Map userPresences = presenceMap.get(key);
if (userPresences == null) {
- return null;
+ return Arrays.asList(new Presence(Presence.Type.unavailable)).iterator();
}
else {
synchronized (userPresences) {
@@ -489,14 +506,14 @@ public class Roster implements ConnectionListener {
}
/**
- * Returns the key to use in the presenceMap for a fully qualified xmpp ID. The roster
+ * Returns the key to use in the presenceMap for a fully qualified XMPP ID. The roster
* can contain any valid address format such us "domain/resource", "user@domain" or
* "user@domain/resource". If the roster contains an entry associated with the fully qualified
- * xmpp ID then use the fully qualified xmpp ID as the key in presenceMap, otherwise use the
- * bare address. Note: When the key in presenceMap is a fully qualified xmpp ID, the
+ * XMPP ID then use the fully qualified XMPP ID as the key in presenceMap, otherwise use the
+ * bare address. Note: When the key in presenceMap is a fully qualified XMPP ID, the
* userPresences is useless since it will always contain one entry for the user.
*
- * @param user the fully qualified xmpp ID, e.g. jdoe@example.com/Work.
+ * @param user the bare or fully qualified XMPP ID, e.g. jdoe@example.com or jdoe@example.com/Work.
* @return the key to use in the presenceMap for the fully qualified xmpp ID.
*/
private String getPresenceMapKey(String user) {
@@ -538,11 +555,11 @@ public class Roster implements ConnectionListener {
/**
* Fires roster presence changed event to roster listeners.
*
- * @param user the user with a presence change.
+ * @param presence the presence change.
*/
- private void fireRosterPresenceEvent(String user) {
+ private void fireRosterPresenceEvent(Presence presence) {
for (RosterListener listener : rosterListeners) {
- listener.presenceChanged(user);
+ listener.presenceChanged(presence);
}
}
@@ -600,7 +617,7 @@ public class Roster implements ConnectionListener {
// If the user is in the roster, fire an event.
for (RosterEntry entry : entries) {
if (entry.getUser().equals(key)) {
- fireRosterPresenceEvent(from);
+ fireRosterPresenceEvent(presence);
}
}
}
@@ -618,7 +635,7 @@ public class Roster implements ConnectionListener {
// If the user is in the roster, fire an event.
for (RosterEntry entry : entries) {
if (entry.getUser().equals(key)) {
- fireRosterPresenceEvent(from);
+ fireRosterPresenceEvent(presence);
}
}
}
diff --git a/source/org/jivesoftware/smack/RosterListener.java b/source/org/jivesoftware/smack/RosterListener.java
index 71caa143c..a0dd8597b 100644
--- a/source/org/jivesoftware/smack/RosterListener.java
+++ b/source/org/jivesoftware/smack/RosterListener.java
@@ -3,7 +3,7 @@
* $Revision$
* $Date$
*
- * Copyright 2003-2004 Jive Software.
+ * Copyright 2003-2007 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@
package org.jivesoftware.smack;
+import org.jivesoftware.smack.packet.Presence;
+
import java.util.Collection;
/**
@@ -53,11 +55,25 @@ public interface RosterListener {
public void entriesDeleted(Collection addresses);
/**
- * Called when the presence of a roster entry is changed.
+ * Called when the presence of a roster entry is changed. Care should be taken
+ * when using the presence data delivered as part of this event. Specifically,
+ * when a user account is online with multiple resources, the UI should account
+ * for that. For example, say a user is online with their desktop computer and
+ * mobile phone. If the user logs out of the IM client on their mobile phone, the
+ * user should not be shown in the roster (contact list) as offline since they're
+ * still available as another resource.
*
- * @param XMPPAddress the XMPP address of the user who's presence has changed,
- * including the resource.
+ * To get the current "best presence" for a user after the presence update, query the roster:
+ *
+ * String user = presence.getFrom();
+ * Presence bestPresence = roster.getPresence(user);
+ *
+ *
+ * That will return the presence value for the user with the highest priority and
+ * availability.
+ *
+ * @param presence the presence that changed.
+ * @see Roster#getPresence(String)
*/
- public void presenceChanged(String XMPPAddress);
-}
-
+ public void presenceChanged(Presence presence);
+}
\ No newline at end of file
diff --git a/source/org/jivesoftware/smack/XMPPConnection.java b/source/org/jivesoftware/smack/XMPPConnection.java
index 10f567f21..ea6d4f23a 100644
--- a/source/org/jivesoftware/smack/XMPPConnection.java
+++ b/source/org/jivesoftware/smack/XMPPConnection.java
@@ -269,7 +269,7 @@ public class XMPPConnection {
/**
* Logs in to the server using the strongest authentication mode supported by
- * the server, then set our presence to available. If more than five seconds
+ * the server, then sets presence to available. If more than five seconds
* (default timeout) elapses in each step of the authentication process without
* a response from the server, or if an error occurs, a XMPPException will be thrown.
*
diff --git a/source/org/jivesoftware/smack/packet/Presence.java b/source/org/jivesoftware/smack/packet/Presence.java
index 6762c9f9a..a420be045 100644
--- a/source/org/jivesoftware/smack/packet/Presence.java
+++ b/source/org/jivesoftware/smack/packet/Presence.java
@@ -269,16 +269,16 @@ public class Presence extends Packet {
*/
public enum Mode {
- /**
- * Available (the default).
- */
- available,
-
/**
* Free to chat.
*/
chat,
+ /**
+ * Available (the default).
+ */
+ available,
+
/**
* Away.
*/