Issue #2701 removed local groups from collaboration

added shared groups to represent groups managed by server
local group actions changed to modify roster groups
code cleanup on contacts manager including removing unneeded roster manager
update script to clean up localization files
removed ui option to create an empty group


Former-commit-id: b86ad8ca6f [formerly f615f2226f] [formerly b86ad8ca6f [formerly f615f2226f] [formerly 26ac549096 [formerly 06a9db4836fa2753a913e2314a8c003380416eac]]]
Former-commit-id: 26ac549096
Former-commit-id: cfe945d76b [formerly 8944860cbb]
Former-commit-id: dd9b3ca640
This commit is contained in:
Brian Clements 2014-01-24 08:51:28 -06:00
parent 71a87d2ffe
commit ff1882e80a
23 changed files with 816 additions and 664 deletions

View file

@ -17,7 +17,9 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.swt, org.eclipse.swt,
com.raytheon.uf.common.comm, com.raytheon.uf.common.comm,
com.raytheon.uf.common.localization, com.raytheon.uf.common.localization,
com.raytheon.uf.viz.core com.raytheon.uf.viz.core,
com.raytheon.uf.common.time,
com.raytheon.uf.common.util
Export-Package: com.raytheon.uf.viz.collaboration.comm, Export-Package: com.raytheon.uf.viz.collaboration.comm,
com.raytheon.uf.viz.collaboration.comm.compression, com.raytheon.uf.viz.collaboration.comm.compression,
com.raytheon.uf.viz.collaboration.comm.identity, com.raytheon.uf.viz.collaboration.comm.identity,

View file

@ -110,6 +110,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueId;
* Jan 07, 2013 2563 bclement use getServiceName instead of getHost when creating room id * Jan 07, 2013 2563 bclement use getServiceName instead of getHost when creating room id
* Jan 08, 2014 2563 bclement fixed custom port and service name in user id * Jan 08, 2014 2563 bclement fixed custom port and service name in user id
* Jan 15, 2014 2630 bclement connection data stores status as Mode object * Jan 15, 2014 2630 bclement connection data stores status as Mode object
* Jan 24, 2014 2701 bclement removed roster manager
* *
* </pre> * </pre>
* *
@ -143,8 +144,6 @@ public class CollaborationConnection implements IEventPublisher {
private IAccountManager accountManager = null; private IAccountManager accountManager = null;
private RosterManager rosterManager = null;
private EventBus eventBus; private EventBus eventBus;
private ContactsManager contactsMgr; private ContactsManager contactsMgr;
@ -209,7 +208,7 @@ public class CollaborationConnection implements IEventPublisher {
accountManager.sendPresence(initialPresence); accountManager.sendPresence(initialPresence);
} }
contactsMgr = new ContactsManager(this); contactsMgr = new ContactsManager(this, connection);
this.registerEventHandler(contactsMgr); this.registerEventHandler(contactsMgr);
instanceMap.put(connectionData, this); instanceMap.put(connectionData, this);
@ -307,28 +306,6 @@ public class CollaborationConnection implements IEventPublisher {
return accountManager; return accountManager;
} }
/**
*
*/
private void setupRosterManager() {
if (rosterManager == null) {
if (isConnected()) {
rosterManager = new RosterManager(connection);
}
}
}
/**
*
* @return
*/
public RosterManager getRosterManager() {
if (rosterManager == null) {
setupRosterManager();
}
return rosterManager;
}
/** /**
* Is this SessionManager currently connected? * Is this SessionManager currently connected?
* *

View file

@ -1,100 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.collaboration.comm.provider.session;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
/**
* Manages roster from server
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 25, 2013 2561 bclement Initial creation
* Dec 20, 2013 2563 bclement added remove from roster method
*
* </pre>
*
* @author bclement
* @version 1.0
*/
public class RosterManager {
private final XMPPConnection connection;
/**
* @param connection
*/
public RosterManager(XMPPConnection connection) {
this.connection = connection;
}
/**
* @return roster from server connection
*/
public Roster getRoster() {
return connection.getRoster();
}
/**
* Add listener for roster events
*
* @param listener
*/
public void addRosterListener(RosterListener listener) {
getRoster().addRosterListener(listener);
}
/**
* Remove listener for roster events
*
* @param listener
*/
public void removeRosterListener(RosterListener listener) {
getRoster().removeRosterListener(listener);
}
/**
* Remove entry from roster on server
*
* @param entry
* @throws CollaborationException
*/
public void removeFromRoster(RosterEntry entry)
throws CollaborationException {
Roster roster = getRoster();
try {
roster.removeEntry(entry);
} catch (XMPPException e) {
throw new CollaborationException(
"Problem removing user from roster on server", e);
}
}
}

View file

