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}