diff --git a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/connection/CollaborationConnection.java b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/connection/CollaborationConnection.java index ae8c42193f..02b491aa50 100644 --- a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/connection/CollaborationConnection.java +++ b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/connection/CollaborationConnection.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.viz.collaboration.comm.provider.connection; +import java.util.ArrayList; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; @@ -51,6 +52,7 @@ import com.raytheon.uf.viz.collaboration.comm.Activator; 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.identity.ISession; +import com.raytheon.uf.viz.collaboration.comm.identity.IVenueSession; import com.raytheon.uf.viz.collaboration.comm.identity.event.IEventPublisher; import com.raytheon.uf.viz.collaboration.comm.identity.event.IVenueInvitationEvent; import com.raytheon.uf.viz.collaboration.comm.identity.invite.SharedDisplayVenueInvite; @@ -118,6 +120,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant; * Apr 15, 2014 2822 bclement added pubsub owner subscriptions provider registration * Apr 23, 2014 2822 bclement added resource name and getCollaborationVersion() * May 09, 2014 3107 bclement added ability for packet timeout to be set via system properties + * May 19, 2014 3180 bclement added getJoinedVenueSessions() * * * @@ -615,6 +618,21 @@ public class CollaborationConnection implements IEventPublisher { return sessions.values(); } + /** + * @return all IVenueSessions that this user is a participant in + */ + public Collection getJoinedVenueSessions() { + Collection allSessions = getSessions(); + ArrayList rval = new ArrayList( + allSessions.size()); + for (ISession session : allSessions) { + if (session != null && session instanceof IVenueSession) { + rval.add((IVenueSession) session); + } + } + return rval; + } + /** * @return Smack connection object */ diff --git a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/connection/SessionInviteListener.java b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/connection/SessionInviteListener.java index 10eafcf701..b468bc4de7 100644 --- a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/connection/SessionInviteListener.java +++ b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/connection/SessionInviteListener.java @@ -26,6 +26,7 @@ import org.jivesoftware.smackx.muc.InvitationListener; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.xmpp.PacketConstants; +import com.raytheon.uf.viz.collaboration.comm.identity.IVenueSession; import com.raytheon.uf.viz.collaboration.comm.identity.event.IVenueInvitationEvent; import com.raytheon.uf.viz.collaboration.comm.identity.invite.VenueInvite; import com.raytheon.uf.viz.collaboration.comm.packet.SessionPayload; @@ -46,6 +47,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueId; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 11, 2014 2903 bclement Initial creation + * May 19, 2014 3180 bclement added alreadyParticipating() * * * @@ -79,11 +81,15 @@ public class SessionInviteListener implements InvitationListener { public void invitationReceived(Connection conn, String room, String inviter, String reason, String password, Message message) { // TODO handle password protected rooms - VenueId venueId = new VenueId(); - venueId.setName(Tools.parseName(room)); - venueId.setHost(Tools.parseHost(room)); + VenueId venueId = VenueId.fromString(room); UserId invitor = IDConverter.convertFrom(inviter); + if (alreadyParticipating(venueId)) { + statusHandler.debug("Invited to session we are already in: " + + venueId + " by " + inviter); + return; + } + SessionPayload payload = null; if (message != null) { payload = (SessionPayload) message @@ -100,6 +106,23 @@ public class SessionInviteListener implements InvitationListener { } } + /** + * @param venue + * @return true if this user is already participanting in the venue + */ + private static boolean alreadyParticipating(VenueId venue) { + boolean rval = false; + CollaborationConnection connection = CollaborationConnection + .getConnection(); + for (IVenueSession session : connection.getJoinedVenueSessions()) { + if (venue.isSameVenue(session.getVenue().getId())) { + rval = true; + break; + } + } + return rval; + } + /** * Handles acceptance of a text only session invitation * diff --git a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/user/VenueId.java b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/user/VenueId.java index d275a93044..979553d5fa 100644 --- a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/user/VenueId.java +++ b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/user/VenueId.java @@ -20,6 +20,7 @@ package com.raytheon.uf.viz.collaboration.comm.provider.user; import com.raytheon.uf.viz.collaboration.comm.identity.user.IQualifiedID; +import com.raytheon.uf.viz.collaboration.comm.provider.Tools; /** * Qualified id for a venue @@ -32,6 +33,7 @@ import com.raytheon.uf.viz.collaboration.comm.identity.user.IQualifiedID; * ------------ ---------- ----------- -------------------------- * Mar 29, 2012 jkorman Initial creation * Feb 13, 2014 2751 bclement removed resource, fixed getFQN + * May 19, 2014 3180 bclement added isSameVenue() fromString() and hashcode/equals * * * @@ -83,4 +85,78 @@ public class VenueId implements IQualifiedID { return name + "@" + host; } + /** + * @param venueId + * @return true if argument represents the same venue on the server + */ + public boolean isSameVenue(String venueId) { + boolean rval; + if (venueId == null) { + rval = false; + } else { + rval = this.equals(fromString(venueId)); + } + return rval; + } + + /** + * @param other + * @return true if argument represents the same venue on the server + */ + public boolean isSameVenue(VenueId other) { + return this.equals(other); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((host == null) ? 0 : host.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + VenueId other = (VenueId) obj; + if (host == null) { + if (other.host != null) + return false; + } else if (!host.equals(other.host)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + /** + * @param venueId + * in the form room@host + * @return + */ + public static VenueId fromString(String venueId) { + VenueId rval = new VenueId(); + rval.setName(Tools.parseName(venueId)); + rval.setHost(Tools.parseHost(venueId)); + return rval; + } } diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationGroupView.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationGroupView.java index 7db7506e18..7ee887f548 100644 --- a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationGroupView.java +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationGroupView.java @@ -153,6 +153,7 @@ import com.raytheon.viz.ui.views.CaveWorkbenchPageManager; * Mar 12, 2014 2632 mpduff Force group deletes from UI if last user is removed. * Apr 11, 2014 2903 bclement login action changes, removed server disconnect listener, * added static utility method to show view + * May 19, 2014 3180 bclement fixed inviting multiple users to session * * * @@ -446,6 +447,10 @@ public class CollaborationGroupView extends CaveFloatingView implements createMenu(manager); } } else if (o instanceof RosterGroup || o instanceof SharedGroup) { + Action inviteAction = new InviteAction(getSelectedUsers()); + if (inviteAction.isEnabled()) { + manager.add(inviteAction); + } manager.add(createSessionAction); if (o instanceof RosterGroup) { RosterGroup group = (RosterGroup) o; @@ -469,7 +474,7 @@ public class CollaborationGroupView extends CaveFloatingView implements .getConnection(); Presence presence = connection.getContactsManager().getPresence(user); if (presence != null && presence.getType() == Type.available) { - Action inviteAction = new InviteAction(user); + Action inviteAction = new InviteAction(getSelectedUsers()); if (inviteAction.isEnabled()) { manager.add(inviteAction); } diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/actions/InviteAction.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/actions/InviteAction.java index 9512195ba9..59f68626ab 100644 --- a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/actions/InviteAction.java +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/actions/InviteAction.java @@ -20,9 +20,11 @@ package com.raytheon.uf.viz.collaboration.ui.actions; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; -import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ActionContributionItem; @@ -30,14 +32,11 @@ import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IMenuCreator; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Menu; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.packet.Presence.Type; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException; -import com.raytheon.uf.viz.collaboration.comm.identity.ISession; import com.raytheon.uf.viz.collaboration.comm.identity.ISharedDisplaySession; import com.raytheon.uf.viz.collaboration.comm.identity.IVenueSession; import com.raytheon.uf.viz.collaboration.comm.identity.invite.SharedDisplayVenueInvite; @@ -48,7 +47,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant; import com.raytheon.uf.viz.collaboration.display.data.SharedDisplaySessionMgr; /** - * Invire some users to join a session. + * Invite some users to join a session. * *
  * 
@@ -61,6 +60,7 @@ import com.raytheon.uf.viz.collaboration.display.data.SharedDisplaySessionMgr;
  * Jan 28, 2014 2698       bclement    removed venue info
  * Jan 30, 2014 2698       bclement    changed UserId to VenueParticipant
  * Mar 06, 2014 2848       bclement    get venueName directly from session
+ * May 19, 2014 3180       bclement    replaced getNewSessions() with new logic in getFilteredSessions()
  * 
  * 
* @@ -95,8 +95,6 @@ public class InviteAction extends Action { this.users = users; this.session = session; this.setToolTipText("Invite selected user(s) to join a session."); - // set the initial enabled state. - isEnabled(); } @Override @@ -140,52 +138,60 @@ public class InviteAction extends Action { */ public void updateEnabled() { boolean enabled = false; - List newSessions = getNewSessions(); - if ((session == null && !newSessions.isEmpty()) - || newSessions.contains(session)) { + Collection filteredSessions = getFilteredSessions(); + if ((session == null && !filteredSessions.isEmpty()) + || filteredSessions.contains(session)) { enabled = true; } setEnabled(enabled); } - private List getNewSessions() { + /** + * @return a collection of VenueSessions in which the current user is a + * participant and any of the {@link #users} are not + * @see #allInSession(Collection, IVenueSession) + */ + private Collection getFilteredSessions() { + CollaborationConnection connection = CollaborationConnection + .getConnection(); + Collection allSessions = connection + .getJoinedVenueSessions(); List result = new ArrayList(); - for (UserId user : users) { - for (IVenueSession session : getNewSessions(user)) { - if (!result.contains(session)) { - result.add(session); - } + List userlist = Arrays.asList(this.users); + for (IVenueSession session : allSessions) { + if (!allInSession(userlist, session)) { + result.add(session); } } return result; } - private List getNewSessions(UserId user) { - Presence presence = CollaborationConnection.getConnection() - .getContactsManager().getPresence(user); - if (presence.getType() == Type.unavailable) { - return Collections.emptyList(); - } - List result = new ArrayList(); - Collection sessions = CollaborationConnection.getConnection() - .getSessions(); - for (ISession session : sessions) { - if (session != null && session instanceof IVenueSession) { - Collection participants = ((IVenueSession) session) - .getVenue().getParticipants(); - boolean notInRoom = true; - for (VenueParticipant pa : participants) { - if (pa.isSameUser(user)) { - notInRoom = false; - break; - } - } - if (notInRoom) { - result.add((IVenueSession) session); - } + /** + * Note: this method will always return false for a session in which this + * user cannot know the real user IDs of the participants + * + * @param users + * @param session + * @return false if any of the users are not in the session + */ + private static boolean allInSession(Collection users, + IVenueSession session) { + boolean rval = true; + Collection participants = session.getVenue() + .getParticipants(); + Set participantIds = new HashSet(participants.size()); + for (VenueParticipant vp : participants) { + if (vp.hasActualUserId()) { + participantIds.add(vp.getUserid().getNormalizedId()); } } - return result; + for (UserId user : users) { + if (!participantIds.contains(user.getNormalizedId())) { + rval = false; + break; + } + } + return rval; } private class MenuCreator implements IMenuCreator { @@ -212,7 +218,7 @@ public class InviteAction extends Action { } private void fill() { - for (IVenueSession session : getNewSessions()) { + for (IVenueSession session : getFilteredSessions()) { String name = session.getVenueName(); Action action = new InviteAction(session, name, users); IContributionItem contrib = new ActionContributionItem(action);