package com.firefly.utils.pattern; import com.firefly.utils.StringUtils; public abstract class Pattern { private static final AllMatch ALL_MATCH = new AllMatch(); /** * Matches a string according to the specified pattern * @param str Target string * @return If it returns null, that represents matching failure, * else it returns an array contains all strings are matched. */ abstract public String[] match(String str); public static Pattern compile(String pattern, String wildcard) { final boolean startWith = pattern.startsWith(wildcard); final boolean endWith = pattern.endsWith(wildcard); final String[] array = StringUtils.split(pattern, wildcard); switch (array.length) { case 0: return ALL_MATCH; case 1: if (startWith && endWith) return new HeadAndTailMatch(array[0]); if (startWith) return new HeadMatch(array[0]); if (endWith) return new TailMatch(array[0]); return new EqualsMatch(pattern); default: return new MultipartMatch(startWith, endWith, array); } } private static class MultipartMatch extends Pattern { private final boolean startWith, endWith; private final String[] parts; private int num; public MultipartMatch(boolean startWith, boolean endWith, String[] parts) { super(); this.startWith = startWith; this.endWith = endWith; this.parts = parts; num = parts.length - 1; if(startWith) num++; if(endWith) num++; } @Override public String[] match(String str) { int currentIndex = -1; int lastIndex = -1; String[] ret = new String[num]; for (int i = 0; i < parts.length; i++) { String part = parts[i]; int j = startWith ? i : i - 1; currentIndex = str.indexOf(part, lastIndex + 1); if (currentIndex > lastIndex) { if(i != 0 || startWith) ret[j] = str.substring(lastIndex + 1, currentIndex); lastIndex = currentIndex + part.length() - 1; continue; } return null; } if(endWith) ret[num - 1] = str.substring(lastIndex + 1); return ret; } } private static class TailMatch extends Pattern { private final String part; public TailMatch(String part) { this.part = part; } @Override public String[] match(String str) { int currentIndex = str.indexOf(part); if(currentIndex == 0) { return new String[] { str.substring(part.length()) }; } return null; } } private static class HeadMatch extends Pattern { private final String part; public HeadMatch(String part) { this.part = part; } @Override public String[] match(String str) { int currentIndex = str.indexOf(part); if(currentIndex + part.length() == str.length()) { return new String[] { str.substring(0, currentIndex) }; } return null; } } private static class HeadAndTailMatch extends Pattern { private final String part; public HeadAndTailMatch(String part) { this.part = part; } @Override public String[] match(String str) { int currentIndex = str.indexOf(part); if(currentIndex >= 0) { String[] ret = new String[]{str.substring(0, currentIndex), str.substring(currentIndex + part.length(), str.length()) }; return ret; } return null; } } private static class EqualsMatch extends Pattern { private final String pattern; public EqualsMatch(String pattern) { this.pattern = pattern; } @Override public String[] match(String str) { return pattern.equals(str) ? new String[0] : null; } } private static class AllMatch extends Pattern { @Override public String[] match(String str) { return new String[]{str}; } } }