/**
   * Adds a registration with this transport, or updates an existing one.
   *
   * @param jid JID of user to add registration to.
   * @param username Legacy username of registration.
   * @param password Legacy password of registration.
   * @param nickname Legacy nickname of registration.
   * @param noRosterItem True if the transport is not to show up in the user's roster.
   * @throws UserNotFoundException if registration or roster not found.
   * @throws IllegalAccessException if jid is not from this server.
   * @throws IllegalArgumentException if username is not valid for this transport type.
   */
  public void addNewRegistration(
      JID jid, String username, String password, String nickname, Boolean noRosterItem)
      throws UserNotFoundException, IllegalAccessException {
    Log.debug("Adding or updating registration for : " + jid.toString() + " / " + username);

    if (!XMPPServer.getInstance().isLocal(jid)) {
      throw new IllegalAccessException(
          "Domain of jid registering does not match domain of server.");
    }

    if (!parent.isUsernameValid(username)) {
      throw new IllegalArgumentException(
          "Username specified is not valid for this transport type.");
    }

    final Collection<Registration> registrations =
        RegistrationManager.getInstance().getRegistrations(jid, parent.transportType);
    boolean foundReg = false;
    boolean triggerRestart = false;
    for (final Registration registration : registrations) {
      if (!registration.getUsername().equals(username)) {
        Log.debug("Deleting existing registration before" + " creating a new one: " + registration);
        RegistrationManager.getInstance().deleteRegistration(registration);
      } else {
        Log.debug("Existing registration found that can be updated: " + registration);
        if ((registration.getPassword() != null && password == null)
            || (registration.getPassword() == null && password != null)
            || (registration.getPassword() != null
                && password != null
                && !registration.getPassword().equals(password))) {
          Log.debug("Updating password for existing registration: " + registration);
          registration.setPassword(password);
          triggerRestart = true;
        }
        if ((registration.getNickname() != null && nickname == null)
            || (registration.getNickname() == null && nickname != null)
            || (registration.getNickname() != null
                && nickname != null
                && !registration.getNickname().equals(nickname))) {
          Log.debug("Updating nickname for existing registration: " + registration);
          registration.setNickname(nickname);
          triggerRestart = true;
        }
        foundReg = true;
      }

      // if a change was made to the registration, restart it.
      if (triggerRestart) {
        try {
          Log.debug(
              "An existing registration was "
                  + "updated. Restarting the related session: "
                  + registration);
          final TransportSession relatedSession =
              parent.sessionManager.getSession(registration.getJID().getNode());
          parent.registrationLoggedOut(relatedSession);
        } catch (NotFoundException e) {
          // No worries, move on.
        }
      }
    }

    if (!foundReg) {
      RegistrationManager.getInstance()
          .createRegistration(jid, parent.transportType, username, password, nickname);
      triggerRestart = true;
    }

    if (triggerRestart) {
      Log.debug("Clean up any leftover roster items " + "from other transports for: " + jid);
      try {
        parent.cleanUpRoster(jid, !noRosterItem);
      } catch (UserNotFoundException ee) {
        throw new UserNotFoundException("Unable to find roster.");
      }
    }

    if (!noRosterItem) {
      try {
        Log.debug("Adding Transport roster item to the roster of: " + jid);
        parent.addOrUpdateRosterItem(jid, parent.getJID(), parent.getDescription(), "Transports");
      } catch (UserNotFoundException e) {
        throw new UserNotFoundException("User not registered with server.");
      }
    } else {
      Log.debug(
          "Not adding Transport roster item to the roster of: "
              + jid
              + " (as this was explicitly requested).");
    }
  }