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}