package com.github.ompc.greys.core.util.matcher; /** * 模版匹配 * Created by oldmanpushcart@gmail.com on 15/10/31. */ public class PatternMatcher implements Matcher<String> { /** * 匹配策略 */ public enum Strategy { /** * 通配符匹配 */ WILDCARD, /** * 正则表达式匹配 */ REGEX, /** * 字符串全匹配 */ EQUALS } // 匹配器 private final Matcher<String> matcher; /** * 正则/通配符匹配切换构造函数<br/> * 这个构造函数的出现主要是迎合Command中的使用需要 * * @param isRegex 是否正则表达式匹配 * @param pattern 匹配模版 */ public PatternMatcher(final boolean isRegex, final String pattern) { this(isRegex ? Strategy.REGEX : Strategy.WILDCARD, pattern); } /** * 通用构造函数 * * @param strategy 匹配策略 * @param pattern 匹配模版 */ public PatternMatcher(Strategy strategy, String pattern) { switch (strategy) { case WILDCARD: { this.matcher = new WildcardMatcher(pattern); break; } case REGEX: { this.matcher = new RegexMatcher(pattern); break; } case EQUALS: { this.matcher = new EqualsMatcher<String>(pattern); break; } default: { throw new IllegalArgumentException("unKnow strategy:" + strategy); } } } @Override public boolean matching(String target) { return matcher.matching(target); } /** * 正则表达式匹配 */ class RegexMatcher implements Matcher<String> { private final String pattern; public RegexMatcher(String pattern) { this.pattern = pattern; } @Override public boolean matching(String target) { return null != target && null != pattern && target.matches(pattern); } } /** * 通配符表达式匹配 */ class WildcardMatcher implements Matcher<String> { private final String pattern; public WildcardMatcher(String pattern) { this.pattern = pattern; } @Override public boolean matching(String target) { return match(target, pattern, 0, 0); } /** * Internal matching recursive function. */ private boolean match(String string, String pattern, int stringStartNdx, int patternStartNdx) { int pNdx = patternStartNdx; int sNdx = stringStartNdx; int pLen = pattern.length(); if (pLen == 1) { if (pattern.charAt(0) == '*') { // speed-up return true; } } int sLen = string.length(); boolean nextIsNotWildcard = false; while (true) { // check if end of string and/or pattern occurred if ((sNdx >= sLen)) { // end of string still may have pending '*' callback pattern while ((pNdx < pLen) && (pattern.charAt(pNdx) == '*')) { pNdx++; } return pNdx >= pLen; } if (pNdx >= pLen) { // end of pattern, but not end of the string return false; } char p = pattern.charAt(pNdx); // pattern char // perform logic if (!nextIsNotWildcard) { if (p == '\\') { pNdx++; nextIsNotWildcard = true; continue; } if (p == '?') { sNdx++; pNdx++; continue; } if (p == '*') { char pnext = 0; // next pattern char if (pNdx + 1 < pLen) { pnext = pattern.charAt(pNdx + 1); } if (pnext == '*') { // double '*' have the same effect as one '*' pNdx++; continue; } int i; pNdx++; // find recursively if there is any substring from the end of the // line that matches the rest of the pattern !!! for (i = string.length(); i >= sNdx; i--) { if (match(string, pattern, i, pNdx)) { return true; } } return false; } } else { nextIsNotWildcard = false; } // check if pattern char and string char are equals if (p != string.charAt(sNdx)) { return false; } // everything matches for now, continue sNdx++; pNdx++; } } } }