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 |
} |