|
20 | 20 | import java.text.DateFormat;
|
21 | 21 | import java.text.ParsePosition;
|
22 | 22 | import java.text.SimpleDateFormat;
|
| 23 | +import java.util.ArrayList; |
23 | 24 | import java.util.Calendar;
|
| 25 | +import java.util.Collections; |
24 | 26 | import java.util.Date;
|
| 27 | +import java.util.HashMap; |
| 28 | +import java.util.List; |
25 | 29 | import java.util.Locale;
|
26 | 30 | import java.util.Map;
|
27 | 31 | import java.util.TimeZone;
|
@@ -64,6 +68,7 @@ public class ParameterBindingJsonReader extends AbstractBsonReader {
|
64 | 68 | private static final Pattern PARAMETER_ONLY_BINDING_PATTERN = Pattern.compile("^\\?(\\d+)$");
|
65 | 69 | private static final Pattern PARAMETER_BINDING_PATTERN = Pattern.compile("\\?(\\d+)");
|
66 | 70 | private static final Pattern EXPRESSION_BINDING_PATTERN = Pattern.compile("[\\?:]#\\{.*\\}");
|
| 71 | + private static final Pattern SPEL_PARAMETER_BINDING_PATTERN = Pattern.compile("('\\?(\\d+)'|\\?(\\d+))"); |
67 | 72 |
|
68 | 73 | private final ParameterBindingContext bindingContext;
|
69 | 74 |
|
@@ -379,14 +384,24 @@ private BindableValue bindableValueFor(JsonToken token) {
|
379 | 384 | String binding = regexMatcher.group();
|
380 | 385 | String expression = binding.substring(3, binding.length() - 1);
|
381 | 386 |
|
382 |
| - Matcher inSpelMatcher = PARAMETER_BINDING_PATTERN.matcher(expression); |
| 387 | + Matcher inSpelMatcher = SPEL_PARAMETER_BINDING_PATTERN.matcher(expression); // ?0 '?0' |
| 388 | + Map<String, Object> innerSpelVariables = new HashMap<>(); |
| 389 | + |
383 | 390 | while (inSpelMatcher.find()) {
|
384 | 391 |
|
385 |
| - int index = computeParameterIndex(inSpelMatcher.group()); |
386 |
| - expression = expression.replace(inSpelMatcher.group(), getBindableValueForIndex(index).toString()); |
| 392 | + String group = inSpelMatcher.group(); |
| 393 | + int index = computeParameterIndex(group); |
| 394 | + Object value = getBindableValueForIndex(index); |
| 395 | + String varName = "__QVar" + innerSpelVariables.size(); |
| 396 | + expression = expression.replace(group, "#" + varName); |
| 397 | + if(group.startsWith("'")) { // retain the string semantic |
| 398 | + innerSpelVariables.put(varName, nullSafeToString(value)); |
| 399 | + } else { |
| 400 | + innerSpelVariables.put(varName, value); |
| 401 | + } |
387 | 402 | }
|
388 | 403 |
|
389 |
| - Object value = evaluateExpression(expression); |
| 404 | + Object value = evaluateExpression(expression, innerSpelVariables); |
390 | 405 | bindableValue.setValue(value);
|
391 | 406 | bindableValue.setType(bsonTypeForValue(value));
|
392 | 407 | return bindableValue;
|
@@ -415,14 +430,24 @@ private BindableValue bindableValueFor(JsonToken token) {
|
415 | 430 | String binding = regexMatcher.group();
|
416 | 431 | String expression = binding.substring(3, binding.length() - 1);
|
417 | 432 |
|
418 |
| - Matcher inSpelMatcher = PARAMETER_BINDING_PATTERN.matcher(expression); |
| 433 | + Matcher inSpelMatcher = SPEL_PARAMETER_BINDING_PATTERN.matcher(expression); |
| 434 | + Map<String, Object> innerSpelVariables = new HashMap<>(); |
| 435 | + |
419 | 436 | while (inSpelMatcher.find()) {
|
420 | 437 |
|
421 |
| - int index = computeParameterIndex(inSpelMatcher.group()); |
422 |
| - expression = expression.replace(inSpelMatcher.group(), getBindableValueForIndex(index).toString()); |
| 438 | + String group = inSpelMatcher.group(); |
| 439 | + int index = computeParameterIndex(group); |
| 440 | + Object value = getBindableValueForIndex(index); |
| 441 | + String varName = "__QVar" + innerSpelVariables.size(); |
| 442 | + expression = expression.replace(group, "#" + varName); |
| 443 | + if(group.startsWith("'")) { // retain the string semantic |
| 444 | + innerSpelVariables.put(varName, nullSafeToString(value)); |
| 445 | + } else { |
| 446 | + innerSpelVariables.put(varName, value); |
| 447 | + } |
423 | 448 | }
|
424 | 449 |
|
425 |
| - computedValue = computedValue.replace(binding, nullSafeToString(evaluateExpression(expression))); |
| 450 | + computedValue = computedValue.replace(binding, nullSafeToString(evaluateExpression(expression, innerSpelVariables))); |
426 | 451 |
|
427 | 452 | bindableValue.setValue(computedValue);
|
428 | 453 | bindableValue.setType(BsonType.STRING);
|
@@ -459,7 +484,7 @@ private static String nullSafeToString(@Nullable Object value) {
|
459 | 484 | }
|
460 | 485 |
|
461 | 486 | private static int computeParameterIndex(String parameter) {
|
462 |
| - return NumberUtils.parseNumber(parameter.replace("?", ""), Integer.class); |
| 487 | + return NumberUtils.parseNumber(parameter.replace("?", "").replace("'", ""), Integer.class); |
463 | 488 | }
|
464 | 489 |
|
465 | 490 | private Object getBindableValueForIndex(int index) {
|
@@ -511,7 +536,12 @@ private BsonType bsonTypeForValue(Object value) {
|
511 | 536 |
|
512 | 537 | @Nullable
|
513 | 538 | private Object evaluateExpression(String expressionString) {
|
514 |
| - return bindingContext.evaluateExpression(expressionString); |
| 539 | + return bindingContext.evaluateExpression(expressionString, Collections.emptyMap()); |
| 540 | + } |
| 541 | + |
| 542 | + @Nullable |
| 543 | + private Object evaluateExpression(String expressionString, Map<String,Object> variables) { |
| 544 | + return bindingContext.evaluateExpression(expressionString, variables); |
515 | 545 | }
|
516 | 546 |
|
517 | 547 | // Spring Data Customization END
|
|
0 commit comments