package pl.radical.open.gg;
import pl.radical.open.gg.event.LoginListener;
import pl.radical.open.gg.event.UserListener;
import pl.radical.open.gg.packet.GGOutgoingPackage;
import pl.radical.open.gg.packet.dicts.SessionState;
import pl.radical.open.gg.packet.dicts.StatusType;
import pl.radical.open.gg.packet.out.GGAddNotify;
import pl.radical.open.gg.packet.out.GGListEmpty;
import pl.radical.open.gg.packet.out.GGNewStatus;
import pl.radical.open.gg.packet.out.GGNotify;
import pl.radical.open.gg.packet.out.GGRemoveNotify;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* The implementation of <code>IPresenceService</code>.
* <p>
* Created on 2004-11-28
*
* @author <a href="mailto:mati@sz.home.pl">Mateusz Szczap</a>
*/
public class DefaultPresenceService implements IPresenceService {
/**
* Set of listeners that will be notified of user related events
*/
private final Set<UserListener> userListeners = new HashSet<UserListener>();
/**
* The session associated with this service
*/
private Session session = null;
/**
* The actual status
*/
private ILocalStatus localStatus = new LocalStatus(StatusType.OFFLINE);
/**
* The set of users that are monitored
*/
private Collection<IUser> monitoredUsers = new HashSet<IUser>();
// friendly
DefaultPresenceService(final Session session) {
if (session == null) {
throw new IllegalArgumentException("session cannot be null");
}
this.session = session;
session.getLoginService().addLoginListener(new LoginHandler());
}
/**
* @see pl.radical.open.gg.IPresenceService#setStatus(pl.radical.open.gg.ILocalStatus)
*/
public void setStatus(final ILocalStatus localStatus) throws GGException {
if (localStatus == null) {
throw new IllegalArgumentException("status cannot be null");
}
checkSessionState();
try {
final GGNewStatus newStatus = new GGNewStatus(localStatus);
session.getSessionAccessor().sendPackage(newStatus);
this.localStatus = localStatus;
notifyLocalUserChangedStatus(this.localStatus);
} catch (final IOException ex) {
throw new GGException("Unable to set status: " + localStatus, ex);
}
}
/**
* @see pl.radical.open.gg.IPresenceService#getStatus()
*/
public ILocalStatus getStatus() {
return localStatus;
}
/**
* @see pl.radical.open.gg.IPresenceService#addMonitoredUser(pl.radical.open.gg.IUser)
*/
public void addMonitoredUser(final IUser user) throws GGException {
if (user == null) {
throw new IllegalArgumentException("user cannot be null");
}
checkSessionState();
if (monitoredUsers.contains(user)) {
return;
}
try {
final GGAddNotify addNotify = new GGAddNotify(user.getUin(), user.getUserMode());
session.getSessionAccessor().sendPackage(addNotify);
monitoredUsers.add(user);
} catch (final IOException ex) {
throw new GGException("Error occured while adding user to be monitored.", ex);
}
}
/**
* @see pl.radical.open.gg.IPresenceService#removeMonitoredUser(pl.radical.open.gg.IUser)
*/
public void removeMonitoredUser(final IUser user) throws GGException {
if (user == null) {
throw new IllegalArgumentException("user cannot be null");
}
checkSessionState();
if (!monitoredUsers.contains(user)) {
throw new GGException("User: " + user + "+ is not monitored");
}
try {
final GGRemoveNotify removeNotify = new GGRemoveNotify(user.getUin(), user.getUserMode());
session.getSessionAccessor().sendPackage(removeNotify);
monitoredUsers.remove(user);
} catch (final IOException ex) {
throw new GGException("Unable to remove monitored user", ex);
}
}
/**
* @see pl.radical.open.gg.IPresenceService#changeMonitoredUserStatus(pl.radical.open.gg.IUser)
*/
public void changeMonitoredUserStatus(final IUser user) throws GGException {
if (user == null) {
throw new IllegalArgumentException("user cannot be null");
}
checkSessionState();
if (!monitoredUsers.contains(user)) {
throw new GGException("User: " + user + "+ is not monitored");
}
try {
final GGRemoveNotify removeNotify = new GGRemoveNotify(user.getUin(), user.getUserMode());
session.getSessionAccessor().sendPackage(removeNotify);
final GGAddNotify addNotify = new GGAddNotify(user.getUin(), user.getUserMode());
session.getSessionAccessor().sendPackage(addNotify);
} catch (final IOException ex) {
throw new GGException("Unable to remove monitored user", ex);
}
}
/**
* @see pl.radical.open.gg.IPresenceService#getMonitoredUsers()
*/
public Collection<IUser> getMonitoredUsers() {
if (session.getSessionState() != SessionState.LOGGED_IN) {
return Collections.emptySet();
}
if (monitoredUsers.isEmpty()) {
return Collections.emptySet();
} else {
return Collections.unmodifiableCollection(monitoredUsers);
}
}
/**
* @see pl.radical.open.gg.IPresenceService#addUserListener(pl.radical.open.gg.event.UserListener)
*/
public void addUserListener(final UserListener userListener) {
if (userListener == null) {
throw new IllegalArgumentException("userListener cannot be null");
}
userListeners.add(userListener);
}
/**
* @see pl.radical.open.gg.IPresenceService#removeUserListener(pl.radical.open.gg.event.UserListener)
*/
public void removeUserListener(final UserListener userListener) {
if (userListener == null) {
throw new IllegalArgumentException("userListener cannot be null");
}
userListeners.remove(userListener);
}
protected void notifyUserChangedStatus(final IUser user, final IRemoteStatus newStatus) throws GGException {
if (user == null) {
throw new IllegalArgumentException("user cannot be null");
}
if (newStatus == null) {
throw new IllegalArgumentException("newStatus cannot be null");
}
for (final Object element : userListeners) {
final UserListener userListener = (UserListener) element;
userListener.userStatusChanged(user, newStatus);
}
}
protected void notifyLocalUserChangedStatus(final ILocalStatus localStatus) throws GGException {
if (localStatus == null) {
throw new IllegalArgumentException("localStatus cannot be null");
}
for (final Object element : userListeners) {
final UserListener userListener = (UserListener) element;
userListener.localStatusChanged(localStatus);
}
}
private void checkSessionState() throws GGSessionException {
if (session.getSessionState() != SessionState.LOGGED_IN) {
throw new GGSessionException(session.getSessionState());
}
}
private class LoginHandler extends LoginListener.Stub {
/**
* @see pl.radical.open.gg.event.LoginListener#loginOK()
*/
@Override
public void loginOK() throws GGException {
localStatus = session.getLoginService().getLoginContext().getStatus();
monitoredUsers = session.getLoginService().getLoginContext().getMonitoredUsers();
setStatus(localStatus);
GGOutgoingPackage outgoingPackage;
if (monitoredUsers.isEmpty()) {
outgoingPackage = GGListEmpty.getInstance();
} else {
final IUser[] users = monitoredUsers.toArray(IUser.EMPTY_ARRAY);
outgoingPackage = new GGNotify(users);
}
try {
session.getSessionAccessor().sendPackage(outgoingPackage);
} catch (final IOException ex) {
throw new GGException("Unable to send initial list of users to monitor", ex);
}
}
}
}