public void augmentOutboundStanzaWithFMUCData( @Nonnull Packet packet )
    {
        if ( !isRemoteFmuc() ) {
            Log.trace( "Recipient '{}' is not in a remote FMUC room. No need to augment stanza with FMUC data.", this.getUserAddress() );
            return;
        }
        Log.trace( "Sending data to recipient '{}' that has joined local room '{}' through a federated remote room (FMUC). Outbound stanza is required to include FMUC data: {}", this.getUserAddress(), this.getChatRoom().getJID(), packet );

        // Data that was sent to us from a(nother) FMUC node might already have this value. If not, we need to ensure that this is added.
        Element fmuc = packet.getElement().element(QName.get("fmuc", "http://isode.com/protocol/fmuc"));
        if ( fmuc == null )
        {
            fmuc = packet.getElement().addElement(QName.get("fmuc", "http://isode.com/protocol/fmuc"));
        }

        if ( fmuc.attributeValue( "from" ) != null && !fmuc.attributeValue( "from" ).trim().isEmpty() )
        {
            Log.trace( "Outbound stanza already includes FMUC data. No need to include further data." );
            return;
        }

        final JID reportingFmucAddress;
        if (packet.getFrom().getResource() == null) {
            Log.trace( "Sender is the room itself: '{}'", packet.getFrom() );
            reportingFmucAddress = this.getChatRoom().getSelfRepresentation().getOccupantJID();
        } else {
            Log.trace( "Sender is an occupant of the room: '{}'", packet.getFrom() );

            // Determine the occupant data of the entity that sent the message.
            final Set<MUCOccupant> senders = new HashSet<>();
            try
            {
                senders.addAll( this.getChatRoom().getOccupantsByNickname(packet.getFrom().getResource()) );
            }
            catch ( UserNotFoundException e )
            {
                Log.trace( "Unable to identify occupant '{}'", packet.getFrom() );
            }

            // If this user is joined through FMUC, use the FMUC-reported address, otherwise, use the local address.
            switch ( senders.size() )
            {
                case 0:
                    Log.warn("Cannot add required FMUC data to outbound stanza. Unable to determine the occupant data of the sender of stanza sent over FMUC: {}", packet);
                    return;

                case 1:
                    final MUCOccupant sender = senders.iterator().next();
                    if ( sender.isRemoteFmuc() ) {
                        reportingFmucAddress = sender.getReportedFmucAddress();
                    } else {
                        reportingFmucAddress = sender.getUserAddress();
                    }
                    break;

                default:
                    // The user has more than one occupant, which probably means it joined the room from more than one device.
                    // At this point in the code flow, we can't determine anymore which full JID caused the stanza to be sent.
                    // As a fallback, send the _bare_ JID of the user (which should be equal for all its resources).
                    // TODO verify if the compromise is acceptable in the XEP.
                    final Set<JID> bareJids = senders.stream()
                        .map(r -> {
                            if ( r.isRemoteFmuc() ) {
                                return r.getReportedFmucAddress().asBareJID();
                            } else {
                                return r.getUserAddress().asBareJID();
                            }
                        })
                        .collect(Collectors.toSet());

                    if ( bareJids.size() == 1 ) {
                        Log.warn("Sender '{}' has more than one occupant in room '{}', indicating that the user joined the room from more than one device. Using its bare instead of full JID for FMUC reporting.",
                            packet.getFrom(),
                            this.getChatRoom().getJID());
                        reportingFmucAddress = bareJids.iterator().next().asBareJID();
                    } else {
                        throw new IllegalStateException("Unable to deduce one FMUC address for occupant address '" + packet.getFrom() + "'.");
                    }
                    break;
            }
        }

        Log.trace( "Adding 'from' FMUC data to outbound stanza, using FMUC address of sender of data, that has been determined to be '{}'.", reportingFmucAddress );
        fmuc.addAttribute("from", reportingFmucAddress.toString() );
    }
When sending data to a user that joined the room through FMUC (when the user is a user that is local to a remote
chatroom that joined our room as a 'joining FMUC node'), then we'll need to add an 'fmuc' element to all data
that we send it.

The data that is to be added must include the 'from' address representing the FMUC role for the occupant that
sent the stanza. We either use the reported FMUC address as passed down from other FMUC nodes, or we use the
address of users connected locally to our server.

This method will add an 'fmuc' child element to the stanza when the user is a user that joined through FMUC (is
a member of a room that federates with the MUC room local to our server).

If the provided stanza already contains an FMUC element with relevant data, this data is left unchanged.

@param packet The stanza to augment
xmppserver/src/main/java/org/jivesoftware/openfire/muc/MUCOccupant.java