@ -19,41 +19,34 @@
**/ **/
package com.raytheon.uf.viz.collaboration.comm.provider.user; package com.raytheon.uf.viz.collaboration.comm.provider.user;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.xml.bind.JAXB; import org.apache.commons.lang.StringUtils;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.jivesoftware.smack.Roster; import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry; import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type; import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smackx.SharedGroupManager;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationOpFailedException; import com.raytheon.uf.common.localization.exception.LocalizationOpFailedException;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; 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.CollaborationException;
import com.raytheon.uf.viz.collaboration.comm.provider.Tools; import com.raytheon.uf.viz.collaboration.comm.provider.Tools;
import com.raytheon.uf.viz.collaboration.comm.provider.event.UserNicknameChangedEvent; import com.raytheon.uf.viz.collaboration.comm.provider.event.UserNicknameChangedEvent;
import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection; import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection;
import com.raytheon.uf.viz.collaboration.comm.provider.session.RosterManager;
import com.raytheon.uf.viz.collaboration.comm.provider.user.LocalGroups.LocalGroup;
/** /**
* Manage contacts from local groups and roster on server * Manage contacts from local groups and roster on server
@ -68,6 +61,9 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.LocalGroups.LocalGro
* Dec 6, 2013 2561 bclement removed ECF * Dec 6, 2013 2561 bclement removed ECF
* Dec 20, 2013 2563 bclement roster items now removed from server, * Dec 20, 2013 2563 bclement roster items now removed from server,
* removed unneeded roster listener * removed unneeded roster listener
* Jan 24, 2014 2701 bclement removed roster manager
* switched local groups to roster groups
* added shared groups
* *
* </pre> * </pre>
* *
@ -79,230 +75,320 @@ public class ContactsManager {
private static final transient IUFStatusHandler statusHandler = UFStatus private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ContactsManager.class); .getHandler(ContactsManager.class);
private final Job storeLocalGroupsJob = new Job("Storing Local Groups") {
@Override
protected IStatus run(IProgressMonitor monitor) {
IPathManager pm = PathManagerFactory.getPathManager();
LocalizationContext context = pm.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.USER);
LocalizationFile file = PathManagerFactory.getPathManager()
.getLocalizationFile(
context,
"collaboration" + File.separator
+ "localGroups.xml");
LocalGroups obj;
synchronized (localGroups) {
obj = new LocalGroups(localGroups);
}
JAXB.marshal(obj, file.getFile());
try {
file.save();
} catch (LocalizationOpFailedException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
e);
}
return org.eclipse.core.runtime.Status.OK_STATUS;
}
};
private final CollaborationConnection connection; private final CollaborationConnection connection;
private final XMPPConnection xmpp;
private final UserSearch search; private final UserSearch search;
private List<LocalGroup> localGroups;
private Map<String, String> localAliases; private Map<String, String> localAliases;
/**
* Cached view of shared groups list on openfire. Will only reach out to
* server if it hasn't updated in an hour. This will disable itself if there
* is a problem communicating with the server since the most likely case is
* that the server doesn't support the operation.
*/
private UpdatingSet<String> sharedGroups = new UpdatingSet<String>(
TimeUtil.MILLIS_PER_HOUR) {
@Override
protected Set<String> update() {
Set<String> rval;
try {
List<String> names = SharedGroupManager.getSharedGroups(xmpp);
rval = new HashSet<String>(names);
} catch (XMPPException e) {
statusHandler.warn("Unable to get shared groups."
+ " Feature may not exist on server",
e.getLocalizedMessage());
disable();
rval = null;
}
return rval;
}
};
private Set<LocalGroupListener> groupListeners = new HashSet<LocalGroupListener>(); private Set<GroupListener> groupListeners = new HashSet<GroupListener>();
public ContactsManager(CollaborationConnection connection) { /**
* @param connection
* @param xmpp
*/
public ContactsManager(CollaborationConnection connection,
XMPPConnection xmpp) {
this.connection = connection; this.connection = connection;
this.search = connection.createSearch(); this.search = connection.createSearch();
localAliases = UserIdWrapper.readAliasMap(); localAliases = UserIdWrapper.readAliasMap();
initLocalGroups(); this.xmpp = xmpp;
}
/**
* Get groups that are managed by server. These are not modifiable from the
* client.
*
* @return
*/
public Collection<SharedGroup> getSharedGroups() {
Set<String> groups = sharedGroups.get();
List<SharedGroup> rval = new ArrayList<SharedGroup>(groups.size());
Roster roster = getRoster();
for (String group : groups) {
RosterGroup rg = roster.getGroup(group);
rval.add(new SharedGroup(rg));
}
return rval;
} }
private void initLocalGroups() { /**
storeLocalGroupsJob.setSystem(true); * Get groups that are managed by the client. This does not included shared
IPathManager pm = PathManagerFactory.getPathManager(); * groups.
LocalizationContext context = pm.getContext( *
LocalizationType.CAVE_STATIC, LocalizationLevel.USER); * @return
LocalizationFile file = PathManagerFactory.getPathManager() */
.getLocalizationFile(context, public Collection<RosterGroup> getGroups() {
"collaboration" + File.separator + "localGroups.xml"); Set<String> shared = sharedGroups.get();
if (file.exists()) { Collection<RosterGroup> groups = getRoster().getGroups();
this.localGroups = JAXB Collection<RosterGroup> rval;
.unmarshal(file.getFile(), LocalGroups.class).getGroups(); if (shared.isEmpty()) {
} rval = groups;
} else {
if (this.localGroups == null) { rval = new ArrayList<RosterGroup>(groups.size());
this.localGroups = new ArrayList<LocalGroup>(); for (RosterGroup group : groups) {
} if (!shared.contains(group.getName())) {
for (LocalGroup group : localGroups) { rval.add(group);
group.setManager(this);
}
}
public List<LocalGroup> getLocalGroups() {
synchronized (this.localGroups) {
return new ArrayList<LocalGroup>(this.localGroups);
}
}
public void addToLocalGroup(String groupName, UserId user) {
synchronized (this.localGroups) {
LocalGroup group = createLocalGroup(groupName);
String userId = user.getNormalizedId();
List<String> userNames = group.getUserNames();
if (!userNames.contains(userId)) {
List<UserId> users = group.getUsers();
group.getUserNames().add(userId);
users.add(user);
}
RosterEntry entry = getRosterEntry(user);
if (entry == null || entry.getGroups().isEmpty()) {
// In order to get presence for a user they must be in the
// roster, we can add them to the roster by either subscribing
// to them using presence or adding them to the roster,
// subscribing to the presence will not set the name correctly
// so we use the roster add method.
try {
RosterManager rosterManager = connection.getRosterManager();
Roster roster = rosterManager.getRoster();
roster.createEntry(userId, user.getAlias(), new String[0]);
} catch (XMPPException e) {
statusHandler.handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
} }
} }
for (LocalGroupListener listener : getSafeGroupListeners()) { }
return rval;
}
/**
* Add user to group. Creates group if it doesn't exist. Adds user to
* contacts if not in roster.
*
* @param groupName
* @param user
*/
public void addToGroup(String groupName, UserId user) {
Roster roster = getRoster();
RosterGroup group = roster.getGroup(groupName);
if (group == null) {
group = createGroup(groupName);
}
String id = user.getNormalizedId();
RosterEntry entry = group.getEntry(id);
if (entry != null) {
statusHandler
.debug("Attempted to add user to group it was already in: "
+ id + " in " + groupName);
return;
}
try {
addToGroup(group, user);
for (GroupListener listener : getSafeGroupListeners()) {
listener.userAdded(group, user); listener.userAdded(group, user);
} }
} catch (XMPPException e) {
String msg = getGroupModInfo(e);
statusHandler.error("Problem adding user to group: " + id + " to "
+ group.getName() + ". " + msg, e);
} }
storeLocalGroupsJob.schedule();
} }
public void deleteFromLocalGroup(String groupName, UserId user) { /**
synchronized (localGroups) { * Add user to group. Adds user to contacts if not in roster.
Iterator<LocalGroup> it = localGroups.iterator(); *
while (it.hasNext()) { * @param group
LocalGroup group = it.next(); * @param user
if (group.getName().equals(groupName)) { * @throws XMPPException
group.getUsers().remove(user); */
group.getUserNames().remove(user.getNormalizedId()); private void addToGroup(RosterGroup group, UserId user)
for (LocalGroupListener listener : getSafeGroupListeners()) { throws XMPPException {
listener.userDeleted(group, user); RosterEntry entry = getRosterEntry(user);
} if (entry == null) {
break; // we dont have user as a contact at all
} // ensure that the user object is up-to-date
user = findUser(user.getName());
String alias = user.getAlias();
if (StringUtils.isBlank(alias)) {
alias = user.getName();
} }
if (getLocalGroups(user).isEmpty()) { getRoster().createEntry(user.getFQName(), alias,
// if the user is in no local groups and no roster groups remove new String[] { group.getName() });
// them from our roster. } else {
RosterEntry entry = getRosterEntry(user); // just need to update groups
if (entry != null && entry.getGroups().isEmpty()) { group.addEntry(entry);
Presence presence = new Presence(Type.unsubscribe);
presence.setTo(user.getNormalizedId());
try {
connection.getAccountManager().sendPresence(presence);
} catch (CollaborationException e) {
statusHandler.error(
"Problem removing user from roster", e);
}
removeFromRoster(entry);
}
}
storeLocalGroupsJob.schedule();
} }
} }
/**
* Remove user from group.
*
* @param groupName
* @param user
*/
public void deleteFromGroup(String groupName, UserId user) {
RosterEntry entry = getRosterEntry(user);
if ( entry == null){
statusHandler.warn("Attempted to alter group for non-contact: " + user);
return;
}
RosterGroup group = getRoster().getGroup(groupName);
if ( group != null){
deleteFromGroup(group, entry);
} else {
statusHandler.warn("Attempted to modify non-existent group: "
+ groupName);
}
}
/**
* Remove entry from group.
*
* @param group
* @param entry
*/
private void deleteFromGroup(RosterGroup group, RosterEntry entry) {
try {
group.removeEntry(entry);
for (GroupListener listener : getSafeGroupListeners()) {
listener.userDeleted(group, IDConverter.convertFrom(entry));
}
} catch (XMPPException e) {
String msg = getGroupModInfo(e);
statusHandler.error("Problem removing entry from group: "
+ IDConverter.convertFrom(entry) + " from "
+ group.getName() + ". " + msg, e);
}
}
/**
* Attempt to get more information about group modification error. Returns
* an empty string if no extra information is found.
*
* @param e
* @return
*/
private String getGroupModInfo(XMPPException e) {
XMPPError xmppError = e.getXMPPError();
String rval = "";
if (xmppError != null) {
switch (xmppError.getCode()) {
case 406:
rval = "Group may not be modifiable. ";
break;
}
}
return rval;
}
/** /**
* Remove entry from roster on server * Remove entry from roster on server
* *
* @param entry * @param entry
* @throws CollaborationException
*/ */
public void removeFromRoster(RosterEntry entry) { public void removeFromRoster(RosterEntry entry) {
RosterManager rosterManager = connection.getRosterManager(); Roster roster = getRoster();
try { try {
rosterManager.removeFromRoster(entry); roster.removeEntry(entry);
} catch (CollaborationException e) { } catch (XMPPException e) {
statusHandler.error("Problem removing roster entry", e); statusHandler.error("Problem removing roster entry", e);
} }
} }
public LocalGroup createLocalGroup(String groupName) { /**
synchronized (localGroups) { * Create group. At least one entry must be placed into group for it to be
for (LocalGroup group : this.localGroups) { * persisted on server.
if (groupName.equals(group.getName())) { *
return group; * @param groupName
} * @return
} */
LocalGroup group = new LocalGroup(groupName); public RosterGroup createGroup(String groupName) {
group.setManager(this); Roster roster = getRoster();
localGroups.add(group); RosterGroup rval = roster.getGroup(groupName);
for (LocalGroupListener listener : getSafeGroupListeners()) { if ( rval != null){
statusHandler.debug("Attempted to create existing group: " + groupName);
return rval;
}
rval = roster.createGroup(groupName);
for (GroupListener listener : getSafeGroupListeners()) {
listener.groupCreated(rval);
}
return rval;
}
/**
* Remove all users from group.
*
* @param groupName
*/
public void deleteGroup(String groupName) {
Roster roster = getRoster();
RosterGroup group = roster.getGroup(groupName);
if ( group == null){
statusHandler.warn("Attempted to delete non-existent group: "
+ groupName);
return;
}
Collection<RosterEntry> entries = group.getEntries();
for (RosterEntry entry : entries) {
deleteFromGroup(group, entry);
}
for (GroupListener listener : getSafeGroupListeners()) {
listener.groupDeleted(group);
}
}
/**
* Move all users from old group to new group. If new group already exists,
* this will merge the two groups.
*
* @param oldName
* @param newName
*/
public void renameGroup(String oldName, String newName) {
Roster roster = getRoster();
RosterGroup group = roster.getGroup(oldName);
if (group == null) {
statusHandler.warn("Attempted to rename non-existent group: "
+ oldName);
return;
}
boolean merger = roster.getGroup(newName) != null;
group.setName(newName);
for (GroupListener listener : getSafeGroupListeners()) {
listener.groupDeleted(group);
}
if (!merger) {
for (GroupListener listener : getSafeGroupListeners()) {
listener.groupCreated(group); listener.groupCreated(group);
} }
storeLocalGroupsJob.schedule();
return group;
} }
} }
public void deleteLocalGroup(String groupName) { /**
synchronized (localGroups) { * Get groups that the user is in.
Iterator<LocalGroup> it = this.localGroups.iterator(); *
while (it.hasNext()) { * @param user
LocalGroup group = it.next(); * @return
if (groupName.equals(group.getName())) { */
List<UserId> users = new ArrayList<UserId>( public Collection<RosterGroup> getGroups(UserId user) {
group.getUsers()); RosterEntry entry = getRoster().getEntry(user.getNormalizedId());
for (UserId user : users) { if (entry == null) {
deleteFromLocalGroup(groupName, user); statusHandler.error("Requested groups for user not in roster: "
} + user);
it.remove(); return Collections.emptyList();
for (LocalGroupListener listener : getSafeGroupListeners()) {
listener.groupDeleted(group);
}
}
}
} }
storeLocalGroupsJob.schedule(); return entry.getGroups();
}
public void renameLocalGroup(String oldName, String newName) {
synchronized (localGroups) {
for (LocalGroup group : localGroups) {
if (oldName.equals(group.getName())) {
for (LocalGroupListener listener : getSafeGroupListeners()) {
listener.groupDeleted(group);
}
group.setName(newName);
for (LocalGroupListener listener : getSafeGroupListeners()) {
listener.groupCreated(group);
}
}
}
}
storeLocalGroupsJob.schedule();
}
public List<LocalGroup> getLocalGroups(UserId user) {
List<LocalGroup> results = new ArrayList<LocalGroup>();
synchronized (localGroups) {
for (LocalGroup group : localGroups) {
for (String userName : group.getUserNames()) {
if (user.getNormalizedId().equals(userName)) {
results.add(group);
break;
}
}
}
}
return results;
} }
/**
* Update local alias for user. Does not persist to server.
*
* @param user
* @param nickname
*/
public void setNickname(UserId user, String nickname) { public void setNickname(UserId user, String nickname) {
synchronized (localAliases) { synchronized (localAliases) {
@ -348,18 +434,36 @@ public class ContactsManager {
return alias; return alias;
} }
/**
* Get user info from roster. Does not include local alias information.
*
* @param userId
* @return
*/
public UserId getUser(String userId) { public UserId getUser(String userId) {
RosterEntry entry = searchRoster(getRoster(), userId); RosterEntry entry = searchRoster(userId);
if (entry == null) { if (entry == null) {
return null; return null;
} }
return IDConverter.convertFrom(entry); return IDConverter.convertFrom(entry);
} }
/**
* Get entry from roster for user. Does not include local alias information.
*
* @param user
* @return
*/
public RosterEntry getRosterEntry(UserId user) { public RosterEntry getRosterEntry(UserId user) {
return searchRoster(user); return searchRoster(user.getNormalizedId());
} }
/**
* Get last known presence for contact.
*
* @param user
* @return
*/
public Presence getPresence(UserId user) { public Presence getPresence(UserId user) {
UserId self = connection.getUser(); UserId self = connection.getUser();
if (self.isSameUser(user)) { if (self.isSameUser(user)) {
@ -369,54 +473,35 @@ public class ContactsManager {
return roster.getPresence(user.getNormalizedId()); return roster.getPresence(user.getNormalizedId());
} }
/**
* Get presence for this account.
*
* @return
*/
public Presence getSelfPresence() { public Presence getSelfPresence() {
return connection.getPresence(); return connection.getPresence();
} }
/** /**
* Used by local groups to make sure all local group items are in the * Convenience method for accessing roster.
* roster.
* *
* @param name
* @return
*/
protected UserId findAndAddUser(String id) {
UserId user = null;
RosterEntry entry = searchRoster(getRoster(), id);
if (entry != null) {
user = IDConverter.convertFrom(entry);
}
if (user == null) {
user = findUser(id);
if (user != null) {
try {
Roster roster = connection.getRosterManager().getRoster();
String alias = user.getAlias();
if (alias == null || alias.trim().isEmpty()) {
alias = user.getName();
}
roster.createEntry(user.getFQName(), alias, new String[0]);
} catch (XMPPException e) {
statusHandler.handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
}
}
return user;
}
/**
* @return * @return
*/ */
private Roster getRoster() { private Roster getRoster() {
return connection.getRosterManager().getRoster(); return xmpp.getRoster();
} }
private UserId findUser(String idString) { /**
* Perform an XMPP search for user. Includes any local alias information.
*
* @param username
* The part of the userid before the '@'
* @return null if not found
*/
private UserId findUser(String username) {
List<UserId> results; List<UserId> results;
try { try {
results = search.byId(idString); results = search.byUsername(username);
} catch (XMPPException e) { } catch (XMPPException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
return null; return null;
@ -431,44 +516,72 @@ public class ContactsManager {
return results.isEmpty() ? null : results.iterator().next(); return results.isEmpty() ? null : results.iterator().next();
} }
private RosterEntry searchRoster(UserId user) { /**
String userId = user.getNormalizedId(); * Get entry from roster for user. Does not include local alias information.
return searchRoster(connection.getRosterManager().getRoster(), userId); *
* @param userId
* @return
*/
private RosterEntry searchRoster(String userId) {
return getRoster().getEntry(userId);
} }
private RosterEntry searchRoster(Roster roster, String userId) { /**
return roster.getEntry(userId); * Add listeners to get information on when groups are modified
} *
* @param listener
public void addLocalGroupListener(LocalGroupListener listener) { */
public void addGroupListener(GroupListener listener) {
synchronized (groupListeners) { synchronized (groupListeners) {
groupListeners.add(listener); groupListeners.add(listener);
} }
} }
public void removeLocalGroupListener(LocalGroupListener listener) { /**
* Remove listener
*
* @param listener
*/
public void removeGroupListener(GroupListener listener) {
synchronized (groupListeners) { synchronized (groupListeners) {
groupListeners.remove(listener); groupListeners.remove(listener);
} }
} }
protected Set<LocalGroupListener> getSafeGroupListeners() { /**
Set<LocalGroupListener> safeSet = new HashSet<LocalGroupListener>(); * Get a copy of the listeners set
*
* @return
*/
protected Set<GroupListener> getSafeGroupListeners() {
Set<GroupListener> safeSet = new HashSet<GroupListener>();
synchronized (groupListeners) { synchronized (groupListeners) {
safeSet.addAll(groupListeners); safeSet.addAll(groupListeners);
} }
return safeSet; return safeSet;
} }
public static interface LocalGroupListener { /**
* Get a list of roster entries that do not belong to any group
*
* @return
*/
public Collection<RosterEntry> getNonGroupedContacts() {
return getRoster().getUnfiledEntries();
}
public void groupCreated(LocalGroup group); /**
* Listener interface for group update events
*/
public static interface GroupListener {
public void groupDeleted(LocalGroup group); public void groupCreated(RosterGroup group);
public void userAdded(LocalGroup group, UserId user); public void groupDeleted(RosterGroup group);
public void userDeleted(LocalGroup group, UserId user); public void userAdded(RosterGroup group, UserId user);
public void userDeleted(RosterGroup group, UserId user);
} }
} }

View file

@ -1,131 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.collaboration.comm.provider.user;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
* Group information not stored on chat server
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 2, 2012 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "LocalGroups")
public class LocalGroups {
@XmlElement(name = "group")
private List<LocalGroup> groups;
public LocalGroups() {
}
public LocalGroups(List<LocalGroup> groups) {
this.groups = new ArrayList<LocalGroup>(groups);
}
public List<LocalGroup> getGroups() {
return groups;
}
public void setGroups(List<LocalGroup> groups) {
this.groups = groups;
}
@XmlAccessorType(XmlAccessType.NONE)
public static class LocalGroup {
@XmlAttribute
private String name;
@XmlElement(name = "user")
private List<String> userNames;
@XmlTransient
private ContactsManager manager;
@XmlTransient
private List<UserId> users;
public LocalGroup() {
}
public LocalGroup(String name) {
this.name = name;
this.userNames = new ArrayList<String>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getUserNames() {
if (userNames == null) {
userNames = new ArrayList<String>();
}
return userNames;
}
public void setUserNames(List<String> userNames) {
this.userNames = userNames;
}
public synchronized List<UserId> getUsers() {
if (users == null) {
users = new ArrayList<UserId>();
for (String userName : userNames) {
UserId user = manager.findAndAddUser(userName);
if (user != null) {
users.add(user);
}
}
}
return users;
}
public void setManager(ContactsManager manager) {
this.manager = manager;
}
}
}

View file

@ -0,0 +1,76 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.collaboration.comm.provider.user;
import java.util.Collection;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
/**
* Shared group managed by xmpp server. Cannot be modified by client.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 23, 2014 2701 bclement Initial creation
*
* </pre>
*
* @author bclement
* @version 1.0
*/
public class SharedGroup {
private final RosterGroup delegate;
/**
* @param group
*/
public SharedGroup(RosterGroup group) {
this.delegate = group;
}
/**
* @return name of group
*/
public String getName() {
return delegate.getName();
}
/**
* @return collection of entries in this group
*/
public Collection<RosterEntry> getEntries() {
return delegate.getEntries();
}
/**
* @param entry
* @return true if entry is in this group
*/
public boolean contains(RosterEntry entry) {
return delegate.contains(entry);
}
}

View file

@ -46,6 +46,7 @@ import com.raytheon.uf.common.status.UFStatus;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Nov 22, 2013 2561 bclement Initial creation * Nov 22, 2013 2561 bclement Initial creation
* Jan 24, 2014 2701 bclement distinction between userid and username
* *
* </pre> * </pre>
* *
@ -62,7 +63,7 @@ public class UserSearch {
private static final String SEARCH_ACTION = "search"; private static final String SEARCH_ACTION = "search";
public static final String USERID_FIELD = "Username"; public static final String USERNAME_FIELD = "Username";
public static final String JABBER_ID_COLUMN = "jid"; public static final String JABBER_ID_COLUMN = "jid";
@ -81,14 +82,14 @@ public class UserSearch {
} }
/** /**
* Search by username * Search by username (the part of the user id before the @)
* *
* @param name * @param name
* @return list of user ids that match that name * @return list of user ids that match that name
* @throws XMPPException * @throws XMPPException
*/ */
public List<UserId> byId(String id) throws XMPPException { public List<UserId> byUsername(String username) throws XMPPException {
return byCriteria(USERID_FIELD, id); return byCriteria(USERNAME_FIELD, username);
} }
/** /**

View file

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 376 B

View file

Before

Width:  |  Height:  |  Size: 605 B

After

Width:  |  Height:  |  Size: 605 B

View file

@ -21,6 +21,7 @@ package com.raytheon.uf.viz.collaboration.ui;
**/ **/
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -88,9 +89,9 @@ import com.raytheon.uf.viz.collaboration.comm.provider.event.UserNicknameChanged
import com.raytheon.uf.viz.collaboration.comm.provider.event.UserPresenceChangedEvent; import com.raytheon.uf.viz.collaboration.comm.provider.event.UserPresenceChangedEvent;
import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection; import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection;
import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager; import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager;
import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager.LocalGroupListener; import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager.GroupListener;
import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter; import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter;
import com.raytheon.uf.viz.collaboration.comm.provider.user.LocalGroups.LocalGroup; 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.comm.provider.user.UserId;
import com.raytheon.uf.viz.collaboration.ui.actions.AddToGroupAction; import com.raytheon.uf.viz.collaboration.ui.actions.AddToGroupAction;
import com.raytheon.uf.viz.collaboration.ui.actions.ArchiveViewerAction; import com.raytheon.uf.viz.collaboration.ui.actions.ArchiveViewerAction;
@ -100,7 +101,6 @@ import com.raytheon.uf.viz.collaboration.ui.actions.ChangeRoleAction;
import com.raytheon.uf.viz.collaboration.ui.actions.ChangeSiteAction; import com.raytheon.uf.viz.collaboration.ui.actions.ChangeSiteAction;
import com.raytheon.uf.viz.collaboration.ui.actions.ChangeStatusAction; import com.raytheon.uf.viz.collaboration.ui.actions.ChangeStatusAction;
import com.raytheon.uf.viz.collaboration.ui.actions.ChangeStatusMessageAction; import com.raytheon.uf.viz.collaboration.ui.actions.ChangeStatusMessageAction;
import com.raytheon.uf.viz.collaboration.ui.actions.CreateGroupAction;
import com.raytheon.uf.viz.collaboration.ui.actions.CreateSessionAction; import com.raytheon.uf.viz.collaboration.ui.actions.CreateSessionAction;
import com.raytheon.uf.viz.collaboration.ui.actions.DeleteGroupAction; import com.raytheon.uf.viz.collaboration.ui.actions.DeleteGroupAction;
import com.raytheon.uf.viz.collaboration.ui.actions.DisplayFeedAction; import com.raytheon.uf.viz.collaboration.ui.actions.DisplayFeedAction;
@ -136,6 +136,8 @@ import com.raytheon.viz.ui.views.CaveFloatingView;
* Dec 6, 2013 2561 bclement removed ECF * Dec 6, 2013 2561 bclement removed ECF
* Dec 19, 2013 2563 bclement added subscribe method for server disconnection * Dec 19, 2013 2563 bclement added subscribe method for server disconnection
* Dec 20, 2013 2563 bclement fixed support for ungrouped roster items * Dec 20, 2013 2563 bclement fixed support for ungrouped roster items
* Jan 24, 2014 2701 bclement removed local groups, added shared groups
* removed option to create empty group
* *
* </pre> * </pre>
* *
@ -143,7 +145,7 @@ import com.raytheon.viz.ui.views.CaveFloatingView;
* @version 1.0 * @version 1.0
*/ */
public class CollaborationGroupView extends CaveFloatingView implements public class CollaborationGroupView extends CaveFloatingView implements
LocalGroupListener, IUserSelector { GroupListener, IUserSelector {
public static final String ID = "com.raytheon.uf.viz.collaboration.ui.CollaborationGroupView"; public static final String ID = "com.raytheon.uf.viz.collaboration.ui.CollaborationGroupView";
private TreeViewer usersTreeViewer; private TreeViewer usersTreeViewer;
@ -228,7 +230,7 @@ public class CollaborationGroupView extends CaveFloatingView implements
if (connection != null) { if (connection != null) {
connection.registerEventHandler(this); connection.registerEventHandler(this);
} }
connection.getContactsManager().addLocalGroupListener(this); connection.getContactsManager().addGroupListener(this);
populateTree(); populateTree();
usersTreeViewer.refresh(); usersTreeViewer.refresh();
parent.layout(); parent.layout();
@ -240,7 +242,7 @@ public class CollaborationGroupView extends CaveFloatingView implements
.getConnection(); .getConnection();
if (connection != null) { if (connection != null) {
connection.unregisterEventHandler(this); connection.unregisterEventHandler(this);
connection.getContactsManager().removeLocalGroupListener(this); connection.getContactsManager().removeGroupListener(this);
} }
super.dispose(); super.dispose();
@ -311,7 +313,6 @@ public class CollaborationGroupView extends CaveFloatingView implements
} }
private void createMenu(IMenuManager mgr) { private void createMenu(IMenuManager mgr) {
mgr.add(new CreateGroupAction());
mgr.add(new UserSearchAction()); mgr.add(new UserSearchAction());
mgr.add(new Separator()); mgr.add(new Separator());
mgr.add(new ChangeFontAction()); mgr.add(new ChangeFontAction());
@ -402,10 +403,10 @@ public class CollaborationGroupView extends CaveFloatingView implements
// the user, both the logged in user as well as entries in groups // the user, both the logged in user as well as entries in groups
UserId user = (UserId) o; UserId user = (UserId) o;
fillContextMenu(manager, selection, user); fillContextMenu(manager, selection, user);
} else if (o instanceof RosterGroup || o instanceof LocalGroup) { } else if (o instanceof RosterGroup || o instanceof SharedGroup) {
manager.add(createSessionAction); manager.add(createSessionAction);
if (o instanceof LocalGroup) { if (o instanceof RosterGroup) {
LocalGroup group = (LocalGroup) o; RosterGroup group = (RosterGroup) o;
manager.add(new DeleteGroupAction(group.getName())); manager.add(new DeleteGroupAction(group.getName()));
aliasAction.setId(group.getName()); aliasAction.setId(group.getName());
aliasAction.setText("Rename Group"); aliasAction.setText("Rename Group");
@ -438,8 +439,8 @@ public class CollaborationGroupView extends CaveFloatingView implements
manager.add(new AddToGroupAction(getSelectedUsers())); manager.add(new AddToGroupAction(getSelectedUsers()));
String groupName = null; String groupName = null;
Object group = selection.getPaths()[0].getFirstSegment(); Object group = selection.getPaths()[0].getFirstSegment();
if (group instanceof LocalGroup) { if (group instanceof RosterGroup) {
groupName = ((LocalGroup) group).getName(); groupName = ((RosterGroup) group).getName();
manager.add(new RemoveFromGroupAction(groupName, getSelectedUsers())); manager.add(new RemoveFromGroupAction(groupName, getSelectedUsers()));
} }
} }
@ -587,14 +588,14 @@ public class CollaborationGroupView extends CaveFloatingView implements
CollaborationConnection.getConnection().getContactsManager() CollaborationConnection.getConnection().getContactsManager()
.setNickname(user, newText); .setNickname(user, newText);
CollaborationConnection.getConnection().postEvent(user); CollaborationConnection.getConnection().postEvent(user);
for (LocalGroup group : CollaborationConnection.getConnection() for (RosterGroup group : CollaborationConnection.getConnection()
.getContactsManager().getLocalGroups(user)) { .getContactsManager().getGroups(user)) {
usersTreeViewer.refresh(group); usersTreeViewer.refresh(group);
} }
} else if (selectedObj instanceof LocalGroup) { } else if (selectedObj instanceof RosterGroup) {
LocalGroup group = (LocalGroup) selectedObj; RosterGroup group = (RosterGroup) selectedObj;
CollaborationConnection.getConnection().getContactsManager() CollaborationConnection.getConnection().getContactsManager()
.renameLocalGroup(group.getName(), newText); .renameGroup(group.getName(), newText);
} }
} }
@ -790,16 +791,13 @@ public class CollaborationGroupView extends CaveFloatingView implements
UserId user = IDConverter.convertFrom((RosterEntry) node); UserId user = IDConverter.convertFrom((RosterEntry) node);
selectedUsers.add(user); selectedUsers.add(user);
} else if (node instanceof RosterGroup) { } else if (node instanceof RosterGroup) {
selectedUsers.addAll(getSelectedUsers((RosterGroup) node)); Collection<RosterEntry> entries = ((RosterGroup) node)
} else if (node instanceof LocalGroup) { .getEntries();
for (UserId user : ((LocalGroup) node).getUsers()) { selectedUsers.addAll(getSelectedUsers(entries));
Presence presence = CollaborationConnection } else if (node instanceof SharedGroup) {
.getConnection().getContactsManager() Collection<RosterEntry> entries = ((SharedGroup) node)
.getPresence(user); .getEntries();
if (presence.getType() == Presence.Type.available) { selectedUsers.addAll(getSelectedUsers(entries));
selectedUsers.add(user);
}
}
} }
} }
@ -807,17 +805,16 @@ public class CollaborationGroupView extends CaveFloatingView implements
} }
/** /**
* This recursively searches group Nodes and returns all users with Type * This searches group entries and returns all users with Type AVAILABLE.
* AVAILABLE.
* *
* @param groupNode * @param entries
* @return users * @return users
*/ */
private Set<UserId> getSelectedUsers(RosterGroup groupNode) { private Set<UserId> getSelectedUsers(Collection<RosterEntry> entries) {
Set<UserId> selectedUsers = new HashSet<UserId>(); Set<UserId> selectedUsers = new HashSet<UserId>();
ContactsManager contacts = CollaborationConnection.getConnection() ContactsManager contacts = CollaborationConnection.getConnection()
.getContactsManager(); .getContactsManager();
for (RosterEntry node : groupNode.getEntries()) { for (RosterEntry node : entries) {
UserId user = IDConverter.convertFrom(node); UserId user = IDConverter.convertFrom(node);
Presence presence = contacts.getPresence(user); Presence presence = contacts.getPresence(user);
if (presence.getType() == Type.available) { if (presence.getType() == Type.available) {
@ -902,22 +899,22 @@ public class CollaborationGroupView extends CaveFloatingView implements
} }
@Override @Override
public void groupCreated(LocalGroup group) { public void groupCreated(RosterGroup group) {
refreshUsersTreeViewerAsync(usersTreeViewer.getInput()); refreshUsersTreeViewerAsync(usersTreeViewer.getInput());
} }
@Override @Override
public void groupDeleted(LocalGroup group) { public void groupDeleted(RosterGroup group) {
refreshUsersTreeViewerAsync(usersTreeViewer.getInput()); refreshUsersTreeViewerAsync(usersTreeViewer.getInput());
} }
@Override @Override
public void userAdded(LocalGroup group, UserId user) { public void userAdded(RosterGroup group, UserId user) {
refreshUsersTreeViewerAsync(group); refreshUsersTreeViewerAsync(group);
} }
@Override @Override
public void userDeleted(LocalGroup group, UserId user) { public void userDeleted(RosterGroup group, UserId user) {
refreshUsersTreeViewerAsync(group); refreshUsersTreeViewerAsync(group);
} }

View file

@ -37,7 +37,8 @@ import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConn
import com.raytheon.viz.ui.dialogs.CaveSWTDialog; import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
/** /**
* TODO Add Description * Dialog allowing user to create a new group in the roster. At least one user
* must be added to the group afterwards for it to be persisted on the server.
* *
* <pre> * <pre>
* *
@ -46,13 +47,13 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jun 27, 2012 bsteffen Initial creation * Jun 27, 2012 bsteffen Initial creation
* Jan 24, 2014 2701 bclement removed local groups
* *
* </pre> * </pre>
* *
* @author bsteffen * @author bsteffen
* @version 1.0 * @version 1.0
*/ */
public class CreateGroupDialog extends CaveSWTDialog { public class CreateGroupDialog extends CaveSWTDialog {
private Text nameText; private Text nameText;
@ -115,7 +116,7 @@ public class CreateGroupDialog extends CaveSWTDialog {
private void finish() { private void finish() {
newGroup = nameText.getText(); newGroup = nameText.getText();
CollaborationConnection.getConnection().getContactsManager() CollaborationConnection.getConnection().getContactsManager()
.createLocalGroup(newGroup); .createGroup(newGroup);
close(); close();
} }

View file

@ -33,13 +33,13 @@ import org.jivesoftware.smack.RosterGroup;
import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection; import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection;
import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter; import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter;
import com.raytheon.uf.viz.collaboration.comm.provider.user.LocalGroups.LocalGroup; 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.comm.provider.user.UserId;
import com.raytheon.uf.viz.collaboration.ui.data.CollaborationGroupContainer; import com.raytheon.uf.viz.collaboration.ui.data.CollaborationGroupContainer;
import com.raytheon.uf.viz.collaboration.ui.data.SessionGroupContainer; import com.raytheon.uf.viz.collaboration.ui.data.SessionGroupContainer;
/** /**
* TODO Add Description * Provides access to contacts list tree
* *
* <pre> * <pre>
* *
@ -49,6 +49,7 @@ import com.raytheon.uf.viz.collaboration.ui.data.SessionGroupContainer;
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Mar 1, 2012 rferrel Initial creation * Mar 1, 2012 rferrel Initial creation
* Dec 6, 2013 2561 bclement removed ECF * Dec 6, 2013 2561 bclement removed ECF
* Jan 24, 2014 2701 bclement removed local groups, added shared groups
* *
* </pre> * </pre>
* *
@ -118,35 +119,33 @@ public class UsersTreeContentProvider implements ITreeContentProvider {
return cont.getObjects().toArray(); return cont.getObjects().toArray();
} else if (parentElement instanceof RosterGroup) { } else if (parentElement instanceof RosterGroup) {
RosterGroup group = (RosterGroup) parentElement; RosterGroup group = (RosterGroup) parentElement;
List<UserId> result = new ArrayList<UserId>(); return getRosterChildren(group.getEntries());
UserId localUser = CollaborationConnection.getConnection() } else if (parentElement instanceof SharedGroup) {
.getUser(); SharedGroup group = (SharedGroup) parentElement;
Collection<RosterEntry> entries = group.getEntries(); return getRosterChildren(group.getEntries());
synchronized (entries) {
entries = new ArrayList<RosterEntry>(entries);
}
for (RosterEntry entry : entries) {
String user = entry.getUser();
if (!localUser.isSameUser(user)) {
result.add(IDConverter.convertFrom(entry));
}
}
return result.toArray();
} else if (parentElement instanceof LocalGroup) {
List<UserId> result = new ArrayList<UserId>();
LocalGroup group = (LocalGroup) parentElement;
UserId localUser = CollaborationConnection.getConnection()
.getUser();
for (UserId user : group.getUsers()) {
if (!localUser.isSameUser(user.getNormalizedId())) {
result.add(user);
}
}
return result.toArray();
} }
return null; return null;
} }
/**
* Get child objects of roster groups
*
* @param entries
* entries in group
* @return
*/
private Object[] getRosterChildren(Collection<RosterEntry> entries) {
List<UserId> result = new ArrayList<UserId>();
UserId localUser = CollaborationConnection.getConnection().getUser();
for (RosterEntry entry : entries) {
String user = entry.getUser();
if (!localUser.isSameUser(user)) {
result.add(IDConverter.convertFrom(entry));
}
}
return result.toArray();
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
@ -172,19 +171,10 @@ public class UsersTreeContentProvider implements ITreeContentProvider {
boolean hasChildren = false; boolean hasChildren = false;
if (element instanceof RosterGroup) { if (element instanceof RosterGroup) {
RosterGroup group = (RosterGroup) element; RosterGroup group = (RosterGroup) element;
UserId localUser = CollaborationConnection.getConnection() hasChildren = rosterHasChildren(group.getEntries());
.getUser(); } else if (element instanceof SharedGroup) {
Collection<RosterEntry> entries = group.getEntries(); SharedGroup group = (SharedGroup) element;
synchronized (entries) { hasChildren = rosterHasChildren(group.getEntries());
entries = new ArrayList<RosterEntry>(entries);
}
for (RosterEntry entry : entries) {
String user = entry.getUser();
if (!localUser.isSameUser(user)) {
hasChildren = true;
break;
}
}
} else if (element instanceof SessionGroupContainer) { } else if (element instanceof SessionGroupContainer) {
SessionGroupContainer cont = (SessionGroupContainer) element; SessionGroupContainer cont = (SessionGroupContainer) element;
if (cont.getObjects() != null && cont.getObjects().size() > 0) { if (cont.getObjects() != null && cont.getObjects().size() > 0) {
@ -192,16 +182,6 @@ public class UsersTreeContentProvider implements ITreeContentProvider {
} else { } else {
hasChildren = false; hasChildren = false;
} }
} else if (element instanceof LocalGroup) {
UserId localUser = CollaborationConnection.getConnection()
.getUser();
List<String> userNames = ((LocalGroup) element).getUserNames();
for (String userName : userNames) {
if (!localUser.isSameUser(userName)) {
hasChildren = true;
break;
}
}
} }
// need to check whether items are filtered out so we don't get // need to check whether items are filtered out so we don't get
@ -219,4 +199,22 @@ public class UsersTreeContentProvider implements ITreeContentProvider {
} }
return hasChildren; return hasChildren;
} }
/**
* @param entries
* @return true if entries has at least one entry that isn't the users
* account
*/
private boolean rosterHasChildren(Collection<RosterEntry> entries) {
UserId localUser = CollaborationConnection.getConnection().getUser();
boolean hasChildren = false;
for (RosterEntry entry : entries) {
String user = entry.getUser();
if (!localUser.isSameUser(user)) {
hasChildren = true;
break;
}
}
return hasChildren;
}
} }

View file

@ -43,7 +43,7 @@ import com.raytheon.uf.viz.collaboration.comm.identity.IVenueSession;
import com.raytheon.uf.viz.collaboration.comm.identity.info.IVenueInfo; import com.raytheon.uf.viz.collaboration.comm.identity.info.IVenueInfo;
import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection; import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection;
import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter; import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter;
import com.raytheon.uf.viz.collaboration.comm.provider.user.LocalGroups.LocalGroup; 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.comm.provider.user.UserId;
import com.raytheon.uf.viz.collaboration.ui.data.SessionGroupContainer; import com.raytheon.uf.viz.collaboration.ui.data.SessionGroupContainer;
@ -59,6 +59,7 @@ import com.raytheon.uf.viz.collaboration.ui.data.SessionGroupContainer;
* Mar 1, 2012 rferrel Initial creation * Mar 1, 2012 rferrel Initial creation
* Dec 6, 2013 2561 bclement removed ECF * Dec 6, 2013 2561 bclement removed ECF
* Dec 20, 2013 2563 bclement fixed support for ungrouped roster items * Dec 20, 2013 2563 bclement fixed support for ungrouped roster items
* Jan 24, 2014 2701 bclement removed local groups, added shared groups
* *
* </pre> * </pre>
* *
@ -105,13 +106,13 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
return userLabelProvider.getImage(IDConverter return userLabelProvider.getImage(IDConverter
.convertFrom((RosterEntry) element)); .convertFrom((RosterEntry) element));
} else if (element instanceof RosterGroup) { } else if (element instanceof RosterGroup) {
key = "group"; key = "roster_group";
} else if (element instanceof SharedGroup) {
key = "shared_group";
} else if (element instanceof IVenueSession) { } else if (element instanceof IVenueSession) {
// key = "session_group"; // key = "session_group";
} else if (element instanceof SessionGroupContainer) { } else if (element instanceof SessionGroupContainer) {
key = "session_group"; key = "session_group";
} else if (element instanceof LocalGroup) {
key = "local_group";
} }
if (imageMap.get(key) == null && !key.equals("")) { if (imageMap.get(key) == null && !key.equals("")) {
@ -124,6 +125,8 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
public String getText(Object element) { public String getText(Object element) {
if (element instanceof RosterGroup) { if (element instanceof RosterGroup) {
return ((RosterGroup) element).getName(); return ((RosterGroup) element).getName();
} else if (element instanceof SharedGroup) {
return ((SharedGroup) element).getName();
} else if (element instanceof RosterEntry) { } else if (element instanceof RosterEntry) {
return userLabelProvider.getText(IDConverter return userLabelProvider.getText(IDConverter
.convertFrom((RosterEntry) element)); .convertFrom((RosterEntry) element));
@ -153,17 +156,14 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
return null; return null;
} }
return info.getVenueDescription(); return info.getVenueDescription();
} else if (element instanceof LocalGroup) {
return ((LocalGroup) element).getName();
} }
return null; return null;
} }
@Override @Override
public Font getFont(Object element) { public Font getFont(Object element) {
if (element instanceof RosterGroup if (element instanceof RosterGroup || element instanceof SharedGroup
|| element instanceof SessionGroupContainer || element instanceof SessionGroupContainer) {
|| element instanceof LocalGroup) {
// for this case do nothing, as it is not the top level of // for this case do nothing, as it is not the top level of
// session groups // session groups
if (boldFont == null) { if (boldFont == null) {

View file

@ -26,12 +26,12 @@ import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup; import org.jivesoftware.smack.RosterGroup;
import com.raytheon.uf.viz.collaboration.comm.identity.IVenueSession; import com.raytheon.uf.viz.collaboration.comm.identity.IVenueSession;
import com.raytheon.uf.viz.collaboration.comm.provider.user.LocalGroups.LocalGroup; 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.comm.provider.user.UserId;
import com.raytheon.uf.viz.collaboration.ui.data.SessionGroupContainer; import com.raytheon.uf.viz.collaboration.ui.data.SessionGroupContainer;
/** /**
* TODO Add Description * Sorts the contacts list
* *
* <pre> * <pre>
* *
@ -41,6 +41,7 @@ import com.raytheon.uf.viz.collaboration.ui.data.SessionGroupContainer;
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Mar 1, 2012 rferrel Initial creation * Mar 1, 2012 rferrel Initial creation
* Dec 6, 2013 2561 bclement removed ECF * Dec 6, 2013 2561 bclement removed ECF
* Jan 24, 2014 2701 bclement removed local groups, added shared groups
* *
* </pre> * </pre>
* *
@ -74,9 +75,12 @@ public class UsersTreeViewerSorter extends ViewerSorter {
} }
// Groups before users. // Groups before users.
if (e1 instanceof RosterGroup) { if (e1 instanceof SharedGroup) {
if (!(e2 instanceof RosterGroup)) { if (!(e2 instanceof SharedGroup)) {
return -1; return -1;
} else {
return ((SharedGroup) e1).getName().compareTo(
((SharedGroup) e2).getName());
} }
} else if (e1 instanceof RosterGroup) { } else if (e1 instanceof RosterGroup) {
return 1; return 1;
@ -113,17 +117,18 @@ public class UsersTreeViewerSorter extends ViewerSorter {
return ((IVenueSession) e1).getVenue().toString() return ((IVenueSession) e1).getVenue().toString()
.compareTo(((IVenueSession) e2).getVenue().toString()); .compareTo(((IVenueSession) e2).getVenue().toString());
} }
if (e1 instanceof LocalGroup) { if (e1 instanceof RosterGroup) {
if (!(e2 instanceof LocalGroup)) { if (!(e2 instanceof RosterGroup)) {
return -1; return -1;
} }
} else if (e1 instanceof LocalGroup) { } else if (e1 instanceof RosterGroup) {
return 1; return 1;
} }
if (e1 instanceof LocalGroup && e2 instanceof LocalGroup) { if (e1 instanceof RosterGroup && e2 instanceof RosterGroup) {
return ((LocalGroup) e1).getName().compareTo( return ((RosterGroup) e1).getName().compareTo(
((LocalGroup) e2).getName()); ((RosterGroup) e2).getName());
} }
return 0; return 0;
} }
} }

View file

@ -19,9 +19,6 @@
**/ **/
package com.raytheon.uf.viz.collaboration.ui.actions; package com.raytheon.uf.viz.collaboration.ui.actions;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.action.Action; import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IContributionItem;
@ -30,13 +27,13 @@ import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Menu;
import org.jivesoftware.smack.RosterEntry; import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
import com.raytheon.uf.viz.collaboration.comm.identity.event.RosterChangeType; import com.raytheon.uf.viz.collaboration.comm.identity.event.RosterChangeType;
import com.raytheon.uf.viz.collaboration.comm.provider.event.RosterChangeEvent; import com.raytheon.uf.viz.collaboration.comm.provider.event.RosterChangeEvent;
import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection; import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection;
import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager; 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.IDConverter;
import com.raytheon.uf.viz.collaboration.comm.provider.user.LocalGroups.LocalGroup;
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId; import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
import com.raytheon.uf.viz.collaboration.ui.Activator; import com.raytheon.uf.viz.collaboration.ui.Activator;
import com.raytheon.uf.viz.collaboration.ui.CreateGroupDialog; import com.raytheon.uf.viz.collaboration.ui.CreateGroupDialog;
@ -53,13 +50,13 @@ import com.raytheon.uf.viz.core.icon.IconUtil;
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jul 3, 2012 bsteffen Initial creation * Jul 3, 2012 bsteffen Initial creation
* Dec 20, 2013 2563 bclement added support for ungrouped roster entries * Dec 20, 2013 2563 bclement added support for ungrouped roster entries
* Jan 24, 2014 2701 bclement removed local groups
* *
* </pre> * </pre>
* *
* @author bsteffen * @author bsteffen
* @version 1.0 * @version 1.0
*/ */
public class AddToGroupAction extends Action { public class AddToGroupAction extends Action {
private final String group; private final String group;
@ -83,7 +80,7 @@ public class AddToGroupAction extends Action {
public AddToGroupAction(String group, UserId... users) { public AddToGroupAction(String group, UserId... users) {
super(group, IconUtil.getImageDescriptor(Activator.getDefault() super(group, IconUtil.getImageDescriptor(Activator.getDefault()
.getBundle(), "local_group.gif")); .getBundle(), "roster_group.gif"));
this.group = group; this.group = group;
this.users = users; this.users = users;
} }
@ -112,8 +109,7 @@ public class AddToGroupAction extends Action {
} }
CollaborationConnection connection = CollaborationConnection.getConnection(); CollaborationConnection connection = CollaborationConnection.getConnection();
for (UserId user : users) { for (UserId user : users) {
connection.getContactsManager() connection.getContactsManager().addToGroup(group, user);
.addToLocalGroup(group, user);
} }
if (entry != null) { if (entry != null) {
// the entry wasn't in a group, so the entire tree needs to be // the entry wasn't in a group, so the entire tree needs to be
@ -149,13 +145,7 @@ public class AddToGroupAction extends Action {
private void fill() { private void fill() {
ContactsManager contactsMgr = CollaborationConnection ContactsManager contactsMgr = CollaborationConnection
.getConnection().getContactsManager(); .getConnection().getContactsManager();
List<LocalGroup> groups = contactsMgr.getLocalGroups(); for (RosterGroup group : contactsMgr.getGroups()) {
List<LocalGroup> usedGroups = new ArrayList<LocalGroup>(groups);
for (UserId user : users) {
usedGroups.retainAll(contactsMgr.getLocalGroups(user));
}
groups.removeAll(usedGroups);
for (LocalGroup group : groups) {
AddToGroupAction action = new AddToGroupAction(group.getName(), AddToGroupAction action = new AddToGroupAction(group.getName(),
users); users);
action.setEntry(entry); action.setEntry(entry);

View file

@ -39,6 +39,7 @@ import com.raytheon.uf.viz.core.icon.IconUtil;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jul 3, 2012 bsteffen Initial creation * Jul 3, 2012 bsteffen Initial creation
* Jan 24, 2014 2701 bclement removed local groups
* *
* </pre> * </pre>
* *
@ -74,7 +75,7 @@ public class CreateGroupAction extends Action {
} }
for (UserId user : users) { for (UserId user : users) {
CollaborationConnection.getConnection().getContactsManager() CollaborationConnection.getConnection().getContactsManager()
.addToLocalGroup(group, user); .addToGroup(group, user);
} }
} }
} }

View file

@ -35,6 +35,7 @@ import com.raytheon.uf.viz.core.icon.IconUtil;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jul 3, 2012 bsteffen Initial creation * Jul 3, 2012 bsteffen Initial creation
* Jan 24, 2014 2701 bclement removed local groups
* *
* </pre> * </pre>
* *
@ -55,6 +56,6 @@ public class DeleteGroupAction extends Action {
@Override @Override
public void run() { public void run() {
CollaborationConnection.getConnection().getContactsManager() CollaborationConnection.getConnection().getContactsManager()
.deleteLocalGroup(group); .deleteGroup(group);
} }
} }

View file

@ -37,6 +37,7 @@ import com.raytheon.uf.viz.core.icon.IconUtil;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jul 3, 2012 bsteffen Initial creation * Jul 3, 2012 bsteffen Initial creation
* Jan 24, 2014 2701 bclement removed local groups
* *
* </pre> * </pre>
* *
@ -62,7 +63,7 @@ public class RemoveFromGroupAction extends Action {
ContactsManager manager = CollaborationConnection.getConnection() ContactsManager manager = CollaborationConnection.getConnection()
.getContactsManager(); .getContactsManager();
for (UserId user : users) { for (UserId user : users) {
manager.deleteFromLocalGroup(group, user); manager.deleteFromGroup(group, user);
} }
} }
} }

View file

@ -21,17 +21,10 @@ package com.raytheon.uf.viz.collaboration.ui.data;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection; import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection;
import com.raytheon.uf.viz.collaboration.comm.provider.session.RosterManager; import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager;
import com.raytheon.uf.viz.collaboration.comm.provider.user.LocalGroups.LocalGroup;
/** /**
* Container for collaboration information window. Includes current user, * Container for collaboration information window. Includes current user,
@ -45,6 +38,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.LocalGroups.LocalGro
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Apr 23, 2012 mnash Initial creation * Apr 23, 2012 mnash Initial creation
* Dec 20, 2013 2563 bclement added items from server roster not in groups * Dec 20, 2013 2563 bclement added items from server roster not in groups
* Jan 24, 2014 2701 bclement removed local groups, added shared groups
* *
* </pre> * </pre>
* *
@ -73,24 +67,10 @@ public class CollaborationGroupContainer {
List<Object> result = new ArrayList<Object>(); List<Object> result = new ArrayList<Object>();
result.add(connection.getUser()); result.add(connection.getUser());
result.add(sessionGroup); result.add(sessionGroup);
RosterManager rosterManager = connection.getRosterManager(); ContactsManager contactsManager = connection.getContactsManager();
Roster roster = rosterManager.getRoster(); result.addAll(contactsManager.getSharedGroups());
for (RosterGroup obj : roster.getGroups()) { result.addAll(contactsManager.getGroups());
result.add(obj); result.addAll(contactsManager.getNonGroupedContacts());
}
Set<String> usersInLocal = new HashSet<String>();
for (LocalGroup group : connection.getContactsManager()
.getLocalGroups()) {
usersInLocal.addAll(group.getUserNames());
result.add(group);
}
for (RosterEntry entry : roster.getUnfiledEntries()) {
// filter out entries that aren't in a group on the server, but are
// in a local group so they don't show up twice on the contacts list
if (!usersInLocal.contains(entry.getUser())) {
result.add(entry);
}
}
return result; return result;
} }

View file

@ -0,0 +1,9 @@
#!/bin/bash
echo "INFO: update started - removing collaboration local groups localization files"
find /awips2/edex/data/utility -type f -regex '.*collaboration/localGroups.xml$' -exec rm -vf {} \;
echo "INFO: the update has completed successfully!"
exit 0

View file

@ -12,6 +12,7 @@ Require-Bundle: org.apache.commons.beanutils;bundle-version="1.8.3",
Export-Package: com.raytheon.uf.common.util, Export-Package: com.raytheon.uf.common.util,
com.raytheon.uf.common.util.algorithm, com.raytheon.uf.common.util.algorithm,
com.raytheon.uf.common.util.cache, com.raytheon.uf.common.util.cache,
com.raytheon.uf.common.util.collections,
com.raytheon.uf.common.util.concurrent, com.raytheon.uf.common.util.concurrent,
com.raytheon.uf.common.util.file, com.raytheon.uf.common.util.file,
com.raytheon.uf.common.util.header, com.raytheon.uf.common.util.header,

View file

@ -0,0 +1,141 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.util.collections;
import java.util.Collection;
/**
* Manages a collection that is updated upon access if the time since last
* update is greater than a specified timeout. The user of the collection only
* needs to call the 'get' method to get a read-only collection without worrying
* about updating the collection themselves.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 23, 2014 2701 bclement Initial creation
*
* </pre>
*
* @author bclement
* @version 1.0
*/
public abstract class UpdatingCollection<C extends Collection<T>, T> {
private final long timeoutMillis;
private C collection;
private long lastUpdate;
private boolean enabled = true;
/**
* @param timeoutMillis
* timeout before new update in milliseconds
*/
public UpdatingCollection(long timeoutMillis) {
this.timeoutMillis = timeoutMillis;
}
/**
* Attempt to get timeout from system property
*
* @param timeoutProp
* system property name
* @param defaultTimeoutMillis
* default timeout before new update in milliseconds
*/
public UpdatingCollection(String timeoutProp, long defaultTimeoutMillis) {
this(Long.getLong(timeoutProp, defaultTimeoutMillis));
}
/**
* Update collection. This method will be called if the collection is not
* initialized or if the time since last update is greater than timeout. If
* this method returns null, the time used in the timeout check will not be
* updated and the get method will return an empty collection.
*
* @return null if there was a problem with update
*/
abstract protected C update();
/**
* Access the collection. The returned value is unmodifiable and guaranteed
* to not be null.
*
* @return
*/
public synchronized C get() {
if (!enabled) {
return collection != null ? collection : getEmpty();
}
C rval = collection;
long sinceLastUpdate = System.currentTimeMillis() - lastUpdate;
if (collection == null || sinceLastUpdate > timeoutMillis) {
rval = update();
if (rval != null) {
rval = collection = wrap(rval);
lastUpdate = System.currentTimeMillis();
} else {
rval = getEmpty();
}
}
return rval;
}
/**
* Wrap collection in unmodifiable collection.
*
* @return
*/
protected abstract C wrap(C collection);
/**
* @return an empty, unmodifiable collection
*/
protected abstract C getEmpty();
/**
* Prevent the collection from attempting to update.
*/
public synchronized void disable() {
this.enabled = false;
}
/**
* Allow the collection to attempt to update.
*/
public synchronized void enable() {
this.enabled = true;
}
/**
* @return the timeout in milliseconds
*/
public long getTimeout() {
return timeoutMillis;
}
}

View file

@ -0,0 +1,89 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.util.collections;
import java.util.Collections;
import java.util.Set;
/**
* Manages a set that is updated upon access if the time since last update is
* greater than a specified timeout. The user of the set only needs to call the
* 'get' method to get a read-only set without worrying about updating the set
* themselves.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 23, 2014 2701 bclement Initial creation
*
* </pre>
*
* @author bclement
* @version 1.0
*/
public abstract class UpdatingSet<T> extends UpdatingCollection<Set<T>, T> {
/**
* @see UpdatingCollection#UpdatingCollection(long)
* @param timeoutMillis
* timeout before new update in milliseconds
*/
public UpdatingSet(long timeoutMillis) {
super(timeoutMillis);
}
/**
* @see UpdatingCollection#UpdatingCollection(String, long)
* @param timeoutProp
* system property name
* @param defaultTimeoutMillis
* default timeout before new update in milliseconds
*/
public UpdatingSet(String timeoutProp, long defaultTimeoutMillis) {
super(timeoutProp, defaultTimeoutMillis);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.util.collections.UpdatingCollection#wrap(java.
* util.Collection)
*/
@Override
protected Set<T> wrap(Set<T> collection) {
return Collections.unmodifiableSet(collection);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.util.collections.UpdatingCollection#getEmpty()
*/
@Override
protected Set<T> getEmpty() {
return Collections.emptySet();
}
}