private void processNickNameChange(
        @Nonnull final Presence packet,
        @Nonnull final MUCRoom room,
        @Nonnull final MUCOccupant preExistingOccupantData,
        @Nonnull String nickname )
        throws UserNotFoundException
    {
        Log.trace("Occupant '{}' of room '{}' tries to change its nickname to '{}'.", preExistingOccupantData.getUserAddress(), room.getName(), nickname);

        if ( room.getOccupantsByBareJID(packet.getFrom().asBareJID()).isEmpty() )
        {
            Log.trace("Nickname change request denied: requestor '{}' is not an occupant of the room.", packet.getFrom().asBareJID());
            sendErrorPacket(packet, PacketError.Condition.not_acceptable, "You are not an occupant of this chatroom.");
            return;
        }

        if ( !room.canChangeNickname() )
        {
            Log.trace("Nickname change request denied: Room configuration does not allow nickname changes.");
            sendErrorPacket(packet, PacketError.Condition.not_acceptable, "Chatroom does not allow nickname changes.");
            return;
        }

        List<MUCOccupant> existingOccupants;
        try {
            existingOccupants = room.getOccupantsByNickname(nickname);
        } catch (UserNotFoundException e) {
            existingOccupants = Collections.emptyList();
        }

        if ( !existingOccupants.isEmpty() && !existingOccupants.stream().allMatch(r->r.getUserAddress().asBareJID().equals(preExistingOccupantData.getUserAddress().asBareJID())) )
        {
            Log.trace("Nickname change request denied: the requested nickname '{}' is used by another occupant of the room.", nickname);
            sendErrorPacket(packet, PacketError.Condition.conflict, "This nickname is taken.");
            return;
        }

        final JID memberBareJID = room.getMemberForReservedNickname(nickname);
        if (memberBareJID != null && !memberBareJID.equals(preExistingOccupantData.getUserAddress().asBareJID()))
        {
            Log.trace("Nickname change request denied: the requested nickname '{}' is reserved by a member of the room.", nickname);
            sendErrorPacket(packet, PacketError.Condition.conflict, "This nickname is taken.");
            return;
        }

        // Send "unavailable" presence for the old nickname
        final Presence presence = preExistingOccupantData.getPresence(); // This returns a copy. Modifications will not be applied to the original.
        // Switch the presence to OFFLINE
        presence.setType(Presence.Type.unavailable);
        presence.setStatus(null);
        // Add the new nickname and status 303 as properties
        final Element frag = presence.getChildElement("x", "http://jabber.org/protocol/muc#user");
        frag.element("item").addAttribute("nick", nickname);
        frag.addElement("status").addAttribute("code", "303");
        room.send(presence, preExistingOccupantData);

        // Send availability presence for the new nickname
        final String oldNick = preExistingOccupantData.getNickname();
        room.nicknameChanged(preExistingOccupantData, packet, oldNick, nickname);
    }
Process a request to change a nickname.

@param packet                  The stanza representing the nickname-change request.
@param room                    The room that the stanza was addressed to.
@param preExistingOccupantData The occupant data of this user in the addressed room prior to processing of this stanza.
@param nickname                The requested nickname.
xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl.java