From bf08c3ffbf5e32e1f2d28e6244cd0e6e716c232e Mon Sep 17 00:00:00 2001 From: Mark Pollack Date: Fri, 19 Jun 2009 11:58:00 +0000 Subject: [PATCH] Document Elvis Operator (?: ) and Safe Navigation Operator (?.) remove references to ANTLR --- .../src/expressions.xml | 129 +++++++++++++----- 1 file changed, 97 insertions(+), 32 deletions(-) diff --git a/spring-framework-reference/src/expressions.xml b/spring-framework-reference/src/expressions.xml index 18a79a51529..e8b74de7f1c 100644 --- a/spring-framework-reference/src/expressions.xml +++ b/spring-framework-reference/src/expressions.xml @@ -122,24 +122,22 @@ The following code introduces the SpEL API to evaluate the literal string expression 'Hello World' - ExpressionParser parser = new SpelAntlrExpressionParser(); + ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression("'Hello World'"); String message = (String) exp.getValue();The value of the message variable is simply 'Hello World'. The SpEL classes and interfaces you are most likely to use are located in the packages org.springframework.expression - and its sub packages spel.antlr and - spel.support. + and its sub package and spel.support. - The expression language is based on a grammar and uses ANTLR to - construct the lexer and parser. The interface - ExpressionParser is responsible for parsing - an expression string. In this example the expression string is a string - literal denoted by the surrounding single quotes. The interface - Expression is responsible for evaluating - the previously defined expression string. There are two exceptions that - can be thrown, ParseException and + The interface ExpressionParser is + responsible for parsing an expression string. In this example the + expression string is a string literal denoted by the surrounding single + quotes. The interface Expression is + responsible for evaluating the previously defined expression string. There + are two exceptions that can be thrown, + ParseException and EvaluationException when calling 'parser.parseExpression' and 'exp.getValue' respectfully. @@ -150,7 +148,7 @@ String message = (String) exp.getValue();The value of the As an example of method invocation, we call the 'concat' method on the string literal - ExpressionParser parser = new SpelAntlrExpressionParser(); + ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression("'Hello World'.concat('!')"); String message = (String) exp.getValue(); @@ -159,7 +157,7 @@ String message = (String) exp.getValue(); As an example of calling a JavaBean property, the String property 'Bytes' can be called as shown below - ExpressionParser parser = new SpelAntlrExpressionParser(); + ExpressionParser parser = new SpelExpressionParser(); // invokes 'getBytes()' Expression exp = parser.parseExpression("'Hello World'.bytes"); @@ -171,7 +169,7 @@ byte[] bytes = (byte[]) exp.getValue(); Public fields may also be accessed - ExpressionParser parser = new SpelAntlrExpressionParser(); + ExpressionParser parser = new SpelExpressionParser(); // invokes 'getBytes().length' Expression exp = parser.parseExpression("'Hello World'.bytes.length"); @@ -181,7 +179,7 @@ int length = (Integer) exp.getValue(); The String's constructor can be called instead of using a string literal - ExpressionParser parser = new SpelAntlrExpressionParser(); + ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression("new String('hello world').toUpperCase()"); String message = exp.getValue(String.class); @@ -204,7 +202,7 @@ c.set(1856, 7, 9); // The constructor arguments are name, birthday, and nationaltiy. Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian"); -ExpressionParser parser = new SpelAntlrExpressionParser(); +ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression("name"); EvaluationContext context = new StandardEvaluationContext(); @@ -244,8 +242,9 @@ boolean result = exp.getValue(context, Boolean.class); // evaluates to trueThe StandardEvaluationContext is where you specify the root object to evaluate against via the method - setRootObject . You can also specify variables - and functions that will be used in the expression using the methods + setRootObject or passing the root object into + the constructor. . You can also specify variables and functions that + will be used in the expression using the methods setVariable and registerFunction. The use of variables and functions are described in the language reference sections - ExpressionParser parser = new SpelAntlrExpressionParser(); + ExpressionParser parser = new SpelExpressionParser(); // evals to "Hello World" String helloWorld = (String) parser.parseExpression("'Hello World'").getValue(); @@ -486,11 +485,10 @@ String city = (String) parser.parseExpression("placeOfBirth.City").getValue(cont names. The contents of arrays and lists are obtained using square bracket notation. - ExpressionParser parser = new SpelAntlrExpressionParser(); + ExpressionParser parser = new SpelExpressionParser(); // Inventions Array -StandardEvaluationContext teslaContext = new StandardEvaluationContext(); -teslaContext.setRootObject(tesla); +StandardEvaluationContext teslaContext = new StandardEvaluationContext(tesla); // evaluates to "Induction motor" String invention = parser.parseExpression("inventions[3]").getValue(teslaContext, @@ -498,8 +496,7 @@ String invention = parser.parseExpression("inventions[3]").getValue(teslaContext // Members List -StandardEvaluationContext societyContext = new StandardEvaluationContext(); -societyContext.setRootObject(ieee); +StandardEvaluationContext societyContext = new StandardEvaluationContext(ieee); // evaluates to "Nikola Tesla" String name = parser.parseExpression("Members[0].Name").getValue(societyContext, String.class); @@ -665,8 +662,7 @@ int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); getValue Inventor inventor = new Inventor(); -StandardEvaluationContext inventorContext = new StandardEvaluationContext(); -inventorContext.setRootObject(inventor); +StandardEvaluationContext inventorContext = new StandardEvaluationContext(inventor); parser.parseExpression("Name").setValue(inventorContext, "Alexander Seovic2"); @@ -728,12 +724,9 @@ p.parseExpression("Members.add(new org.spring.samples.spel.inventor.Inventor('Al StandardEvaluationContext. Inventor tesla = new Inventor("Nikola Tesla", "Serbian"); -StandardEvaluationContext context = new StandardEvaluationContext(); +StandardEvaluationContext context = new StandardEvaluationContext(tesla); context.setVariable("newName", "Mike Tesla"); - -context.setRootObject(tesla); - parser.parseExpression("Name = #newName").getValue(context); System.out.println(tesla.getName()) // "Mike Tesla" @@ -750,7 +743,7 @@ List<Integer> primes = new ArrayList<Integer>(); primes.addAll(Arrays.asList(2,3,5,7,11,13,17)); // create parser and set variable 'primes' as the array of integers -ExpressionParser parser = new SpelAntlrExpressionParser(); +ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); context.setVariable("primes",primes); @@ -810,7 +803,7 @@ List<Integer> primesGreaterThanTen = This method is then registered with the evaluation context and can be used within an expression string - ExpressionParser parser = new SpelAntlrExpressionParser(); + ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); context.registerFunction("reverseString", @@ -842,6 +835,78 @@ expression = "isMember(#queryName)? #queryName + ' is a member of the ' " + String queryResultString = parser.parseExpression(expression).getValue(societyContext, String.class); // queryResultString = "Nikola Tesla is a member of the IEEE Society" + + Also see the next section on the Elvis operator for an even + shorter syntax for the ternary operator + + +
+ The Elvis Operator + + The Elvis operator is a shortening of the ternary operator syntax + and is used in the Groovy + language. The ternary operator syntax you usually have to repeat a + variable twice, for example + + String name = "Elvis Presley"; +String displayName = name != null ? name : "Unknown"; + + Instead you can use the Elvis operator, named for the resemblance + to Elvis' hair style. + + ExpressionParser parser = new SpelExpressionParser(); + +String name = parser.parseExpression("null?:'Unknown'").getValue(String.class); + +System.out.println(name); // 'Unknown' + + + + Here is a more complex example + + ExpressionParser parser = new SpelExpressionParser(); + +Inventor tesla = new Inventor("Nikola Tesla", "Serbian"); +StandardEvaluationContext context = new StandardEvaluationContext(tesla); + +String name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, String.class); + +System.out.println(name); // Mike Tesla + +tesla.setName(null); + +name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, String.class); + +System.out.println(name); // Elvis Presley +
+ +
+ Safe Navigation operator + + The Safe Navigation operator is used to avoid a + NullPointerException and comes from the Groovy + language. Typically when you have a reference to an object you might + need to verify that it is not null before accessing methods or + properties of the object. To avoid this, the safe navigation operator + will simply return null instead of throwing an exception. + + ExpressionParser parser = new SpelExpressionParser(); + +Inventor tesla = new Inventor("Nikola Tesla", "Serbian"); +tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan")); + +StandardEvaluationContext context = new StandardEvaluationContext(tesla); + +String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class); +System.out.println(city); // Smiljan + +tesla.setPlaceOfBirth(null); + +city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class); + +System.out.println(city); // null - does not throw NullPointerException!!!