From 5c1fc7f8b7deee3ad7579a087b460e9c68ed4292 Mon Sep 17 00:00:00 2001 From: Matt Tucker Date: Mon, 12 Feb 2007 00:56:47 +0000 Subject: [PATCH] * Roster.getPresence now forces bare JID (SMACK-192). * RosterListner API changes (SMACK-191). git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@7070 b35dd754-fafc-0310-a699-88a17e54d16e --- .../smackx/jingle/JingleManager.java | 8 +- source/org/jivesoftware/smack/Roster.java | 85 +++++++++++-------- .../jivesoftware/smack/RosterListener.java | 30 +++++-- .../jivesoftware/smack/XMPPConnection.java | 2 +- .../jivesoftware/smack/packet/Presence.java | 10 +-- 5 files changed, 86 insertions(+), 49 deletions(-) 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. */