Untitled
unknown
java
a year ago
3.9 kB
6
Indexable
Never
package pl.ds.util; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; import java.util.Collection; import java.util.stream.Stream; import static java.util.Objects.isNull; public final class StringUtil { private StringUtil() { // no instances } /** * <p>Checks if a {@code string} contains a {@code pattern}.</p> * * <p>A pattern may contain single or multiple wildcard characters {@code *}. * Each occurrence of {@code *} in the {@code pattern} means that it can be a match for * zero or more characters of the {@code string}.</p> * * <p>Asterisk (*) is considered as a regular character, if it is preceded by a backslash (\) * in a pattern. Backslash (\) is considered as a regular character in all cases other * than preceding the asterisk (*).</p> * * <p>Examples:</p> * <pre> * StringUtils.contains(null, *) = false * StringUtils.contains(*, null) = false * StringUtils.contains("", "") = true * StringUtils.contains("abc", "") = true * StringUtils.contains("abc", "a") = true * StringUtils.contains("abc", "a*") = true * StringUtils.contains("a*c", "a\*") = true * StringUtils.contains("a*c", "abc") = false * StringUtils.contains("abc", "A") = false * StringUtils.contains("abc", "abcd") = false * </pre> * * @param string string to check * @param pattern pattern to search in a string * @return true if the {@code string} contains a {@code pattern}, false otherwise. */ public static boolean contains(String string, String pattern) { if (isNull(string) || isNull(pattern) || pattern.length() > string.length()) { return false; } if (pattern.isEmpty()) { return true; } StringCharacterIterator stringIterator = new StringCharacterIterator(string); StringCharacterIterator patternIterator = new StringCharacterIterator(pattern); Collection<PatternComparator> comparators = new ArrayList<>(); do { char stringChar = stringIterator.current(); if (stringChar == patternIterator.first()) { comparators.add(new PatternComparator(pattern)); } if (comparators.stream().map(comparator -> comparator.pushCharacter(stringChar)).anyMatch(PatternComparator::isSuccess)) { return true; } else { comparators.removeIf(PatternComparator::isFailed); } } while (stringIterator.next() != CharacterIterator.DONE); return false; } private static class PatternComparator { private Status status; private enum Status {IN_PROGRESS, FAILED, SUCCESS;} private final StringCharacterIterator patternIterator; public PatternComparator(String pattern) { patternIterator = new StringCharacterIterator(pattern); status = Status.IN_PROGRESS; } private PatternComparator pushCharacter(char character) { if (status != Status.IN_PROGRESS) { return this; } if (patternIterator.current() == character) { if (endOfPattern()) { status = Status.SUCCESS; } else { patternIterator.next(); status = Status.IN_PROGRESS; } } else { status = Status.FAILED; } return this; } public boolean isSuccess() { return status == Status.SUCCESS; } public boolean isFailed() { return status == Status.FAILED; } private boolean endOfPattern() { return patternIterator.getIndex() + 1 == patternIterator.getEndIndex(); } } }