25
25
import java .util .Collections ;
26
26
import java .util .Date ;
27
27
import java .util .List ;
28
+ import java .util .UUID ;
28
29
29
- import org .bson .BsonBinary ;
30
30
import org .bson .Document ;
31
31
import org .bson .codecs .DecoderContext ;
32
32
import org .junit .jupiter .api .Test ;
33
33
import org .springframework .data .spel .EvaluationContextProvider ;
34
34
import org .springframework .data .spel .ExpressionDependencies ;
35
35
import org .springframework .expression .EvaluationContext ;
36
+ import org .springframework .expression .ParseException ;
36
37
import org .springframework .expression .TypedValue ;
37
38
import org .springframework .expression .spel .standard .SpelExpressionParser ;
38
39
import org .springframework .expression .spel .support .StandardEvaluationContext ;
@@ -369,11 +370,11 @@ public void capturingExpressionDependenciesShouldNotThrowParseErrorForSpelOnlyJs
369
370
new SpelExpressionParser ());
370
371
}
371
372
372
- @ Test // GH-3871
373
- public void bindEntireQueryUsingSpelExpressionWhenEvaluationResultIsJsonString () {
373
+ @ Test // GH-3871, GH-4089
374
+ public void bindEntireQueryUsingSpelExpressionWhenEvaluationResultIsDocument () {
374
375
375
376
Object [] args = new Object [] { "expected" , "unexpected" };
376
- String json = "?#{ true ? \" { 'name': ?0 }\" : \" { 'name' : ?1 }\" }" ;
377
+ String json = "?#{ true ? { 'name': ?0 } : { 'name' : ?1 } }" ;
377
378
StandardEvaluationContext evaluationContext = (StandardEvaluationContext ) EvaluationContextProvider .DEFAULT
378
379
.getEvaluationContext (args );
379
380
@@ -384,25 +385,27 @@ public void bindEntireQueryUsingSpelExpressionWhenEvaluationResultIsJsonString()
384
385
assertThat (target ).isEqualTo (new Document ("name" , "expected" ));
385
386
}
386
387
387
- @ Test // GH-3871
388
- public void throwsExceptionWhenbindEntireQueryUsingSpelExpressionResultsInInvalidJsonString () {
388
+ @ Test // GH-3871, GH-4089
389
+ public void throwsExceptionWhenBindEntireQueryUsingSpelExpressionIsMalFormatted () {
389
390
390
391
Object [] args = new Object [] { "expected" , "unexpected" };
391
- String json = "?#{ true ? \" { 'name': ?0 { }\" : \" { 'name' : ?1 }\" }" ;
392
+ String json = "?#{ true ? { 'name': ?0 { } } : { 'name' : ?1 } }" ;
392
393
StandardEvaluationContext evaluationContext = (StandardEvaluationContext ) EvaluationContextProvider .DEFAULT
393
394
.getEvaluationContext (args );
394
395
395
- ParameterBindingJsonReader reader = new ParameterBindingJsonReader (json ,
396
- new ParameterBindingContext ((index ) -> args [index ], new SpelExpressionParser (), evaluationContext ));
396
+ assertThatExceptionOfType (ParseException .class ).isThrownBy (() -> {
397
+ ParameterBindingJsonReader reader = new ParameterBindingJsonReader (json ,
398
+ new ParameterBindingContext ((index ) -> args [index ], new SpelExpressionParser (), evaluationContext ));
397
399
398
- assertThatExceptionOfType (IllegalArgumentException .class ).isThrownBy (() -> new ParameterBindingDocumentCodec ().decode (reader , DecoderContext .builder ().build ()));
400
+ new ParameterBindingDocumentCodec ().decode (reader , DecoderContext .builder ().build ());
401
+ });
399
402
}
400
403
401
- @ Test // GH-3871
404
+ @ Test // GH-3871, GH-4089
402
405
public void bindEntireQueryUsingSpelExpressionWhenEvaluationResultIsJsonStringContainingUUID () {
403
406
404
- Object [] args = new Object [] { " UUID(' cfbca728-4e39-4613-96bc-f920b5c37e16')" , "unexpected" };
405
- String json = "?#{ true ? \" { 'name': ?0 }\" : \" { 'name' : ?1 }\" }" ;
407
+ Object [] args = new Object [] { UUID . fromString ( " cfbca728-4e39-4613-96bc-f920b5c37e16" ) , "unexpected" };
408
+ String json = "?#{ true ? { 'name': ?0 } : { 'name' : ?1 } }" ;
406
409
StandardEvaluationContext evaluationContext = (StandardEvaluationContext ) EvaluationContextProvider .DEFAULT
407
410
.getEvaluationContext (args );
408
411
@@ -411,7 +414,7 @@ public void bindEntireQueryUsingSpelExpressionWhenEvaluationResultIsJsonStringCo
411
414
412
415
Document target = new ParameterBindingDocumentCodec ().decode (reader , DecoderContext .builder ().build ());
413
416
414
- assertThat (target .get ("name" )).isInstanceOf (BsonBinary .class );
417
+ assertThat (target .get ("name" )).isInstanceOf (UUID .class );
415
418
}
416
419
417
420
@ Test // GH-3871
@@ -481,6 +484,69 @@ void parsesNullValue() {
481
484
assertThat (target ).isEqualTo (new Document ("parent" , null ));
482
485
}
483
486
487
+
488
+ @ Test // GH-4089
489
+ void retainsSpelArgumentTypeViaArgumentIndex () {
490
+
491
+ String source = "new java.lang.Object()" ;
492
+ Document target = parse ("{ arg0 : ?#{[0]} }" , source );
493
+ assertThat (target .get ("arg0" )).isEqualTo (source );
494
+ }
495
+
496
+ @ Test // GH-4089
497
+ void retainsSpelArgumentTypeViaParameterPlaceholder () {
498
+
499
+ String source = "new java.lang.Object()" ;
500
+ Document target = parse ("{ arg0 : :#{?0} }" , source );
501
+ assertThat (target .get ("arg0" )).isEqualTo (source );
502
+ }
503
+
504
+ @ Test // GH-4089
505
+ void errorsOnNonDocument () {
506
+
507
+ String source = "new java.lang.Object()" ;
508
+ assertThatExceptionOfType (IllegalArgumentException .class ).isThrownBy (() -> parse (":#{?0}" , source ));
509
+ }
510
+
511
+ @ Test // GH-4089
512
+ void bindsFullDocument () {
513
+
514
+ Document source = new Document ();
515
+ assertThat (parse (":#{?0}" , source )).isSameAs (source );
516
+ }
517
+
518
+ @ Test // GH-4089
519
+ void enforcesStringSpelArgumentTypeViaParameterPlaceholderWhenQuoted () {
520
+
521
+ Integer source = 10 ;
522
+ Document target = parse ("{ arg0 : :#{'?0'} }" , source );
523
+ assertThat (target .get ("arg0" )).isEqualTo ("10" );
524
+ }
525
+
526
+ @ Test // GH-4089
527
+ void enforcesSpelArgumentTypeViaParameterPlaceholderWhenQuoted () {
528
+
529
+ String source = "new java.lang.Object()" ;
530
+ Document target = parse ("{ arg0 : :#{'?0'} }" , source );
531
+ assertThat (target .get ("arg0" )).isEqualTo (source );
532
+ }
533
+
534
+ @ Test // GH-4089
535
+ void retainsSpelArgumentTypeViaParameterPlaceholderWhenValueContainsSingleQuotes () {
536
+
537
+ String source = "' + new java.lang.Object() + '" ;
538
+ Document target = parse ("{ arg0 : :#{?0} }" , source );
539
+ assertThat (target .get ("arg0" )).isEqualTo (source );
540
+ }
541
+
542
+ @ Test // GH-4089
543
+ void retainsSpelArgumentTypeViaParameterPlaceholderWhenValueContainsDoubleQuotes () {
544
+
545
+ String source = "\\ \" + new java.lang.Object() + \\ \" " ;
546
+ Document target = parse ("{ arg0 : :#{?0} }" , source );
547
+ assertThat (target .get ("arg0" )).isEqualTo (source );
548
+ }
549
+
484
550
private static Document parse (String json , Object ... args ) {
485
551
486
552
ParameterBindingJsonReader reader = new ParameterBindingJsonReader (json , args );
0 commit comments