@Override
  public synchronized void unsubscribe(String item) throws SubscriptionException, FailureException {

    String val;
    if ((val = Constants.getVal(item, Constants.USER_SUBSCRIPTION)) != null) {
      logger.debug("User unsubscription: " + item);

      chat.stopUserMessageListen(val);

    } else if ((val = Constants.getVal(item, Constants.ROOMCHATLIST_SUBSCRIPTION)) != null) {
      logger.debug("Room list unsubscription: " + val);

      chat.stopRoomListen(val);

    } else if ((val = Constants.getVal(item, Constants.ROOMCHAT_SUBSCRIPTION)) != null) {
      logger.debug("Room chat unsubscription: " + val);

      chat.stopRoomChatListen(val);

    } else {
      logger.debug("User status unsubscription: " + item);

      chat.stopUserStatusListen(item);
    }
  }
  @Override
  public synchronized void subscribe(String item, Object handle, boolean needsIterator)
      throws SubscriptionException, FailureException {

    String val;
    if ((val = Constants.getVal(item, Constants.USER_SUBSCRIPTION)) != null) {
      // DISTINCT used only to signal presence
      logger.debug("User subscription: " + item);

      // user is created on subscription and destroyed on unsubscription
      chat.startUserMessageListen(val, handle);

    } else if ((val = Constants.getVal(item, Constants.ROOMCHATLIST_SUBSCRIPTION)) != null) {
      // COMMAND contains users of a certain room
      logger.debug("Room list subscription: " + val);

      chat.startRoomListen(
          val,
          handle); // will add the room if non-existent (room may exist if a user entered it even if
                   // no one is listening to it)

    } else if ((val = Constants.getVal(item, Constants.ROOMCHAT_SUBSCRIPTION)) != null) {
      // DISTINCT chat for the room
      logger.debug("Room chat subscription: " + val);

      chat.startRoomChatListen(val, handle);

    } else {
      // MERGE subscription for user status and nick + their commands and positions
      logger.debug("User status subscription: " + item);

      chat.startUserStatusListen(item, handle);
    }
  }