001package gu.sql2java; 002 003import static com.google.common.base.Preconditions.checkArgument; 004import static com.google.common.base.Preconditions.checkNotNull; 005 006import java.util.Objects; 007import java.util.regex.Pattern; 008 009import com.google.common.base.Function; 010import com.google.common.base.Predicate; 011import com.google.common.base.Strings; 012 013public abstract class BaseFuzzyMatchFilter<K> implements IFuzzyMatchFilter<K> { 014 015 protected MatchErrorHandler<K> errorHandler; 016 017 public BaseFuzzyMatchFilter() { 018 } 019 020 @Override 021 public IFuzzyMatchFilter<K> withErrorHandler(MatchErrorHandler<K> errorHandler) { 022 this.errorHandler = errorHandler; 023 return this; 024 } 025 static class DefaultFuzzyFilter<K> extends BaseFuzzyMatchFilter<K>{ 026 private K key; 027 @Override 028 public boolean apply(K input) { 029 return Objects.equals(key, input); 030 } 031 @Override 032 public IFuzzyMatchFilter<K> withPattern(K pattern) { 033 key = pattern; 034 return this; 035 } 036 } 037 038 /** 039 * 线程安全(thread safe)的模糊查询匹配接口实现基类 040 * @author guyadong 041 * 042 */ 043 public static abstract class BaseStringMatchFilter extends BaseFuzzyMatchFilter<String>implements IStringMatchFilter{ 044 private static final ThreadLocal<Pattern> pattern = new ThreadLocal<>(); 045 private String patternStr; 046 private Function<String, String> patternFormater; 047 private int patternFlag = 0; 048 049 @Override 050 public BaseStringMatchFilter withPattern(String pattern,int... flags) { 051 try{ 052 checkArgument(!Strings.isNullOrEmpty(pattern),"pattern is null or empty"); 053 this.patternStr = pattern; 054 if(patternFormater != null){ 055 patternStr = patternFormater.apply(pattern); 056 } 057 if(flags != null){ 058 for(int flag : flags){ 059 patternFlag |= flag; 060 } 061 } 062 return this; 063 } catch (RuntimeException e) { 064 if(errorHandler != null){ 065 errorHandler.onMatchError(e, pattern); 066 } 067 throw e; 068 } 069 } 070 @Override 071 public BaseStringMatchFilter withPattern(String pattern){ 072 return withPattern(pattern,new int[0]); 073 } 074 @Override 075 public BaseStringMatchFilter withPattern(String pattern,boolean inCaseSensitive){ 076 if(inCaseSensitive){ 077 return withPattern(pattern,Pattern.CASE_INSENSITIVE); 078 } 079 return withPattern(pattern); 080 } 081 082 protected boolean isInCaseSensitive(){ 083 return (patternFlag & Pattern.CASE_INSENSITIVE) != 0; 084 } 085 protected Pattern pattern() { 086 if(pattern.get() == null || !pattern.get().pattern().equals(patternStr)){ 087 pattern.set(Pattern.compile(checkNotNull(patternStr,"patternStr is uninitialized"),patternFlag)); 088 } 089 return pattern.get(); 090 } 091 092 public Function<String, String> getPatternFormater() { 093 return patternFormater; 094 } 095 096 public BaseStringMatchFilter setPatternFormater(Function<String, String> patternFormater) { 097 this.patternFormater = patternFormater; 098 return this; 099 } 100 101 } 102 103 public static class RegexFilter extends BaseFuzzyMatchFilter.BaseStringMatchFilter{ 104 @Override 105 public boolean apply(String input) { 106 try{ 107 return input == null 108 ? false 109 : pattern().matcher(input).matches(); 110 } catch (RuntimeException e) { 111 if(errorHandler != null){ 112 errorHandler.onMatchError(e, pattern().pattern()); 113 } 114 return false; 115 } 116 } 117 } 118 119 static class DefaultStringMatcher extends BaseFuzzyMatchFilter.BaseStringMatchFilter{ 120 private final Predicate<String> filter; 121 public DefaultStringMatcher(StringMatchType matchType) { 122 switch (checkNotNull(matchType,"matchType is null")) { 123 case CMP_LEFT_MATCH: 124 filter = new Predicate<String>() { 125 @Override 126 public boolean apply(String input) { 127 if(isInCaseSensitive()){ 128 input.toUpperCase().startsWith(pattern().pattern().toUpperCase()); 129 } 130 return input.startsWith(pattern().pattern()); 131 } 132 }; 133 break; 134 case CMP_RIGHT_MATCH: 135 filter = new Predicate<String>() { 136 137 @Override 138 public boolean apply(String input) { 139 if(isInCaseSensitive()){ 140 return input.toUpperCase().endsWith(pattern().pattern().toUpperCase()); 141 } 142 return input.endsWith(pattern().pattern()); 143 } 144 }; 145 break; 146 case CMP_MATCH: 147 filter = new Predicate<String>() { 148 149 @Override 150 public boolean apply(String input) { 151 if(isInCaseSensitive()){ 152 return input.toUpperCase().indexOf(pattern().pattern().toUpperCase())>=0; 153 } 154 return input.indexOf(pattern().pattern())>=0; 155 } 156 }; 157 break; 158 case EXACTLY_MATCH: 159 filter = new Predicate<String>() { 160 161 @Override 162 public boolean apply(String input) { 163 if(isInCaseSensitive()){ 164 return input.toUpperCase().equals(pattern().pattern().toUpperCase()); 165 } 166 return input.equals(pattern().pattern()); 167 } 168 }; 169 break; 170 default: 171 throw new IllegalArgumentException("UNSUPPORTED MatchType " + matchType); 172 } 173 } 174 175 @Override 176 public boolean apply(String input) { 177 try{ 178 return input == null 179 ? false 180 : filter.apply(input); 181 } catch (RuntimeException e) { 182 if(errorHandler != null){ 183 errorHandler.onMatchError(e, pattern().pattern()); 184 } 185 return false; 186 } 187 } 188 } 189}