17
17
18
18
import java .util .ArrayList ;
19
19
import java .util .List ;
20
- import java .util .regex .Matcher ;
21
- import java .util .regex .Pattern ;
22
20
23
- import org .springframework .lang . Nullable ;
21
+ import org .springframework .data . repository . query . SpelQueryContext ;
24
22
25
23
/**
26
24
* Query using Spring Expression Language to indicate parameter bindings. Queries using SpEL use {@code :#{…}} to
32
30
*/
33
31
class ExpressionQuery {
34
32
35
- private static final char CURLY_BRACE_OPEN = '{' ;
36
- private static final char CURLY_BRACE_CLOSE = '}' ;
37
-
38
33
private static final String SYNTHETIC_PARAMETER_TEMPLATE = "__synthetic_%d__" ;
39
34
40
- private static final Pattern EXPRESSION_BINDING_PATTERN = Pattern .compile ("[:]#\\ {(.*)}" );
41
-
42
35
private final String query ;
43
36
44
37
private final List <ParameterBinding > parameterBindings ;
45
38
46
39
private ExpressionQuery (String query , List <ParameterBinding > parameterBindings ) {
40
+
47
41
this .query = query ;
48
42
this .parameterBindings = parameterBindings ;
49
43
}
@@ -57,9 +51,17 @@ private ExpressionQuery(String query, List<ParameterBinding> parameterBindings)
57
51
public static ExpressionQuery create (String query ) {
58
52
59
53
List <ParameterBinding > parameterBindings = new ArrayList <>();
60
- String rewritten = transformQueryAndCollectExpressionParametersIntoBindings (query , parameterBindings );
61
54
62
- return new ExpressionQuery (rewritten , parameterBindings );
55
+ SpelQueryContext queryContext = SpelQueryContext .of ((counter , expression ) -> {
56
+
57
+ String parameterName = String .format (SYNTHETIC_PARAMETER_TEMPLATE , counter );
58
+ parameterBindings .add (new ParameterBinding (parameterName , expression ));
59
+ return parameterName ;
60
+ }, String ::concat );
61
+
62
+ SpelQueryContext .SpelExtractor parsed = queryContext .parse (query );
63
+
64
+ return new ExpressionQuery (parsed .getQueryString (), parameterBindings );
63
65
}
64
66
65
67
public String getQuery () {
@@ -70,67 +72,6 @@ public List<ParameterBinding> getBindings() {
70
72
return parameterBindings ;
71
73
}
72
74
73
- private static String transformQueryAndCollectExpressionParametersIntoBindings (String input ,
74
- List <ParameterBinding > bindings ) {
75
-
76
- StringBuilder result = new StringBuilder ();
77
-
78
- int startIndex = 0 ;
79
- int currentPosition = 0 ;
80
- int parameterIndex = 0 ;
81
-
82
- while (currentPosition < input .length ()) {
83
-
84
- Matcher matcher = findNextBindingOrExpression (input , currentPosition );
85
-
86
- // no expression parameter found
87
- if (matcher == null ) {
88
- break ;
89
- }
90
-
91
- int exprStart = matcher .start ();
92
- currentPosition = exprStart ;
93
-
94
- // eat parameter expression
95
- int curlyBraceOpenCount = 1 ;
96
- currentPosition += 3 ;
97
-
98
- while (curlyBraceOpenCount > 0 && currentPosition < input .length ()) {
99
- switch (input .charAt (currentPosition ++)) {
100
- case CURLY_BRACE_OPEN :
101
- curlyBraceOpenCount ++;
102
- break ;
103
- case CURLY_BRACE_CLOSE :
104
- curlyBraceOpenCount --;
105
- break ;
106
- default :
107
- }
108
- }
109
-
110
- result .append (input .subSequence (startIndex , exprStart ));
111
-
112
- String parameterName = String .format (SYNTHETIC_PARAMETER_TEMPLATE , parameterIndex ++);
113
- result .append (':' ).append (parameterName );
114
-
115
- bindings .add (ParameterBinding .named (parameterName , matcher .group (1 )));
116
-
117
- currentPosition = matcher .end ();
118
- startIndex = currentPosition ;
119
- }
120
-
121
- return result .append (input .subSequence (currentPosition , input .length ())).toString ();
122
- }
123
-
124
- @ Nullable
125
- private static Matcher findNextBindingOrExpression (String input , int position ) {
126
-
127
- Matcher matcher = EXPRESSION_BINDING_PATTERN .matcher (input );
128
- if (matcher .find (position )) {
129
- return matcher ;
130
- }
131
-
132
- return null ;
133
- }
134
75
135
76
@ Override
136
77
public String toString () {
@@ -153,10 +94,6 @@ private ParameterBinding(String parameterName, String expression) {
153
94
this .parameterName = parameterName ;
154
95
}
155
96
156
- static ParameterBinding named (String name , String expression ) {
157
- return new ParameterBinding (name , expression );
158
- }
159
-
160
97
String getExpression () {
161
98
return expression ;
162
99
}
0 commit comments