@NotNull
    private static Predicate<String> createSeparatedWordBoundaryPredicate(
            final String userInput,
            final Pattern separatorCharacterClass) {

        // Has some uppercase so use word boundaries
        // An upper case letter means the start of a word
        // a lower case letter means the continuation of a word
        // A digit after a letter means the start of a word
        // A digit after a digit means the continuation of a word.

        final String separator = "\\W";

        final StringBuilder patternBuilder = new StringBuilder();
        char lastChr = 0;
        for (int i = 0; i < userInput.length(); i++) {
            char chr = userInput.charAt(i);

            if (Character.isUpperCase(chr)
                || (Character.isDigit(chr) && Character.isLetter(lastChr))) {
                if (i == 0) {
                    // First letter so is either preceded by ^ or by a separator
                    patternBuilder
                            .append("(?:^|") // non-capturing
                            .append(separator)
                            .append("+")
                            .append(")");
                } else {
                    // Not the first letter so need the end of the previous word
                    // and a word separator
                    patternBuilder
//                            .append(CASE_INSENS_WORD_LETTER_CHAR_CLASS)
                            .append(".*?")
                            .append(separator)
                            .append("+"); // one of more separators
                }
                // Start of a word
            }

            if (Character.isLetterOrDigit(chr)) {
                patternBuilder.append(chr);
            } else {
                // Might be a special char so escape it
                patternBuilder.append(Pattern.quote(String.valueOf(chr)));
            }
            lastChr = chr;
        }
        final Pattern pattern = Pattern.compile(
                patternBuilder.toString(), Pattern.CASE_INSENSITIVE);
        LOGGER.trace("Using separated word pattern: {} with separators {}",
                pattern, separator);

        return pattern.asPredicate();
    }
For a given user input this method will return a function that can evaluate a string to see how
good the match is. The quality of the match is determined by the length of the matched region
(shorter == better) and its distance from the start of the string (closer == better).
stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/StringPredicateFactory.java