001package gu.sql2java;
002
003import com.google.common.base.Function;
004
005/**
006 * 字符串模糊匹配类型
007 * @author guyadong
008 *
009 */
010public enum StringMatchType implements Function<String, String>{
011        /**
012         * 精确匹配,
013         * 比较字符串是否与pattern完全相等
014         */
015        EXACTLY_MATCH, 
016        /**
017         * 字符串比较匹配,
018         * 比较字符串是否以pattern起始,如 'hello' 匹配 'hello,world'
019         */
020        CMP_LEFT_MATCH,
021        /**
022         * 字符串比较匹配,
023         * 比较字符串是否以pattern结尾,如 'world' 匹配 'hello,world'
024         */
025        CMP_RIGHT_MATCH,
026        /**
027         * 字符串比较匹配,
028         * 比较字符串是否包含pattern,如 'wo' 匹配 'hello,world'
029         */
030        CMP_MATCH,
031        /**
032         * 支持通配符的字符串比较匹配
033         * pattern中允许包含通配符('*','?'),'*'匹配任意0或多个字符,'?'匹配任意单个字符
034         * 比较字符串是否包含pattern,如 '1*2房' 匹配 '1032房间',匹配'10楼/32房间','1?2'匹配'1楼2单元','1?2房'不匹配'1032房间'
035         */
036        WILDCARD_MATCH,
037        /**
038         * 数字模糊匹配
039         * pattern必须全部为数字,
040         * 比较字符串中所有数字组成的字符串是否包含pattern数字序列,如'102'匹配'102-2房间','122'匹配'/1楼/2单元/2房间'
041         */
042        DIGIT_FUZZY_MATCH,
043        /**
044         * 左侧数字模糊匹配
045         * pattern必须全部为数字,
046         * 比较字符串中所有数字组成的字符串是否以pattern数字序列起始,如'102'匹配'10幛/22房间',但不匹配'/1楼/102房间'
047         */
048        DIGIT_FUZZY_LEFT_MATCH,
049        /**
050         * 右侧数字模糊匹配
051         * pattern必须全部为数字,
052         * 比较字符串中所有数字组成的字符串是否以pattern数字序列结尾,如'102'匹配'/1楼/102房间',但不匹配'102-2房间'
053         */
054        DIGIT_FUZZY_RIGHT_MATCH,
055        /**
056         * 带分隔符'/'的数字模糊匹配
057         * pattern必须为数字及分隔符'/','-','.',分隔符会被替换为'/',
058         * 比较字符串中所有数字组成的字符串是否包含pattern数字序列,如'1-102'匹配'1楼/102房间',不匹配'1楼/1102房间'
059         */
060        DIGIT_SEP_FUZZY_MATCH, 
061        /**
062         * 带分隔符'/'的左侧数字模糊匹配
063         * pattern必须为数字及分隔符'/','-','.',分隔符会被替换为'/',
064         * 比较字符串中所有数字组成的字符串是否以pattern数字起始,如'1-102'匹配'1楼/102-2房间',不匹配'1幢/1单元/102房间'
065         */
066        DIGIT_SEP_FUZZY_LEFT_MATCH,
067        /**
068         * 带分隔符'/'的右侧数字模糊匹配
069         * pattern必须为数字及分隔符'/','-','.',分隔符会被替换为'/',
070         * 比较字符串中所有数字组成的字符串是否以pattern数字结尾,如'1/102'匹配'1楼/1单元/102房间',不匹配'1幢/102-2房间'
071         */
072        DIGIT_SEP_FUZZY_RIGHT_MATCH,
073        /**
074         * 正则表达式匹配
075         * pattern为正则表达式,表达式,如果pattern不以'^'或'|$'结尾,会自动加上'^.*'开头和'.*$'结尾
076         * 比较字符串是否有满足pattern的正则匹配,如'1\d+'匹配'/1楼/102房间'
077         */
078        REGEX_MATCH, 
079        /**
080         * 全字模糊匹配
081         * pattern为要匹配的字符串序列
082         * 比较字符串是否混入pattern字符序列,如'12房'匹配'/1楼/102房间','王鹏'匹配'王小鹏','王鹏程','周王鹏','王鹏'
083         */
084        FUZZY_MATCH;
085
086        @Override
087        public String apply(String input) {
088                switch (this) {
089                case WILDCARD_MATCH:
090                        return "^.*" + input.replace("*", ".*").replace("?", ".") + ".*$";
091                case FUZZY_MATCH:
092                        return "^.*" + input.replaceAll(".", "$0.*");
093                case DIGIT_FUZZY_MATCH:
094                        return "^.*" + input.replaceAll(".", "$0[^\\\\d]*") + ".*$";
095                case DIGIT_FUZZY_LEFT_MATCH:
096                        return "^[^\\d]*" + input.replaceAll(".", "$0[^\\\\d]*") + ".*$";
097                case DIGIT_FUZZY_RIGHT_MATCH:
098                        return "^.*" + input.replaceAll(".", "[^\\\\d]*$0") + "[^\\d]*$";
099                case DIGIT_SEP_FUZZY_MATCH:
100                        // '.' '-' 为分隔符替换为 '/' 
101                        return "^.*" + input.replaceAll("[\\\\.\\\\-]+", "/").replaceAll(".", "$0[^\\\\d]*") + ".*$";
102                case DIGIT_SEP_FUZZY_LEFT_MATCH:
103                        // '.' '-' 为分隔符替换为 '/' 
104                        return "^[^\\d]*" + input.replaceAll("[\\\\.\\\\-]+", "/").replaceAll(".", "$0[^\\\\d]*") + ".*$";
105                case DIGIT_SEP_FUZZY_RIGHT_MATCH:
106                        // '.' '-' 为分隔符替换为 '/' 
107                        return "^.*" + input.replaceAll("[\\\\.\\\\-]+", "/").replaceAll(".", "[^\\\\d]*$0") + "[^\\d]*$";
108                case REGEX_MATCH:
109                        if(!input.startsWith("^")){
110                                input = "^.*" + input; 
111                        }
112                        if(!input.endsWith("^")){
113                                input = input + ".*$"; 
114                        }
115                        return input;
116                case CMP_LEFT_MATCH:
117                case CMP_RIGHT_MATCH:
118                case CMP_MATCH:
119                case EXACTLY_MATCH:
120                default:
121                        return input;
122                }
123        }
124        public IStringMatchFilter createMatchFilter(){
125                switch (this) {
126                case CMP_LEFT_MATCH:
127                case CMP_RIGHT_MATCH:
128                case CMP_MATCH:
129                case EXACTLY_MATCH:
130                        return new BaseFuzzyMatchFilter.DefaultStringMatcher(this);
131                default:
132                        return new BaseFuzzyMatchFilter.RegexFilter().setPatternFormater(this);
133                }
134        }
135}