1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.expression.spel;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Date;
22 import java.util.GregorianCalendar;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.junit.Test;
28
29 import org.springframework.expression.EvaluationContext;
30 import org.springframework.expression.Expression;
31 import org.springframework.expression.ExpressionParser;
32 import org.springframework.expression.ParserContext;
33 import org.springframework.expression.spel.standard.SpelExpressionParser;
34 import org.springframework.expression.spel.support.StandardEvaluationContext;
35 import org.springframework.expression.spel.testresources.Inventor;
36 import org.springframework.expression.spel.testresources.PlaceOfBirth;
37
38 import static org.junit.Assert.*;
39
40
41
42
43
44
45
46
47
48 public class SpelDocumentationTests extends AbstractExpressionTests {
49
50 static Inventor tesla ;
51 static Inventor pupin ;
52
53 static {
54 GregorianCalendar c = new GregorianCalendar();
55 c.set(1856, 7, 9);
56 tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
57 tesla.setPlaceOfBirth(new PlaceOfBirth("SmilJan"));
58 tesla.setInventions(new String[] { "Telephone repeater", "Rotating magnetic field principle",
59 "Polyphase alternating-current system", "Induction motor", "Alternating-current power transmission",
60 "Tesla coil transformer", "Wireless communication", "Radio", "Fluorescent lights" });
61
62 pupin = new Inventor("Pupin", c.getTime(), "Idvor");
63 pupin.setPlaceOfBirth(new PlaceOfBirth("Idvor"));
64
65 }
66 static class IEEE {
67 private String name;
68
69
70 public Inventor[] Members = new Inventor[1];
71 public List Members2 = new ArrayList();
72 public Map<String,Object> officers = new HashMap<String,Object>();
73
74 public List<Map<String, Object>> reverse = new ArrayList<Map<String, Object>>();
75
76 @SuppressWarnings("unchecked")
77 IEEE() {
78 officers.put("president",pupin);
79 List linv = new ArrayList();
80 linv.add(tesla);
81 officers.put("advisors",linv);
82 Members2.add(tesla);
83 Members2.add(pupin);
84
85 reverse.add(officers);
86 }
87
88 public boolean isMember(String name) {
89 return true;
90 }
91
92 public String getName() { return name; }
93 public void setName(String n) { this.name = n; }
94 }
95
96 @Test
97 public void testMethodInvocation() {
98 evaluate("'Hello World'.concat('!')","Hello World!",String.class);
99 }
100
101 @Test
102 public void testBeanPropertyAccess() {
103 evaluate("new String('Hello World'.bytes)","Hello World",String.class);
104 }
105
106 @Test
107 public void testArrayLengthAccess() {
108 evaluate("'Hello World'.bytes.length",11,Integer.class);
109 }
110
111 @Test
112 public void testRootObject() throws Exception {
113 GregorianCalendar c = new GregorianCalendar();
114 c.set(1856, 7, 9);
115
116
117 Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
118
119 ExpressionParser parser = new SpelExpressionParser();
120 Expression exp = parser.parseExpression("name");
121
122 StandardEvaluationContext context = new StandardEvaluationContext();
123 context.setRootObject(tesla);
124
125 String name = (String) exp.getValue(context);
126 assertEquals("Nikola Tesla",name);
127 }
128
129 @Test
130 public void testEqualityCheck() throws Exception {
131 ExpressionParser parser = new SpelExpressionParser();
132
133 StandardEvaluationContext context = new StandardEvaluationContext();
134 context.setRootObject(tesla);
135
136 Expression exp = parser.parseExpression("name == 'Nikola Tesla'");
137 boolean isEqual = exp.getValue(context, Boolean.class);
138 assertTrue(isEqual);
139 }
140
141
142
143 @Test
144 public void testXMLBasedConfig() {
145 evaluate("(T(java.lang.Math).random() * 100.0 )>0",true,Boolean.class);
146 }
147
148
149 @Test
150 public void testLiterals() throws Exception {
151 ExpressionParser parser = new SpelExpressionParser();
152
153 String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();
154 assertEquals("Hello World",helloWorld);
155
156 double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();
157 assertEquals(6.0221415E+23, avogadrosNumber, 0);
158
159 int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();
160 assertEquals(Integer.MAX_VALUE,maxValue);
161
162 boolean trueValue = (Boolean) parser.parseExpression("true").getValue();
163 assertTrue(trueValue);
164
165 Object nullValue = parser.parseExpression("null").getValue();
166 assertNull(nullValue);
167 }
168
169 @Test
170 public void testPropertyAccess() throws Exception {
171 EvaluationContext context = TestScenarioCreator.getTestEvaluationContext();
172 int year = (Integer) parser.parseExpression("Birthdate.Year + 1900").getValue(context);
173 assertEquals(1856,year);
174
175 String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context);
176 assertEquals("SmilJan",city);
177 }
178
179 @Test
180 public void testPropertyNavigation() throws Exception {
181 ExpressionParser parser = new SpelExpressionParser();
182
183
184 StandardEvaluationContext teslaContext = TestScenarioCreator.getTestEvaluationContext();
185
186
187
188 String invention = parser.parseExpression("inventions[3]").getValue(teslaContext, String.class);
189 assertEquals("Induction motor",invention);
190
191
192 StandardEvaluationContext societyContext = new StandardEvaluationContext();
193 IEEE ieee = new IEEE();
194 ieee.Members[0]= tesla;
195 societyContext.setRootObject(ieee);
196
197
198 String name = parser.parseExpression("Members[0].Name").getValue(societyContext, String.class);
199 assertEquals("Nikola Tesla",name);
200
201
202
203 invention = parser.parseExpression("Members[0].Inventions[6]").getValue(societyContext, String.class);
204 assertEquals("Wireless communication",invention);
205 }
206
207
208 @Test
209 public void testDictionaryAccess() throws Exception {
210 StandardEvaluationContext societyContext = new StandardEvaluationContext();
211 societyContext.setRootObject(new IEEE());
212
213 Inventor pupin = parser.parseExpression("officers['president']").getValue(societyContext, Inventor.class);
214 assertNotNull(pupin);
215
216
217 String city = parser.parseExpression("officers['president'].PlaceOfBirth.city").getValue(societyContext, String.class);
218 assertNotNull(city);
219
220
221 Inventor i = parser.parseExpression("officers['advisors'][0]").getValue(societyContext,Inventor.class);
222 assertEquals("Nikola Tesla",i.getName());
223
224 parser.parseExpression("officers['advisors'][0].PlaceOfBirth.Country").setValue(societyContext, "Croatia");
225
226 Inventor i2 = parser.parseExpression("reverse[0]['advisors'][0]").getValue(societyContext,Inventor.class);
227 assertEquals("Nikola Tesla",i2.getName());
228
229 }
230
231
232
233 @Test
234 public void testMethodInvocation2() throws Exception {
235
236 String c = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class);
237 assertEquals("bc",c);
238
239 StandardEvaluationContext societyContext = new StandardEvaluationContext();
240 societyContext.setRootObject(new IEEE());
241
242 boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(societyContext, Boolean.class);
243 assertTrue(isMember);
244 }
245
246
247
248 @Test
249 public void testRelationalOperators() throws Exception {
250 boolean result = parser.parseExpression("2 == 2").getValue(Boolean.class);
251 assertTrue(result);
252
253 result = parser.parseExpression("2 < -5.0").getValue(Boolean.class);
254 assertFalse(result);
255
256
257 result = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);
258 assertTrue(result);
259 }
260
261 @Test
262 public void testOtherOperators() throws Exception {
263
264 boolean falseValue = parser.parseExpression("'xyz' instanceof T(int)").getValue(Boolean.class);
265 assertFalse(falseValue);
266
267
268 boolean trueValue = parser.parseExpression("'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
269 assertTrue(trueValue);
270
271
272 falseValue = parser.parseExpression("'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
273 assertFalse(falseValue);
274 }
275
276
277
278 @Test
279 public void testLogicalOperators() throws Exception {
280
281 StandardEvaluationContext societyContext = new StandardEvaluationContext();
282 societyContext.setRootObject(new IEEE());
283
284
285
286
287 boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);
288 assertFalse(falseValue);
289
290 String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";
291 boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
292
293
294
295
296 trueValue = parser.parseExpression("true or false").getValue(Boolean.class);
297 assertTrue(trueValue);
298
299
300 expression = "isMember('Nikola Tesla') or isMember('Albert Einstien')";
301 trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
302 assertTrue(trueValue);
303
304
305
306
307 falseValue = parser.parseExpression("!true").getValue(Boolean.class);
308 assertFalse(falseValue);
309
310
311
312 expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
313 falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
314 assertFalse(falseValue);
315 }
316
317
318
319 @Test
320 public void testNumericalOperators() throws Exception {
321
322 int two = parser.parseExpression("1 + 1").getValue(Integer.class);
323 assertEquals(2,two);
324
325 String testString = parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class);
326 assertEquals("test string",testString);
327
328
329 int four = parser.parseExpression("1 - -3").getValue(Integer.class);
330 assertEquals(4,four);
331
332 double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class);
333 assertEquals(-9000.0d, d, 0);
334
335
336 int six = parser.parseExpression("-2 * -3").getValue(Integer.class);
337 assertEquals(6,six);
338
339 double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class);
340 assertEquals(24.0d, twentyFour, 0);
341
342
343 int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class);
344 assertEquals(-2,minusTwo);
345
346 double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);
347 assertEquals(1.0d, one, 0);
348
349
350 int three = parser.parseExpression("7 % 4").getValue(Integer.class);
351 assertEquals(3,three);
352
353 int oneInt = parser.parseExpression("8 / 5 % 2").getValue(Integer.class);
354 assertEquals(1,oneInt);
355
356
357 int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class);
358 assertEquals(-21,minusTwentyOne);
359 }
360
361
362
363 @Test
364 public void testAssignment() throws Exception {
365 Inventor inventor = new Inventor();
366 StandardEvaluationContext inventorContext = new StandardEvaluationContext();
367 inventorContext.setRootObject(inventor);
368
369 parser.parseExpression("foo").setValue(inventorContext, "Alexander Seovic2");
370
371 assertEquals("Alexander Seovic2",parser.parseExpression("foo").getValue(inventorContext,String.class));
372
373
374 String aleks = parser.parseExpression("foo = 'Alexandar Seovic'").getValue(inventorContext, String.class);
375 assertEquals("Alexandar Seovic",parser.parseExpression("foo").getValue(inventorContext,String.class));
376 assertEquals("Alexandar Seovic",aleks);
377 }
378
379
380
381 @Test
382 public void testTypes() throws Exception {
383 Class<?> dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);
384 assertEquals(Date.class, dateClass);
385 boolean trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR").getValue(Boolean.class);
386 assertTrue(trueValue);
387 }
388
389
390
391 @Test
392 public void testConstructors() throws Exception {
393 StandardEvaluationContext societyContext = new StandardEvaluationContext();
394 societyContext.setRootObject(new IEEE());
395 Inventor einstein =
396 parser.parseExpression("new org.springframework.expression.spel.testresources.Inventor('Albert Einstein',new java.util.Date(), 'German')").getValue(Inventor.class);
397 assertEquals("Albert Einstein", einstein.getName());
398
399 parser.parseExpression("Members2.add(new org.springframework.expression.spel.testresources.Inventor('Albert Einstein', 'German'))").getValue(societyContext);
400 }
401
402
403
404 @Test
405 public void testVariables() throws Exception {
406 Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
407 StandardEvaluationContext context = new StandardEvaluationContext();
408 context.setVariable("newName", "Mike Tesla");
409
410 context.setRootObject(tesla);
411
412 parser.parseExpression("foo = #newName").getValue(context);
413
414 assertEquals("Mike Tesla",tesla.getFoo());
415 }
416
417 @SuppressWarnings("unchecked")
418 @Test
419 public void testSpecialVariables() throws Exception {
420
421 List<Integer> primes = new ArrayList<Integer>();
422 primes.addAll(Arrays.asList(2,3,5,7,11,13,17));
423
424
425 ExpressionParser parser = new SpelExpressionParser();
426 StandardEvaluationContext context = new StandardEvaluationContext();
427 context.setVariable("primes",primes);
428
429
430 List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression("#primes.?[#this>10]").getValue(context);
431 assertEquals("[11, 13, 17]",primesGreaterThanTen.toString());
432 }
433
434
435
436 @Test
437 public void testFunctions() throws Exception {
438 ExpressionParser parser = new SpelExpressionParser();
439 StandardEvaluationContext context = new StandardEvaluationContext();
440
441 context.registerFunction("reverseString", StringUtils.class.getDeclaredMethod(
442 "reverseString", new Class[] { String.class }));
443
444 String helloWorldReversed = parser.parseExpression("#reverseString('hello world')").getValue(context, String.class);
445 assertEquals("dlrow olleh",helloWorldReversed);
446 }
447
448
449
450 @Test
451 public void testTernary() throws Exception {
452 String falseString = parser.parseExpression("false ? 'trueExp' : 'falseExp'").getValue(String.class);
453 assertEquals("falseExp",falseString);
454
455 StandardEvaluationContext societyContext = new StandardEvaluationContext();
456 societyContext.setRootObject(new IEEE());
457
458
459 parser.parseExpression("Name").setValue(societyContext, "IEEE");
460 societyContext.setVariable("queryName", "Nikola Tesla");
461
462 String expression = "isMember(#queryName)? #queryName + ' is a member of the ' "
463 + "+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'";
464
465 String queryResultString = parser.parseExpression(expression).getValue(societyContext, String.class);
466 assertEquals("Nikola Tesla is a member of the IEEE Society",queryResultString);
467
468 }
469
470
471
472 @SuppressWarnings("unchecked")
473 @Test
474 public void testSelection() throws Exception {
475 StandardEvaluationContext societyContext = new StandardEvaluationContext();
476 societyContext.setRootObject(new IEEE());
477 List<Inventor> list = (List<Inventor>) parser.parseExpression("Members2.?[nationality == 'Serbian']").getValue(societyContext);
478 assertEquals(1,list.size());
479 assertEquals("Nikola Tesla",list.get(0).getName());
480 }
481
482
483
484 @Test
485 public void testTemplating() throws Exception {
486 String randomPhrase =
487 parser.parseExpression("random number is ${T(java.lang.Math).random()}", new TemplatedParserContext()).getValue(String.class);
488 assertTrue(randomPhrase.startsWith("random number"));
489 }
490
491 static class TemplatedParserContext implements ParserContext {
492
493 @Override
494 public String getExpressionPrefix() {
495 return "${";
496 }
497
498 @Override
499 public String getExpressionSuffix() {
500 return "}";
501 }
502
503 @Override
504 public boolean isTemplate() {
505 return true;
506 }
507 }
508
509 static class StringUtils {
510
511 public static String reverseString(String input) {
512 StringBuilder backwards = new StringBuilder();
513 for (int i = 0; i < input.length(); i++) {
514 backwards.append(input.charAt(input.length() - 1 - i));
515 }
516 return backwards.toString();
517 }
518 }
519
520 }
521