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, int matchFlags) { 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, int matchFlags){ 072 return withPattern(pattern,new int[]{matchFlags}); 073 } 074 075 protected boolean isInCaseSensitive(){ 076 return (patternFlag & Pattern.CASE_INSENSITIVE) != 0; 077 } 078 protected Pattern pattern() { 079 if(pattern.get() == null || !pattern.get().pattern().equals(patternStr)){ 080 pattern.set(Pattern.compile(checkNotNull(patternStr,"patternStr is uninitialized"),patternFlag)); 081 } 082 return pattern.get(); 083 } 084 085 public Function<String, String> getPatternFormater() { 086 return patternFormater; 087 } 088 089 public BaseStringMatchFilter setPatternFormater(Function<String, String> patternFormater) { 090 this.patternFormater = patternFormater; 091 return this; 092 } 093 094 } 095 096 public static class RegexFilter extends BaseFuzzyMatchFilter.BaseStringMatchFilter{ 097 @Override 098 public boolean apply(String input) { 099 try{ 100 return input == null 101 ? false 102 : pattern().matcher(input).matches(); 103 } catch (RuntimeException e) { 104 if(errorHandler != null){ 105 errorHandler.onMatchError(e, pattern().pattern()); 106 } 107 return false; 108 } 109 } 110 } 111 112 static class DefaultStringMatcher extends BaseFuzzyMatchFilter.BaseStringMatchFilter{ 113 private final Predicate<String> filter; 114 public DefaultStringMatcher(StringMatchType matchType) { 115 switch (checkNotNull(matchType,"matchType is null")) { 116 case CMP_LEFT_MATCH: 117 filter = new Predicate<String>() { 118 @Override 119 public boolean apply(String input) { 120 if(isInCaseSensitive()){ 121 input.toUpperCase().startsWith(pattern().pattern().toUpperCase()); 122 } 123 return input.startsWith(pattern().pattern()); 124 } 125 }; 126 break; 127 case CMP_RIGHT_MATCH: 128 filter = new Predicate<String>() { 129 130 @Override 131 public boolean apply(String input) { 132 if(isInCaseSensitive()){ 133 return input.toUpperCase().endsWith(pattern().pattern().toUpperCase()); 134 } 135 return input.endsWith(pattern().pattern()); 136 } 137 }; 138 break; 139 case CMP_MATCH: 140 filter = new Predicate<String>() { 141 142 @Override 143 public boolean apply(String input) { 144 if(isInCaseSensitive()){ 145 return input.toUpperCase().indexOf(pattern().pattern().toUpperCase())>=0; 146 } 147 return input.indexOf(pattern().pattern())>=0; 148 } 149 }; 150 break; 151 case EXACTLY_MATCH: 152 filter = new Predicate<String>() { 153 154 @Override 155 public boolean apply(String input) { 156 if(isInCaseSensitive()){ 157 return input.toUpperCase().equals(pattern().pattern().toUpperCase()); 158 } 159 return input.equals(pattern().pattern()); 160 } 161 }; 162 break; 163 default: 164 throw new IllegalArgumentException("UNSUPPORTED MatchType " + matchType); 165 } 166 } 167 168 @Override 169 public boolean apply(String input) { 170 try{ 171 return input == null 172 ? false 173 : filter.apply(input); 174 } catch (RuntimeException e) { 175 if(errorHandler != null){ 176 errorHandler.onMatchError(e, pattern().pattern()); 177 } 178 return false; 179 } 180 } 181 } 182}