public IQ handleIQ( IQ iq )
    {
        Log.trace( "Received request: {}", iq );

        final IQ reply = IQ.createResultIQ( iq );
        if ( !PROPERTY_ENABLED.getValue() )
        {
            Log.debug( "Unable to process request: service has been disabled by configuration." );
            reply.setError( Condition.service_unavailable );
            return reply;
        }

        final Element formElement = iq.getChildElement().element( QName.get( "x", "jabber:x:data" ) );
        if ( formElement == null )
        {
            Log.debug( "Responding with a fresh search form." );
            reply.setChildElement( getDataElement() );
            return reply;
        }

        // Parse params from request.
        final SearchParameters params;
        try
        {
            params = parseSearchParameters( formElement );
        }
        catch ( IllegalArgumentException | ParseException e )
        {
            Log.debug( "Unable to parse search parameters from request.", e );
            reply.setError( Condition.bad_request );
            return reply;
        }

        // Search for chatrooms matching the request params.
        List<MUCRoomSearchInfo> mucs = searchForChatrooms( params );

        mucs = switch (params.getKey()) {
            case nusers  -> sortByUserAmount(mucs);
            case address -> sortByAddress(mucs);
        };

        final ResultSet<MUCRoomSearchInfo> searchResults = new ResultSetImpl<>( mucs );

        // See if the requesting entity would like to apply 'result set management'
        final Element set = iq.getChildElement().element( QName.get( "set", ResultSet.NAMESPACE_RESULT_SET_MANAGEMENT ) );
        final List<MUCRoomSearchInfo> mucrsm;

        // apply RSM only if the element exists, and the (total) results set is not empty.
        final boolean applyRSM = set != null && !mucs.isEmpty();

        if ( applyRSM )
        {
            Log.trace( "Applying RSM" );
            if ( !ResultSet.isValidRSMRequest( set ) )
            {
                reply.setError( Condition.bad_request );
                return reply;
            }

            try
            {
                mucrsm = searchResults.applyRSMDirectives( set );
            }
            catch ( NullPointerException e )
            {
                final IQ itemNotFound = IQ.createResultIQ( iq );
                itemNotFound.setError( Condition.item_not_found );
                return itemNotFound;
            }
        }
        else
        {
            // if no rsm, all found rooms are part of the result.
            Log.trace( "Not applying RSM" );
            mucrsm = new ArrayList<>( searchResults );
        }

        final Element res = generateResultElement( mucrsm );

        if ( applyRSM )
        {
            res.add( searchResults.generateSetElementFromResults( mucrsm ) );
        }

        reply.setChildElement( res );

        return reply;
    }
Constructs an answer on a IQ stanza that contains a search request. The
answer will be an IQ stanza of type 'result' or 'error'.

@param iq The IQ stanza that is the search request.
@return An answer to the provided request.
xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/IQMuclumbusSearchHandler.java