Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.lib / org.gvsig.expressionevaluator.lib.impl / src / main / java / org / gvsig / expressionevaluator / impl / function / predicate / LikeOperator.java @ 44139

History | View | Annotate | Download (3.26 KB)

1
package org.gvsig.expressionevaluator.impl.function.predicate;
2

    
3
import java.util.ArrayList;
4
import java.util.HashMap;
5
import java.util.Map;
6
import java.util.regex.Matcher;
7
import java.util.regex.Pattern;
8
import org.gvsig.expressionevaluator.Function;
9
import org.gvsig.expressionevaluator.Interpreter;
10
import org.gvsig.expressionevaluator.impl.function.operator.AbstractBinaryOperator;
11

    
12
/*
13
 * Based on portions of code from org.medfoster.sqljep.function.Like of the
14
 * SQLJEP project ((c) Copyright 2006, Alexey Gaidukov)
15
 * http://sqljep.sourceforge.net/
16
 */
17

    
18
public class LikeOperator extends AbstractBinaryOperator {
19
        protected static final Integer ZERO_OR_MORE_CHARS = 0; 
20
        protected static final Integer ONE_CHAR = 1; 
21

    
22
        protected static Map<String,Pattern> patterns = new HashMap<>();
23

    
24

    
25
    public static final String NAME = "LIKE";
26

    
27
    public LikeOperator() {
28
        super(Function.GROUP_STRING, NAME);
29
    }
30

    
31
    @Override
32
    public boolean allowConstantFolding() {
33
        return true;
34
    }
35
    
36
    @Override
37
    public Object call(Interpreter interpreter, Object op1, Object op2) {       
38
        if( op1 instanceof CharSequence && op2 instanceof CharSequence ) {
39
            boolean value = like(((CharSequence) op1).toString(), ((CharSequence) op2).toString());
40
            return value;
41
        }
42
        throw new IllegalArgumentException("Types not allowed in '"+name()+"' operand.");
43
    }
44
    
45
    public static boolean like(String source, String match) {
46
                Pattern pattern = patterns.get(match);
47
                if (pattern == null) {
48
            if( patterns.size()>20 ) {
49
                patterns = new HashMap<>();
50
            }
51
                        ArrayList<Object> p = compile(match);
52
                        String regexp = toRegExp(p);
53
                        pattern = Pattern.compile(regexp);
54
                        patterns.put(match, pattern);
55
                }
56
                Matcher m = pattern.matcher(source);
57
                return m.find();
58
        }
59
        
60
        protected static ArrayList<Object> compile(String pattern) {
61
                ArrayList<Object> format = new ArrayList<>();
62
                StringBuilder fill = new StringBuilder();
63
                final int plen = pattern.length();
64
                Character lastSymbol = null;
65
                if (pattern.length() > 2 && pattern.charAt(0) == '/' && pattern.charAt(pattern.length()-1) == '/') {
66
                        format.add(pattern.substring(1, pattern.length()-2));
67
                } else {
68
                        for (int i = 0; i < plen; i++) {
69
                                boolean f = false;
70
                                char c = pattern.charAt(i);
71
                                if (lastSymbol != null && lastSymbol == '\\') {
72
                                        lastSymbol = null;
73
                                        fill.append(c);
74
                                } else {
75
                                        if (c == '%') {
76
                                                if (fill.length() > 0) {
77
                                                        format.add(fill.toString());
78
                                                        fill.setLength(0);
79
                                                }
80
                                                format.add(ZERO_OR_MORE_CHARS); 
81
                                        }
82
                                        else if (c == '_') {
83
                                                if (fill.length() > 0) {
84
                                                        format.add(fill.toString());
85
                                                        fill.setLength(0);
86
                                                }
87
                                                format.add(ONE_CHAR); 
88
                                        } else {
89
                                                fill.append(c);
90
                                        }
91
                                        lastSymbol = c;
92
                                }
93
                        }
94
                        if (fill.length() > 0) {
95
                                format.add(fill.toString());
96
                        }
97
                }
98
                return format;
99
        }
100
        
101
        public static String toRegExp(ArrayList<Object> pattern) {
102
                if (pattern != null) {
103
                        StringBuilder str = new StringBuilder("^");
104
                        for (Object o : pattern) {
105
                                if (o == ZERO_OR_MORE_CHARS) {
106
                                        str.append(".*?");
107
                                }
108
                                else if (o == ONE_CHAR) {
109
                                        str.append(".?");
110
                                } else {
111
                                        str.append((String)o);
112
                                }
113
                        }
114
                        return str.toString();
115
                } else {
116
                        return null;
117
                }
118
        }    
119

    
120
}