Issue #3070 fixed contact request handling

no longer get empty group if user denies contact request
fixed UI update issue when server removes from your roster
added icon for pending contact request
fixed auto accept reply from users you initiated contact request with


Former-commit-id: 01e773fb9d4ec8b0ab75ddf714b79debb9ad4096
This commit is contained in:
Brian Clements 2014-04-24 15:46:06 -05:00
parent b53d914640
commit 02f08d75c6
14 changed files with 125 additions and 63 deletions

View file

@ -19,9 +19,10 @@
**/
package com.raytheon.uf.viz.collaboration.comm.identity.event;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.packet.Presence;
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
/**
* Event fired when the roster has changed
*
@ -33,6 +34,7 @@ import org.jivesoftware.smack.packet.Presence;
* ------------ ---------- ----------- --------------------------
* Apr 06, 2012 jkorman Initial creation.
* Feb 24, 2014 2632 mpduff Added getPresence, changed getItem to getEntry.
* Apr 24, 2014 3070 bclement getEntry() returns UserId
*
* </pre>
*
@ -54,7 +56,7 @@ public interface IRosterChangeEvent {
*
* @return The changed entry
*/
RosterEntry getEntry();
UserId getEntry();
/**
* Get the Presence object.

View file

@ -50,7 +50,8 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 04, 2014 2785 mpduff Initial creation
* Apr 14, 2014 2903 bclement moved from session subpackage to account
* Apr 14, 2014 2903 bclement moved from session subpackage to account
* Apr 24, 2014 3070 bclement RosterChangeEvent changes, adds back even if blocked
*
* </pre>
*
@ -119,10 +120,8 @@ public class SubscriptionPacketListener implements PacketListener,
* @param fromID
*/
private void handleSubscribed(UserId fromID) {
ContactsManager cm = sessionManager.getContactsManager();
RosterEntry entry = cm.getRosterEntry(fromID);
IRosterChangeEvent event = new RosterChangeEvent(RosterChangeType.ADD,
entry);
fromID);
sessionManager.postEvent(event);
}
@ -132,13 +131,8 @@ public class SubscriptionPacketListener implements PacketListener,
* @param fromID
*/
private void handleUnsubscribed(UserId fromID) {
ContactsManager cm = sessionManager.getContactsManager();
RosterEntry entry = cm.getRosterEntry(fromID);
if (entry == null) {
return;
}
IRosterChangeEvent event = new RosterChangeEvent(
RosterChangeType.DELETE, entry);
RosterChangeType.DELETE, fromID);
sessionManager.postEvent(event);
}
@ -149,28 +143,29 @@ public class SubscriptionPacketListener implements PacketListener,
*/
private void handleSubResponse(UserId fromId, SubscriptionResponse response) {
Presence.Type subscribedType;
ContactsManager cm = sessionManager.getContactsManager();
boolean addToRoster = false;
if (response.isAccepted()) {
subscribedType = Presence.Type.subscribed;
RosterEntry entry = cm.getRosterEntry(fromId);
if (entry == null) {
addToRoster = true;
}
} else {
subscribedType = Presence.Type.unsubscribed;
}
Presence presence = new Presence(subscribedType);
try {
sendPresence(fromId, presence);
if (addToRoster) {
if (response.addToGroup()) {
cm.addToGroup(response.getGroup(), fromId);
} else {
cm.addToRoster(fromId);
if (response.isAccepted()) {
/* add them back */
ContactsManager cm = sessionManager.getContactsManager();
RosterEntry entry = cm.getRosterEntry(fromId);
if (entry != null && ContactsManager.isBlocked(entry)) {
/* in roster, but blocked */
cm.sendContactRequest(fromId);
}
if (response.addToGroup()) {
/*
* if contact is not in roster, this will also send them a
* contact request, otherwise it just add them to the group
*/
cm.addToGroup(response.getGroup(), fromId);
}
}
} catch (CollaborationException e) {
log.error("Unable to send presence", e);

View file

@ -19,11 +19,11 @@
**/
package com.raytheon.uf.viz.collaboration.comm.provider.event;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.packet.Presence;
import com.raytheon.uf.viz.collaboration.comm.identity.event.IRosterChangeEvent;
import com.raytheon.uf.viz.collaboration.comm.identity.event.RosterChangeType;
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
/**
* Event posted when a roster entry needs to be updated
@ -36,6 +36,7 @@ import com.raytheon.uf.viz.collaboration.comm.identity.event.RosterChangeType;
* ------------ ---------- ----------- --------------------------
* Apr 11, 2012 jkorman Initial creation
* Feb 24, 2014 2632 mpduff Added getPresence, changed getItem to getEntry.
* Apr 24, 2014 3070 bclement getEntry() returns UserId
*
* </pre>
*
@ -47,7 +48,7 @@ public class RosterChangeEvent implements IRosterChangeEvent {
private final RosterChangeType type;
private final RosterEntry entry;
private final UserId entry;
/** The presence object */
private Presence presence;
@ -60,7 +61,7 @@ public class RosterChangeEvent implements IRosterChangeEvent {
* @param entry
* The changed entry.
*/
public RosterChangeEvent(RosterChangeType type, RosterEntry entry) {
public RosterChangeEvent(RosterChangeType type, UserId entry) {
this.type = type;
this.entry = entry;
}
@ -76,7 +77,7 @@ public class RosterChangeEvent implements IRosterChangeEvent {
* @param presence
* The presence object
*/
public RosterChangeEvent(RosterChangeType type, RosterEntry entry,
public RosterChangeEvent(RosterChangeType type, UserId entry,
Presence presence) {
this.type = type;
this.entry = entry;
@ -102,7 +103,7 @@ public class RosterChangeEvent implements IRosterChangeEvent {
* @see com.raytheon.uf.viz.collaboration.comm.identity.event.IRosterChangeEvent#getEntry()
*/
@Override
public RosterEntry getEntry() {
public UserId getEntry() {
return entry;
}

View file

@ -26,7 +26,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterListener;
import org.jivesoftware.smack.packet.Presence;
@ -48,6 +47,8 @@ import com.raytheon.uf.viz.collaboration.comm.provider.event.RosterChangeEvent;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 22, 2014 2822 bclement Initial creation
* Apr 24, 2014 3070 bclement removed roster,
* RosterChangedEvent sends UserId not RosterEntry
*
* </pre>
*
@ -58,17 +59,14 @@ public class ContactsListener implements RosterListener {
private final ContactsManager manager;
private final Roster roster;
private final Map<String, List<ResourceInfo>> contactResources = new HashMap<String, List<ResourceInfo>>();
/**
* @param manager
* @param roster
*/
public ContactsListener(ContactsManager manager, Roster roster) {
public ContactsListener(ContactsManager manager) {
this.manager = manager;
this.roster = roster;
}
/*
@ -92,9 +90,11 @@ public class ContactsListener implements RosterListener {
}
}
RosterEntry entry = manager.getRosterEntry(u);
post(entry);
if (entry != null) {
post(entry);
}
IRosterChangeEvent event = new RosterChangeEvent(
RosterChangeType.PRESENCE, entry, presence);
RosterChangeType.PRESENCE, u, presence);
post(event);
}
}
@ -197,11 +197,13 @@ public class ContactsListener implements RosterListener {
*/
private void send(Collection<String> addresses, RosterChangeType type) {
for (String addy : addresses) {
RosterEntry entry = roster.getEntry(addy);
if (entry != null) {
IRosterChangeEvent event = new RosterChangeEvent(type, entry);
post(event);
}
UserId entry = IDConverter.convertFrom(addy);
/*
* RosterChangeEvents can't use RosterEntry objects because DELETE
* events happen after the entry is removed from the server roster
*/
IRosterChangeEvent event = new RosterChangeEvent(type, entry);
post(event);
}
}

View file

@ -47,6 +47,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.collections.UpdatingSet;
import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
import com.raytheon.uf.viz.collaboration.comm.identity.IAccountManager;
import com.raytheon.uf.viz.collaboration.comm.provider.Tools;
import com.raytheon.uf.viz.collaboration.comm.provider.connection.CollaborationConnection;
@ -75,6 +76,8 @@ import com.raytheon.uf.viz.collaboration.comm.provider.connection.CollaborationC
* Apr 16, 2014 2981 bclement fixed NPE when cached shared group deleted on server
* Apr 23, 2014 2822 bclement moved roster listener to ContactsListener,
* added getSharedDisplayEnabledResource()
* Apr 24, 2014 3070 bclement added checks for empty groups, added isContact(),
* added sendContactRequest()
*
* </pre>
*
@ -134,7 +137,7 @@ public class ContactsManager {
localAliases = UserIdWrapper.readAliasMap();
this.xmpp = xmpp;
Roster roster = xmpp.getRoster();
this.contactsListener = new ContactsListener(this, roster);
this.contactsListener = new ContactsListener(this);
roster.addRosterListener(this.contactsListener);
}
@ -154,7 +157,7 @@ public class ContactsManager {
* group will be null if it has been removed from server after
* cached in shared groups.
*/
if (rg != null) {
if (rg != null && !rg.getEntries().isEmpty()) {
rval.add(new SharedGroup(rg));
}
}
@ -176,7 +179,8 @@ public class ContactsManager {
} else {
rval = new ArrayList<RosterGroup>(groups.size());
for (RosterGroup group : groups) {
if (!shared.contains(group.getName())) {
if (!shared.contains(group.getName())
&& !group.getEntries().isEmpty()) {
rval.add(group);
}
}
@ -667,6 +671,7 @@ public class ContactsManager {
}
/**
*
* @param entry
* @return true if we are blocked from seeing updates from user in entry
*/
@ -697,6 +702,31 @@ public class ContactsManager {
return rval;
}
/**
*
* @param entry
* @return true if we can see updates from user in entry
*/
public static boolean isContact(RosterEntry entry) {
ItemType type = entry.getType();
return type != null
&& (type.equals(ItemType.both) || type.equals(ItemType.to));
}
/**
* @see #isContact(RosterEntry)
* @param id
* @return true if we can see updates from user
*/
public boolean isContact(UserId id) {
RosterEntry entry = getRosterEntry(id);
boolean rval = false;
if (entry != null) {
rval = isContact(entry);
}
return rval;
}
/**
* @see ContactsListener#getSharedDisplayEnabledResource(UserId)
* @param user
@ -706,6 +736,17 @@ public class ContactsManager {
return contactsListener.getSharedDisplayEnabledResource(user);
}
/**
* Send a contact request to user
*
* @param user
* @throws CollaborationException
*/
public void sendContactRequest(UserId user) throws CollaborationException {
IAccountManager manager = connection.getAccountManager();
manager.sendPresence(user, new Presence(Type.subscribe));
}
/**
* Listener interface for group update events
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 B

View file

@ -52,6 +52,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
* Feb 13, 2014 2751 bclement made generic for IUsers
* Feb 13, 2014 2751 njensen Extracted getImageName() to allow overrides
* Feb 17, 2014 2751 bclement moved block image logic to roster specific code
* Apr 24, 2014 3070 bclement added pending contact icon
*
* </pre>
*
@ -103,6 +104,14 @@ public abstract class AbstractUserLabelProvider<T extends IUser> extends
return null;
}
String key = getImageName(user);
if (element instanceof RosterEntry) {
RosterEntry entry = (RosterEntry) element;
ItemStatus status = entry.getStatus();
if (status != null) {
/* status always indicates pending */
key = "pending";
}
}
if (imageMap.get(key) == null && !key.equals("")) {
imageMap.put(key, CollaborationUtils.getNodeImage(key));
@ -144,7 +153,8 @@ public abstract class AbstractUserLabelProvider<T extends IUser> extends
}
ItemStatus status = entry.getStatus();
if (status != null) {
text.append(status).append(" pending\n");
/* status always indicates pending */
text.append("Contact request pending\n");
}
}
// delete trailing newline

View file

@ -42,6 +42,7 @@ import com.raytheon.uf.viz.core.localization.HierarchicalPreferenceStore;
* Mar 1, 2012 rferrel Initial creation
* Feb 19, 2014 2631 mpduff Changed to use the HierarchicalPreferenceStore.
* Feb 20, 2014 2631 mpduff Need to set defaults here since we changed to use the HierarchicalPreferenceStore
* Apr 24, 2014 3070 bclement added default groupname to preference defaults
*
* </pre>
*
@ -126,6 +127,8 @@ public class Activator extends AbstractUIPlugin {
prefs.setDefault(CollabPrefConstants.DEFAULT_HANDLE,
CollabPrefConstants.HandleOption.USERNAME.name());
prefs.setDefault(CollabPrefConstants.CUSTOM_HANDLE, "");
prefs.setDefault(CollabPrefConstants.DEFAULT_GROUPNAME_PREF,
"Contacts");
}
return prefs;
}

View file

@ -32,7 +32,6 @@ import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
import com.raytheon.uf.viz.collaboration.comm.provider.connection.CollaborationConnection;
import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager;
import com.raytheon.uf.viz.collaboration.comm.provider.user.SharedGroup;
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
import com.raytheon.uf.viz.collaboration.ui.data.CollaborationGroupContainer;
@ -51,6 +50,7 @@ import com.raytheon.uf.viz.collaboration.ui.data.SessionGroupContainer;
* Dec 6, 2013 2561 bclement removed ECF
* Jan 24, 2014 2701 bclement removed local groups, added shared groups
* Jan 27, 2014 2700 bclement added support roster entries
* Apr 24, 2014 3070 bclement removed check for hasInteraction() from group entries
*
* </pre>
*
@ -141,8 +141,7 @@ public class UsersTreeContentProvider implements ITreeContentProvider {
UserId localUser = connection.getUser();
for (RosterEntry entry : entries) {
String user = entry.getUser();
if (!localUser.isSameUser(user)
&& ContactsManager.hasInteraction(entry)) {
if (!localUser.isSameUser(user)) {
result.add(entry);
}
}

View file

@ -51,6 +51,7 @@ import com.raytheon.uf.viz.core.icon.IconUtil;
* Jul 3, 2012 bsteffen Initial creation
* Dec 20, 2013 2563 bclement added support for ungrouped roster entries
* Jan 24, 2014 2701 bclement removed local groups
* Apr 24, 2014 3070 bclement RosterChangeEvent changes
*
* </pre>
*
@ -114,8 +115,9 @@ public class AddToGroupAction extends Action {
if (entry != null) {
// the entry wasn't in a group, so the entire tree needs to be
// refreshed
UserId entryId = IDConverter.convertFrom(entry);
connection.postEvent(new RosterChangeEvent(RosterChangeType.MODIFY,
entry));
entryId));
}
}

View file

@ -26,6 +26,8 @@ import com.raytheon.uf.viz.collaboration.comm.identity.event.RosterChangeType;
import com.raytheon.uf.viz.collaboration.comm.provider.connection.CollaborationConnection;
import com.raytheon.uf.viz.collaboration.comm.provider.event.RosterChangeEvent;
import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager;
import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter;
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
import com.raytheon.uf.viz.collaboration.ui.Activator;
import com.raytheon.uf.viz.core.icon.IconUtil;
@ -40,6 +42,7 @@ import com.raytheon.uf.viz.core.icon.IconUtil;
* ------------ ---------- ----------- --------------------------
* Dec 20, 2013 2563 bclement Initial creation
* Mar 05, 2014 2837 bclement changed wording from Roster to Contacts, added image
* Apr 24, 2014 3070 bclement RosterChangeEvent changes
*
* </pre>
*
@ -64,7 +67,8 @@ public class RemoveFromRosterAction extends Action {
ContactsManager manager = connection
.getContactsManager();
manager.removeFromRoster(entry);
UserId entryId = IDConverter.convertFrom(entry);
connection.postEvent(new RosterChangeEvent(RosterChangeType.DELETE,
entry));
entryId));
}
}

View file

@ -21,12 +21,10 @@ package com.raytheon.uf.viz.collaboration.ui.actions;
import org.eclipse.jface.action.Action;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type;
import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
import com.raytheon.uf.viz.collaboration.comm.identity.IAccountManager;
import com.raytheon.uf.viz.collaboration.comm.provider.connection.CollaborationConnection;
import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager;
import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter;
import com.raytheon.uf.viz.collaboration.ui.Activator;
import com.raytheon.uf.viz.core.icon.IconUtil;
@ -42,6 +40,7 @@ import com.raytheon.uf.viz.core.icon.IconUtil;
* ------------ ---------- ----------- --------------------------
* Jan 24, 2014 bclement Initial creation
* Mar 05, 2014 2837 bclement added image
* Apr 24, 2014 3070 bclement moved contact request logic to contacts manager
*
* </pre>
*
@ -71,10 +70,9 @@ public class SendSubReqAction extends Action {
@Override
public void run() {
CollaborationConnection connection = CollaborationConnection.getConnection();
IAccountManager manager = connection.getAccountManager();
ContactsManager manager = connection.getContactsManager();
try {
manager.sendPresence(IDConverter.convertFrom(entry), new Presence(
Type.subscribe));
manager.sendContactRequest(IDConverter.convertFrom(entry));
} catch (CollaborationException e) {
Activator.statusHandler.error(
"Unable to send subscription request", e);

View file

@ -34,6 +34,7 @@ package com.raytheon.uf.viz.collaboration.ui.prefs;
* Feb 3, 2014 2699 bclement added handle preferences
* Feb 18, 2014 2631 mpduff Add constants for room change events.
* Mar 24, 2014 2936 mpduff Remove INCLUDE_NWS_FEED_FIELD_EDITOR_ID.
* Apr 24, 2014 3070 bclement added DEFAULT_GROUPNAME_PREF
*
* </pre>
*
@ -62,6 +63,8 @@ public class CollabPrefConstants {
public static final String CUSTOM_HANDLE = "customHandle";
public static final String DEFAULT_GROUPNAME_PREF = "defaultGroupName";
public static final int AWAY_TIMEOUT_DEFAULT = 10; // ten minutes
/** Enable join events field editor id */

View file

@ -19,7 +19,6 @@
**/
package com.raytheon.uf.viz.collaboration.ui.prefs;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@ -27,7 +26,6 @@ import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jface.preference.IPersistentPreferenceStore;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.jivesoftware.smack.RosterGroup;
import org.jivesoftware.smack.XMPPException;
import com.raytheon.uf.common.status.IUFStatusHandler;
@ -36,6 +34,7 @@ import com.raytheon.uf.viz.collaboration.comm.identity.roster.ISubscriptionRespo
import com.raytheon.uf.viz.collaboration.comm.identity.roster.SubscriptionResponse;
import com.raytheon.uf.viz.collaboration.comm.provider.account.ISubscriptionRequestCompleteAction;
import com.raytheon.uf.viz.collaboration.comm.provider.connection.CollaborationConnection;
import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager;
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserSearch;
import com.raytheon.uf.viz.collaboration.ui.Activator;
@ -52,6 +51,8 @@ import com.raytheon.uf.viz.core.VizApp;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 03, 2014 2785 mpduff Initial creation
* Apr 24, 2014 3070 bclement added default group for auto accept
* fixed auto accept known contacts
*
* </pre>
*
@ -88,15 +89,16 @@ public class SubscriptionResponderImpl implements ISubscriptionResponder {
.getPreferenceStore();
if (prefs.getBoolean(CollabPrefConstants.AUTO_ACCEPT_SUBSCRIBE)) {
rval.setAccepted(true);
rval.setGroup(prefs
.getString(CollabPrefConstants.DEFAULT_GROUPNAME_PREF));
action.executeSubscriptionRequestComplete(fromID, rval);
return;
}
CollaborationConnection conn = CollaborationConnection.getConnection();
Collection<RosterGroup> groups = conn.getContactsManager().getGroups(
fromID);
if (!groups.isEmpty()) {
// we already have this user in a group in our roster
ContactsManager cm = conn.getContactsManager();
if (cm.isContact(fromID)) {
/* we already have a subscription to this user */
rval.setAccepted(true);
action.executeSubscriptionRequestComplete(fromID, rval);
} else {