class HibernateSimpleQueryUtils {

    static List<Pair<Integer, Integer>> getReplaceableTermsOfQuery(String simpleQuery) {
        var termIndexPairs = new ArrayList<Pair<Integer, Integer>>();
        var queryCharCount = simpleQuery.length();

        var index = 0;
        while(index >= 0 && index < queryCharCount) {
            var currentChar = simpleQuery.charAt(index);

            // skip term delimiters
            if(TERM_DELIMITER.contains(currentChar)) {
                index++;
                continue;
            }

            // ignore phrase terms and near operators
            if(currentChar == '"') {
                index = getIndexAfterPhraseTerm(index, simpleQuery);
                continue;
            }

            var nextSpecialCharIndex = getIndexOfFirstAppearanceOfAny(index, SPECIAL_CHARACTERS, simpleQuery);
            var nextTermDelimiterIndex = getIndexOfFirstAppearanceOfAny(index, TERM_DELIMITER, simpleQuery);

            // no term delimiter found after the current term
            if(nextTermDelimiterIndex < 0) {
                nextTermDelimiterIndex = queryCharCount;
            }
            var termEndIndex = nextTermDelimiterIndex - 1;

            // when a term delimiter is present and the term is not a fuzzy or prefix term add
            // the pair -> ignore fuzzy and prefix terms
            var isSimpleTerm = nextSpecialCharIndex < 0 || nextTermDelimiterIndex < nextSpecialCharIndex;
            if(isSimpleTerm) {
                termIndexPairs.add(Pair.of(index, termEndIndex));

                index = nextTermDelimiterIndex + 1;
            } else {
                // skip this term
                index = getIndexAfterFirstAppearanceOfAny(nextSpecialCharIndex, TERM_DELIMITER, simpleQuery);
            }
        }

        return termIndexPairs;
    }

}