public IQ handleIQ(IQ iq)
    {
        final IQ reply = IQ.createResultIQ(iq);
        final Element formElement = iq.getChildElement().element(
            QName.get("x", "jabber:x:data"));
        if (formElement == null)
        {
            reply.setChildElement(getDataElement());
            return reply;
        }

        // parse params from request.
        final DataForm df = new DataForm(formElement);
        boolean nameIsExactMatch = false;
        String subject = null;
        int numUsers = -1;
        int numMaxUsers = -1;
        boolean includePasswordProtectedRooms = true;

        final Set<String> names = new HashSet<>();
        for (final FormField field : df.getFields()) 
        {
            if (field.getVariable().equals("name"))
            {
                if (field.getFirstValue()!=null&& !field.getFirstValue().trim().isEmpty())
                {
                    names.add(field.getFirstValue());
                }
            }
        }

        final FormField matchFF = df.getField("name_is_exact_match");
        if (matchFF != null)
        {
            final String b = matchFF.getFirstValue();
            if (b != null)
            {
                nameIsExactMatch = b.equals("1")
                        || b.equalsIgnoreCase("true")
                        || b.equalsIgnoreCase("yes");
            }
        }

        final FormField subjectFF = df.getField(SUBJECT);
        if (subjectFF != null)
        {
            subject = subjectFF.getFirstValue();
        }

        try
        {
            final FormField userAmountFF = df.getField(NUM_USERS);
            if (userAmountFF != null)
            {
                String value = userAmountFF.getFirstValue();
                if (value != null && !value.isEmpty()) {
                    numUsers = Integer.parseInt(value);
                }
            }

            final FormField maxUsersFF = df.getField(NUM_MAX_USERS);
            if (maxUsersFF != null)
            {
                String value = maxUsersFF.getFirstValue();
                if (value != null && !value.isEmpty()) {
                    numMaxUsers = Integer.parseInt(value);
                }
            }
        }
        catch (NumberFormatException e)
        {
            reply.setError(PacketError.Condition.bad_request);
            return reply;
        }

        final FormField includePasswordProtectedRoomsFF = df.getField("include_password_protected");
        if (includePasswordProtectedRoomsFF != null)
        {
            final String b = includePasswordProtectedRoomsFF.getFirstValue();
            if (b != null)
            {
                try {
                    includePasswordProtectedRooms = DataForm.parseBoolean( b );
                } catch ( ParseException e ) {
                    reply.setError(PacketError.Condition.bad_request);
                    return reply;
                }
            }
        }

        // search for chatrooms matching the request params.
        final List<MUCRoomSearchInfo> mucs = new ArrayList<>();
        for (MUCRoomSearchInfo room : mucService.getAllRoomSearchInfo())
        {
            boolean find = false;

            if (!names.isEmpty())
            {
                for (final String name : names)
                {
                    if (nameIsExactMatch)
                    {
                        if (name.equalsIgnoreCase(room.getNaturalLanguageName()))
                        {
                            find = true;
                            break;
                        }
                    }
                    else
                    {
                        if (room.getNaturalLanguageName().toLowerCase().contains(name.toLowerCase()))
                        {
                            find = true;
                            break;
                        }
                    }
                }
            }

            if (subject != null && !subject.trim().isEmpty()
                    && room.getSubject().toLowerCase().contains(subject.toLowerCase()))
            {
                find = true;
            }

            if (numUsers > -1 && room.getParticipantCount() < numUsers)
            {
                find = false;
            }

            if (numMaxUsers > -1 && room.getMaxUsers() < numMaxUsers)
            {
                find = false;
            }

            if (!includePasswordProtectedRooms && room.isPasswordProtected())
            {
                find = false;
            }

            if (find && canBeIncludedInResult(room))
            {
                mucs.add(room);
            }
        }

        final ResultSet<MUCRoomSearchInfo> searchResults = new ResultSetImpl<>(
            sortByUserAmount(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)
        {
            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.
            mucrsm = new ArrayList<>(searchResults);
        }

        final Element res = DocumentHelper.createElement(QName.get("query",
            JABBER_IQ_SEARCH));

        final DataForm resultform = new DataForm(DataForm.Type.result);
        boolean atLeastoneResult = false;
        for (MUCRoomSearchInfo room : mucrsm)
        {
            final Map<String, Object> fields = new HashMap<>();
            fields.put("name", room.getNaturalLanguageName());
            fields.put(SUBJECT, room.getSubject());
            fields.put(NUM_USERS, room.getOccupantsCount());
            fields.put(NUM_MAX_USERS, determineMaxUsersDisplay(room.getMaxUsers()));
            fields.put("is_password_protected", room.isPasswordProtected());
            fields.put("is_member_only", room.isMembersOnly());
            fields.put("jid", room.getJID().toString());
            resultform.addItemFields(fields);
            atLeastoneResult = true;
        }
        if (atLeastoneResult)
        {
            resultform.addReportedField("name", "Name", FormField.Type.text_single);
            resultform.addReportedField(SUBJECT, "Subject", FormField.Type.text_single);
            resultform.addReportedField(NUM_USERS, "Number of users", FormField.Type.text_single);
            resultform.addReportedField(NUM_MAX_USERS, "Max number allowed of users", FormField.Type.text_single);
            resultform.addReportedField("is_password_protected", "Is a password protected room.", FormField.Type.boolean_type);
            resultform.addReportedField("is_member_only", "Is a member only room.", FormField.Type.boolean_type);
            resultform.addReportedField("jid", "JID", FormField.Type.jid_single);
        }
                res.add(resultform.getElement());
        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/IQMUCSearchHandler.java