28
28
import java .util .HashSet ;
29
29
import java .util .List ;
30
30
import java .util .Map ;
31
+ import java .util .Objects ;
31
32
import java .util .Set ;
32
33
import java .util .StringTokenizer ;
34
+ import java .util .stream .Collectors ;
33
35
import java .util .stream .Stream ;
34
36
35
37
import example .Color ;
@@ -2267,6 +2269,12 @@ public static String concat(String a, String b) {
2267
2269
return a +b ;
2268
2270
}
2269
2271
2272
+ public static String concat2 (Object ... args ) {
2273
+ return Arrays .stream (args )
2274
+ .map (Objects ::toString )
2275
+ .collect (Collectors .joining ());
2276
+ }
2277
+
2270
2278
public static String join (String ...strings ) {
2271
2279
StringBuilder buf = new StringBuilder ();
2272
2280
for (String string : strings ) {
@@ -2279,7 +2287,7 @@ public static String join(String...strings) {
2279
2287
void compiledExpressionShouldWorkWhenUsingCustomFunctionWithVarargs () throws Exception {
2280
2288
StandardEvaluationContext context ;
2281
2289
2282
- // Here the target method takes Object... and we are passing a string
2290
+ // single string argument
2283
2291
expression = parser .parseExpression ("#doFormat('hey %s', 'there')" );
2284
2292
context = new StandardEvaluationContext ();
2285
2293
context .registerFunction ("doFormat" ,
@@ -2291,6 +2299,7 @@ void compiledExpressionShouldWorkWhenUsingCustomFunctionWithVarargs() throws Exc
2291
2299
assertCanCompile (expression );
2292
2300
assertThat (expression .getValue (String .class )).isEqualTo ("hey there" );
2293
2301
2302
+ // single string argument from root array access
2294
2303
expression = parser .parseExpression ("#doFormat([0], 'there')" );
2295
2304
context = new StandardEvaluationContext (new Object [] {"hey %s" });
2296
2305
context .registerFunction ("doFormat" ,
@@ -2302,6 +2311,7 @@ void compiledExpressionShouldWorkWhenUsingCustomFunctionWithVarargs() throws Exc
2302
2311
assertCanCompile (expression );
2303
2312
assertThat (expression .getValue (String .class )).isEqualTo ("hey there" );
2304
2313
2314
+ // single string from variable
2305
2315
expression = parser .parseExpression ("#doFormat([0], #arg)" );
2306
2316
context = new StandardEvaluationContext (new Object [] {"hey %s" });
2307
2317
context .registerFunction ("doFormat" ,
@@ -2313,13 +2323,29 @@ void compiledExpressionShouldWorkWhenUsingCustomFunctionWithVarargs() throws Exc
2313
2323
assertThat (((SpelExpression ) expression ).getAST ().isCompilable ()).isTrue ();
2314
2324
assertCanCompile (expression );
2315
2325
assertThat (expression .getValue (String .class )).isEqualTo ("hey there" );
2326
+
2327
+ // string array argument
2328
+ expression = parser .parseExpression ("#doFormat('hey %s', #arg)" );
2329
+ context = new StandardEvaluationContext ();
2330
+ context .registerFunction ("doFormat" ,
2331
+ DelegatingStringFormat .class .getDeclaredMethod ("format" , String .class , Object [].class ));
2332
+ context .setVariable ("arg" , new String [] { "there" });
2333
+ ((SpelExpression ) expression ).setEvaluationContext (context );
2334
+ assertThat (expression .getValue (String .class )).isEqualTo ("hey there" );
2335
+ assertThat (((SpelExpression ) expression ).getAST ().isCompilable ()).isTrue ();
2336
+ assertCanCompile (expression );
2337
+ assertThat (expression .getValue (String .class )).isEqualTo ("hey there" );
2316
2338
}
2317
2339
2318
2340
@ Test
2319
2341
void functionReference () throws Exception {
2320
2342
EvaluationContext ctx = new StandardEvaluationContext ();
2321
2343
Method m = getClass ().getDeclaredMethod ("concat" , String .class , String .class );
2322
- ctx .setVariable ("concat" ,m );
2344
+ ctx .setVariable ("concat" , m );
2345
+ Method m2 = getClass ().getDeclaredMethod ("concat2" , Object [].class );
2346
+ ctx .setVariable ("concat2" , m2 );
2347
+ Method m3 = getClass ().getDeclaredMethod ("join" , String [].class );
2348
+ ctx .setVariable ("join" , m3 );
2323
2349
2324
2350
expression = parser .parseExpression ("#concat('a','b')" );
2325
2351
assertThat (expression .getValue (ctx )).isEqualTo ("ab" );
@@ -2331,6 +2357,20 @@ void functionReference() throws Exception {
2331
2357
assertCanCompile (expression );
2332
2358
assertThat (expression .getValue (ctx )).isEqualTo ('b' );
2333
2359
2360
+ // varargs
2361
+ expression = parser .parseExpression ("#join(#stringArray)" );
2362
+ ctx .setVariable ("stringArray" , new String [] { "a" , "b" , "c" });
2363
+ assertThat (expression .getValue (ctx )).isEqualTo ("abc" );
2364
+ assertCanCompile (expression );
2365
+ assertThat (expression .getValue (ctx )).isEqualTo ("abc" );
2366
+
2367
+ // varargs with argument component type that is a subtype of the varargs component type.
2368
+ expression = parser .parseExpression ("#concat2(#stringArray)" );
2369
+ ctx .setVariable ("stringArray" , new String [] { "a" , "b" , "c" });
2370
+ assertThat (expression .getValue (ctx )).isEqualTo ("abc" );
2371
+ assertCanCompile (expression );
2372
+ assertThat (expression .getValue (ctx )).isEqualTo ("abc" );
2373
+
2334
2374
expression = parser .parseExpression ("#concat(#a,#b)" );
2335
2375
ctx .setVariable ("a" , "foo" );
2336
2376
ctx .setVariable ("b" , "bar" );
@@ -2524,12 +2564,11 @@ void functionReferenceVarargs_SPR12359() throws Exception {
2524
2564
assertCanCompile (expression );
2525
2565
assertThat (expression .getValue (context , new SomeCompareMethod2 ()).toString ()).isEqualTo ("xyz" );
2526
2566
2527
- // TODO Determine why the String[] is passed as the first element of the Object... varargs array instead of the entire varargs array.
2528
- // expression = parser.parseExpression("#append2(#stringArray)");
2529
- // assertThat(expression.getValue(context)).hasToString("xyz");
2530
- // assertThat(((SpelExpression) expression).getAST().isCompilable()).isTrue();
2531
- // assertCanCompile(expression);
2532
- // assertThat(expression.getValue(context)).hasToString("xyz");
2567
+ expression = parser .parseExpression ("#append2(#stringArray)" );
2568
+ assertThat (expression .getValue (context )).hasToString ("xyz" );
2569
+ assertThat (((SpelExpression ) expression ).getAST ().isCompilable ()).isTrue ();
2570
+ assertCanCompile (expression );
2571
+ assertThat (expression .getValue (context )).hasToString ("xyz" );
2533
2572
2534
2573
expression = parser .parseExpression ("#sum(1,2,3)" );
2535
2574
assertThat (expression .getValue (context )).isEqualTo (6 );
@@ -4878,6 +4917,25 @@ void constructorReference() {
4878
4917
tc8 = (TestClass8 ) o ;
4879
4918
assertThat (tc8 .i ).isEqualTo (42 );
4880
4919
4920
+ // varargs
4921
+ expression = parser .parseExpression ("new " + testclass8 + "(#root)" );
4922
+ Object [] objectArray = { "a" , "b" , "c" };
4923
+ assertThat (expression .getValue (objectArray ).getClass ().getName ()).isEqualTo (testclass8 );
4924
+ assertCanCompile (expression );
4925
+ o = expression .getValue (objectArray );
4926
+ assertThat (o .getClass ().getName ()).isEqualTo (testclass8 );
4927
+ tc8 = (TestClass8 ) o ;
4928
+ assertThat (tc8 .args ).containsExactly ("a" , "b" , "c" );
4929
+
4930
+ // varargs with argument component type that is a subtype of the varargs component type.
4931
+ expression = parser .parseExpression ("new " + testclass8 + "(#root)" );
4932
+ assertThat (expression .getValue (objectArray ).getClass ().getName ()).isEqualTo (testclass8 );
4933
+ assertCanCompile (expression );
4934
+ o = expression .getValue (new String [] { "a" , "b" , "c" });
4935
+ assertThat (o .getClass ().getName ()).isEqualTo (testclass8 );
4936
+ tc8 = (TestClass8 ) o ;
4937
+ assertThat (tc8 .args ).containsExactly ("a" , "b" , "c" );
4938
+
4881
4939
// private class, can't compile it
4882
4940
String testclass9 = "org.springframework.expression.spel.SpelCompilationCoverageTests$TestClass9" ;
4883
4941
expression = parser .parseExpression ("new " + testclass9 + "(42)" );
@@ -4984,6 +5042,7 @@ void methodReferenceVarargs() {
4984
5042
assertThat (tc .s ).isEqualTo ("aaabbbccc" );
4985
5043
tc .reset ();
4986
5044
5045
+ // varargs object
4987
5046
expression = parser .parseExpression ("sixteen('aaa','bbb','ccc')" );
4988
5047
assertCannotCompile (expression );
4989
5048
expression .getValue (tc );
@@ -4994,27 +5053,38 @@ void methodReferenceVarargs() {
4994
5053
assertThat (tc .s ).isEqualTo ("aaabbbccc" );
4995
5054
tc .reset ();
4996
5055
5056
+ // string array from property in varargs object
4997
5057
expression = parser .parseExpression ("sixteen(seventeen)" );
4998
5058
assertCannotCompile (expression );
4999
5059
expression .getValue (tc );
5000
5060
assertThat (tc .s ).isEqualTo ("aaabbbccc" );
5001
5061
assertCanCompile (expression );
5002
5062
tc .reset ();
5003
- // see TODO below
5004
- // expression.getValue(tc);
5005
- // assertThat(tc.s).isEqualTo("aaabbbccc");
5006
- // tc.reset();
5007
-
5008
- // TODO Determine why the String[] is passed as the first element of the Object... varargs array instead of the entire varargs array.
5009
- // expression = parser.parseExpression("sixteen(stringArray)");
5010
- // assertCannotCompile(expression);
5011
- // expression.getValue(tc);
5012
- // assertThat(tc.s).isEqualTo("aaabbbccc");
5013
- // assertCanCompile(expression);
5014
- // tc.reset();
5015
- // expression.getValue(tc);
5016
- // assertThat(tc.s).isEqualTo("aaabbbccc");
5017
- // tc.reset();
5063
+ expression .getValue (tc );
5064
+ assertThat (tc .s ).isEqualTo ("aaabbbccc" );
5065
+ tc .reset ();
5066
+
5067
+ // string array from variable in varargs object
5068
+ expression = parser .parseExpression ("sixteen(stringArray)" );
5069
+ assertCannotCompile (expression );
5070
+ expression .getValue (tc );
5071
+ assertThat (tc .s ).isEqualTo ("aaabbbccc" );
5072
+ assertCanCompile (expression );
5073
+ tc .reset ();
5074
+ expression .getValue (tc );
5075
+ assertThat (tc .s ).isEqualTo ("aaabbbccc" );
5076
+ tc .reset ();
5077
+
5078
+ // string array in varargs object with other parameter
5079
+ expression = parser .parseExpression ("eighteen('AAA', stringArray)" );
5080
+ assertCannotCompile (expression );
5081
+ expression .getValue (tc );
5082
+ assertThat (tc .s ).isEqualTo ("AAA::aaabbbccc" );
5083
+ assertCanCompile (expression );
5084
+ tc .reset ();
5085
+ expression .getValue (tc );
5086
+ assertThat (tc .s ).isEqualTo ("AAA::aaabbbccc" );
5087
+ tc .reset ();
5018
5088
5019
5089
// varargs int
5020
5090
expression = parser .parseExpression ("twelve(1,2,3)" );
@@ -6863,6 +6933,18 @@ public void sixteen(Object... vargs) {
6863
6933
public String [] seventeen () {
6864
6934
return new String [] { "aaa" , "bbb" , "ccc" };
6865
6935
}
6936
+
6937
+ public void eighteen (String a , Object ... vargs ) {
6938
+ if (vargs == null ) {
6939
+ s = a + "::" ;
6940
+ }
6941
+ else {
6942
+ s = a +"::" ;
6943
+ for (Object varg : vargs ) {
6944
+ s += varg ;
6945
+ }
6946
+ }
6947
+ }
6866
6948
}
6867
6949
6868
6950
@@ -6911,6 +6993,7 @@ public static class TestClass8 {
6911
6993
public String s ;
6912
6994
public double d ;
6913
6995
public boolean z ;
6996
+ public Object [] args ;
6914
6997
6915
6998
public TestClass8 (int i , String s , double d , boolean z ) {
6916
6999
this .i = i ;
@@ -6926,6 +7009,10 @@ public TestClass8(Integer i) {
6926
7009
this .i = i ;
6927
7010
}
6928
7011
7012
+ public TestClass8 (Object ... args ) {
7013
+ this .args = args ;
7014
+ }
7015
+
6929
7016
@ SuppressWarnings ("unused" )
6930
7017
private TestClass8 (String a , String b ) {
6931
7018
this .s = a +b ;
0 commit comments