private void makeRemoteOccupantJoinRoom( @Nonnull final Presence presence )
    {
        // FIXME: better input validation / better problem handling when remote node sends crappy data!
        final Element mucUser = presence.getElement().element(QName.get("x","http://jabber.org/protocol/muc#user"));
        final Element fmuc = presence.getElement().element(FMUC);
        if ( fmuc == null ) {
            throw new IllegalArgumentException( "Argument 'presence' should be an FMUC presence, but it does not appear to be: it is missing the FMUC child element." );
        }

        final JID remoteMUC = presence.getFrom().asBareJID();
        final String nickname = presence.getFrom().getResource();

        Log.debug( "(room: '{}'): Occupant on remote peer '{}' joins the room with nickname '{}'.", room.getJID(), remoteMUC, nickname );

        Role role;
        if ( mucUser != null && mucUser.element("item") != null && mucUser.element("item").attributeValue("role") != null ) {
            try {
                role = Role.valueOf(mucUser.element("item").attributeValue("role"));
            } catch ( IllegalArgumentException e ) {
                Log.info( "Cannot parse role as received in FMUC join, using default role instead: {}", presence, e );
                role = Role.participant;
            }
        } else {
            Log.info( "Cannot parse role as received in FMUC join, using default role instead: {}", presence );
            role = Role.participant;
        }

        Affiliation affiliation;
        if ( mucUser != null && mucUser.element("item") != null && mucUser.element("item").attributeValue("affiliation") != null ) {
            try {
                affiliation = Affiliation.valueOf(mucUser.element("item").attributeValue("affiliation"));
            } catch ( IllegalArgumentException e ) {
                Log.info( "Cannot parse affiliation as received in FMUC join, using default role instead: {}", presence, e );
                affiliation = Affiliation.none;
            }
        } else {
            Log.info( "Cannot parse affiliation as received in FMUC join, using default role instead: {}", presence );
            affiliation = Affiliation.none;
        }

        final JID userJID = getFMUCFromJID( presence );

        final MUCOccupant joinOccupantData = new MUCOccupant(room, nickname, role, affiliation, userJID, createCopyWithoutFMUC(presence));

        joinOccupantData.setReportedFmucAddress( userJID );

        final boolean clientOnlyJoin = room.alreadyJoinedWithThisNick( userJID, nickname );
        if (clientOnlyJoin)
        {
            Log.warn( "(room: '{}'): Ignoring join of occupant on remote peer '{}' with nickname '{}' as this user is already in the room.", room.getJID(), remoteMUC, nickname );
        }
        else
        {
            // Update the (local) room state to now include this occupant.
            room.addOccupant(joinOccupantData);

            // Send out presence stanzas that signal all other occupants that this occupant has now joined. Unlike a 'regular' join we MUST
            // _not_ sent back presence for all other occupants (that has already been covered by the FMUC protocol implementation).
            room.sendInitialPresenceToExistingOccupants(joinOccupantData);
        }
    }
Processes a presence stanza that is expected to be an FMUC-flavored 'room join' representation, and adds the
remote user to the room.

This method will <em>not</em> make modifications to the state of the FMUC node set. It expects those changes to
be taken care of by the caller.

This method provides the functionally opposite implementation of {@link #makeRemoteOccupantLeaveRoom(Presence)}.

@param presence The stanza representing a user on a federated FMUC node joining the room (cannot be null).
@see #makeRemoteOccupantLeaveRoom(Presence)
xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/FMUCHandler.java