Java tutorial
/** This file is part of Adguard Content Blocker (https://github.com/AdguardTeam/ContentBlocker). Copyright 2016 Performix LLC. All rights reserved. Adguard Content Blocker is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Adguard Content Blocker is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Adguard Content Blocker. If not, see <http://www.gnu.org/licenses/>. */ package com.adguard.commons.lang; import org.apache.commons.lang3.StringUtils; import java.util.regex.Pattern; /** * Represents a wildcard */ public class Wildcard { private final int regexpOptions; private final Pattern regexp; private final String shortcut; /** * Initializes a wildcard with the given pattern. * * @param pattern Pattern */ public Wildcard(String pattern) { this(pattern, Pattern.CASE_INSENSITIVE); } /** * Initializes a wildcard with the given search pattern and options. * * @param pattern Wildcard pattern * @param regexpOptions Regexp options */ public Wildcard(String pattern, int regexpOptions) { this.regexpOptions = regexpOptions; regexp = Pattern.compile(wildcardToRegex(pattern), regexpOptions); shortcut = extractShortcut(pattern); } /** * Gets wildcard shortcut * * @return Wildcard shortcut */ String getShortcut() { return shortcut; } /** * Returns "true" if input text is matching wildcard. * This method first checking shortcut -- if shortcut exists in input string -- than it checks regexp. * * @param input Input string * @return true if input string matches wildcard */ public boolean matches(String input) { if (StringUtils.isEmpty(input)) { return false; } boolean matchCase = ((regexpOptions & Pattern.CASE_INSENSITIVE) == Pattern.CASE_INSENSITIVE); if (matchCase && !StringUtils.contains(input, shortcut)) { return false; } if (!matchCase && !StringUtils.containsIgnoreCase(input, shortcut)) { return false; } return regexp.matcher(input).matches(); } /** * Converts wildcard to regular expression * * @param pattern The wildcard pattern to convert * @return A regex equivalent of the given wildcard */ private static String wildcardToRegex(String pattern) { return "^" + StringUtils.replaceEach(escapeRegexp(pattern), new String[] { "\\*", "\\?" }, new String[] { ".*", "." }) + "$"; } /** * Escapes regexp special characters: \, *, +, ?, |, {, [, (,), ^, $,., #, and white space * * @param pattern Pattern to escape * @return Escaped pattern */ private static String escapeRegexp(String pattern) { String[] specialCharacters = new String[] { "\\", "*", "+", "?", "|", "{", "[", "(", ")", "^", "$", ".", "#" }; String[] escapedCharacters = new String[] { "\\\\", "\\*", "\\+", "\\?", "\\|", "\\{", "\\[", "\\(", "\\)", "\\^", "\\$", "\\.", "\\#" }; return StringUtils.replaceEach(pattern, specialCharacters, escapedCharacters); } /** * Extracts longest string that does not contain * or ? symbols. * * @param pattern Wildcard pattern * @return Longest string without special symbols */ private static String extractShortcut(String pattern) { char[] wildcardChars = new char[] { '*', '?' }; int startIndex = 0; int endIndex = StringUtils.indexOfAny(pattern, wildcardChars); if (endIndex < 0) { return pattern; } String shortcut = endIndex == startIndex ? StringUtils.EMPTY : pattern.substring(startIndex, endIndex - startIndex); while (endIndex >= 0) { startIndex = startIndex + endIndex + 1; if (pattern.length() <= startIndex) { break; } endIndex = StringUtils.indexOfAny(pattern.substring(startIndex), wildcardChars); String tmpShortcut = endIndex < 0 ? pattern.substring(startIndex) : pattern.substring(startIndex, endIndex + startIndex); if (tmpShortcut.length() > shortcut.length()) { shortcut = tmpShortcut; } } return shortcut; } @Override public String toString() { return regexp.toString(); } }