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 @ 44207
History | View | Annotate | Download (3.3 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 static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LIKE; |
9 |
import org.gvsig.expressionevaluator.Function; |
10 |
import org.gvsig.expressionevaluator.Interpreter; |
11 |
import org.gvsig.expressionevaluator.impl.function.operator.AbstractBinaryOperator; |
12 |
|
13 |
/*
|
14 |
* Based on portions of code from org.medfoster.sqljep.function.Like of the
|
15 |
* SQLJEP project ((c) Copyright 2006, Alexey Gaidukov)
|
16 |
* http://sqljep.sourceforge.net/
|
17 |
*/
|
18 |
|
19 |
public class LikeOperator extends AbstractBinaryOperator { |
20 |
protected static final Integer ZERO_OR_MORE_CHARS = 0; |
21 |
protected static final Integer ONE_CHAR = 1; |
22 |
|
23 |
protected static Map<String,Pattern> patterns = new HashMap<>(); |
24 |
|
25 |
|
26 |
public LikeOperator() {
|
27 |
super(Function.GROUP_STRING, OPERATOR_LIKE, true); |
28 |
} |
29 |
|
30 |
@Override
|
31 |
public boolean allowConstantFolding() { |
32 |
return true; |
33 |
} |
34 |
|
35 |
@Override
|
36 |
public Object call(Interpreter interpreter, Object op1, Object op2) { |
37 |
if( op1 instanceof CharSequence && op2 instanceof CharSequence ) { |
38 |
boolean value = like(((CharSequence) op1).toString(), ((CharSequence) op2).toString()); |
39 |
return value;
|
40 |
} |
41 |
throw new IllegalArgumentException("Types not allowed in '"+name()+"' operand."); |
42 |
} |
43 |
|
44 |
public static boolean like(String source, String match) { |
45 |
Pattern pattern = patterns.get(match);
|
46 |
if (pattern == null) { |
47 |
if( patterns.size()>20 ) { |
48 |
patterns = new HashMap<>(); |
49 |
} |
50 |
ArrayList<Object> p = compile(match); |
51 |
String regexp = toRegExp(p);
|
52 |
pattern = Pattern.compile(regexp);
|
53 |
patterns.put(match, pattern); |
54 |
} |
55 |
Matcher m = pattern.matcher(source);
|
56 |
return m.find();
|
57 |
} |
58 |
|
59 |
protected static ArrayList<Object> compile(String pattern) { |
60 |
ArrayList<Object> format = new ArrayList<>(); |
61 |
StringBuilder fill = new StringBuilder(); |
62 |
final int plen = pattern.length(); |
63 |
Character lastSymbol = null; |
64 |
if (pattern.length() > 2 && pattern.charAt(0) == '/' && pattern.charAt(pattern.length()-1) == '/') { |
65 |
format.add(pattern.substring(1, pattern.length()-2)); |
66 |
} else {
|
67 |
for (int i = 0; i < plen; i++) { |
68 |
boolean f = false; |
69 |
char c = pattern.charAt(i);
|
70 |
if (lastSymbol != null && lastSymbol == '\\') { |
71 |
lastSymbol = null;
|
72 |
fill.append(c); |
73 |
} else {
|
74 |
if (c == '%') { |
75 |
if (fill.length() > 0) { |
76 |
format.add(fill.toString()); |
77 |
fill.setLength(0);
|
78 |
} |
79 |
format.add(ZERO_OR_MORE_CHARS); |
80 |
} |
81 |
else if (c == '_') { |
82 |
if (fill.length() > 0) { |
83 |
format.add(fill.toString()); |
84 |
fill.setLength(0);
|
85 |
} |
86 |
format.add(ONE_CHAR); |
87 |
} else {
|
88 |
fill.append(c); |
89 |
} |
90 |
lastSymbol = c; |
91 |
} |
92 |
} |
93 |
if (fill.length() > 0) { |
94 |
format.add(fill.toString()); |
95 |
} |
96 |
} |
97 |
return format;
|
98 |
} |
99 |
|
100 |
public static String toRegExp(ArrayList<Object> pattern) { |
101 |
if (pattern != null) { |
102 |
StringBuilder str = new StringBuilder("^"); |
103 |
for (Object o : pattern) { |
104 |
if (o == ZERO_OR_MORE_CHARS) {
|
105 |
str.append(".*?");
|
106 |
} |
107 |
else if (o == ONE_CHAR) { |
108 |
str.append(".?");
|
109 |
} else {
|
110 |
str.append((String)o);
|
111 |
} |
112 |
} |
113 |
return str.toString();
|
114 |
} else {
|
115 |
return null; |
116 |
} |
117 |
} |
118 |
|
119 |
} |