View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.expression.spel;
18  
19  import java.lang.annotation.ElementType;
20  import java.lang.annotation.Retention;
21  import java.lang.annotation.RetentionPolicy;
22  import java.lang.annotation.Target;
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.HashMap;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.junit.Test;
30  
31  import org.springframework.expression.AccessException;
32  import org.springframework.expression.EvaluationContext;
33  import org.springframework.expression.EvaluationException;
34  import org.springframework.expression.Expression;
35  import org.springframework.expression.PropertyAccessor;
36  import org.springframework.expression.TypedValue;
37  import org.springframework.expression.spel.standard.SpelExpressionParser;
38  import org.springframework.expression.spel.support.StandardEvaluationContext;
39  
40  import static org.junit.Assert.*;
41  
42  public class IndexingTests {
43  
44  	@Test
45  	public void indexIntoGenericPropertyContainingMap() {
46  		Map<String, String> property = new HashMap<String, String>();
47  		property.put("foo", "bar");
48  		this.property = property;
49  		SpelExpressionParser parser = new SpelExpressionParser();
50  		Expression expression = parser.parseExpression("property");
51  		assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.HashMap<?, ?>", expression.getValueTypeDescriptor(this).toString());
52  		assertEquals(property, expression.getValue(this));
53  		assertEquals(property, expression.getValue(this, Map.class));
54  		expression = parser.parseExpression("property['foo']");
55  		assertEquals("bar", expression.getValue(this));
56  	}
57  
58  	@FieldAnnotation
59  	public Object property;
60  
61  	@Test
62  	public void indexIntoGenericPropertyContainingMapObject() {
63  		Map<String, Map<String, String>> property = new HashMap<String, Map<String, String>>();
64  		Map<String, String> map =  new HashMap<String, String>();
65  		map.put("foo", "bar");
66  		property.put("property", map);
67  		SpelExpressionParser parser = new SpelExpressionParser();
68  		StandardEvaluationContext context = new StandardEvaluationContext();
69  		context.addPropertyAccessor(new MapAccessor());
70  		context.setRootObject(property);
71  		Expression expression = parser.parseExpression("property");
72  		assertEquals("java.util.HashMap<?, ?>", expression.getValueTypeDescriptor(context).toString());
73  		assertEquals(map, expression.getValue(context));
74  		assertEquals(map, expression.getValue(context, Map.class));
75  		expression = parser.parseExpression("property['foo']");
76  		assertEquals("bar", expression.getValue(context));
77  	}
78  
79  	public static class MapAccessor implements PropertyAccessor {
80  
81  		@Override
82  		public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
83  			return (((Map<?, ?>) target).containsKey(name));
84  		}
85  
86  		@Override
87  		public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
88  			return new TypedValue(((Map<?, ?>) target).get(name));
89  		}
90  
91  		@Override
92  		public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
93  			return true;
94  		}
95  
96  		@Override
97  		@SuppressWarnings("unchecked")
98  		public void write(EvaluationContext context, Object target, String name, Object newValue)
99  				throws AccessException {
100 			((Map) target).put(name, newValue);
101 		}
102 
103 		@Override
104 		public Class<?>[] getSpecificTargetClasses() {
105 			return new Class[] { Map.class };
106 		}
107 
108 	}
109 
110 	@Test
111 	public void setGenericPropertyContainingMap() {
112 		Map<String, String> property = new HashMap<String, String>();
113 		property.put("foo", "bar");
114 		this.property = property;
115 		SpelExpressionParser parser = new SpelExpressionParser();
116 		Expression expression = parser.parseExpression("property");
117 		assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.HashMap<?, ?>", expression.getValueTypeDescriptor(this).toString());
118 		assertEquals(property, expression.getValue(this));
119 		expression = parser.parseExpression("property['foo']");
120 		assertEquals("bar", expression.getValue(this));
121 		expression.setValue(this, "baz");
122 		assertEquals("baz", expression.getValue(this));
123 	}
124 
125 	@Test
126 	public void setPropertyContainingMap() {
127 		Map<Integer, Integer> property = new HashMap<Integer, Integer>();
128 		property.put(9, 3);
129 		this.parameterizedMap = property;
130 		SpelExpressionParser parser = new SpelExpressionParser();
131 		Expression expression = parser.parseExpression("parameterizedMap");
132 		assertEquals("java.util.HashMap<java.lang.Integer, java.lang.Integer>", expression.getValueTypeDescriptor(this).toString());
133 		assertEquals(property, expression.getValue(this));
134 		expression = parser.parseExpression("parameterizedMap['9']");
135 		assertEquals(3, expression.getValue(this));
136 		expression.setValue(this, "37");
137 		assertEquals(37, expression.getValue(this));
138 	}
139 
140 	public Map<Integer, Integer> parameterizedMap;
141 
142 	@Test
143 	public void setPropertyContainingMapAutoGrow() {
144 		SpelExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, false));
145 		Expression expression = parser.parseExpression("parameterizedMap");
146 		assertEquals("java.util.Map<java.lang.Integer, java.lang.Integer>", expression.getValueTypeDescriptor(this).toString());
147 		assertEquals(property, expression.getValue(this));
148 		expression = parser.parseExpression("parameterizedMap['9']");
149 		assertEquals(null, expression.getValue(this));
150 		expression.setValue(this, "37");
151 		assertEquals(37, expression.getValue(this));
152 	}
153 
154 	@Test
155 	public void indexIntoGenericPropertyContainingList() {
156 		List<String> property = new ArrayList<String>();
157 		property.add("bar");
158 		this.property = property;
159 		SpelExpressionParser parser = new SpelExpressionParser();
160 		Expression expression = parser.parseExpression("property");
161 		assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.ArrayList<?>", expression.getValueTypeDescriptor(this).toString());
162 		assertEquals(property, expression.getValue(this));
163 		expression = parser.parseExpression("property[0]");
164 		assertEquals("bar", expression.getValue(this));
165 	}
166 
167 	@Test
168 	public void setGenericPropertyContainingList() {
169 		List<Integer> property = new ArrayList<Integer>();
170 		property.add(3);
171 		this.property = property;
172 		SpelExpressionParser parser = new SpelExpressionParser();
173 		Expression expression = parser.parseExpression("property");
174 		assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.ArrayList<?>", expression.getValueTypeDescriptor(this).toString());
175 		assertEquals(property, expression.getValue(this));
176 		expression = parser.parseExpression("property[0]");
177 		assertEquals(3, expression.getValue(this));
178 		expression.setValue(this, "4");
179 		assertEquals("4", expression.getValue(this));
180 	}
181 
182 	@Test
183 	public void setGenericPropertyContainingListAutogrow() {
184 		List<Integer> property = new ArrayList<Integer>();
185 		this.property = property;
186 		SpelExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
187 		Expression expression = parser.parseExpression("property");
188 		assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.ArrayList<?>", expression.getValueTypeDescriptor(this).toString());
189 		assertEquals(property, expression.getValue(this));
190 		expression = parser.parseExpression("property[0]");
191 		try {
192 			expression.setValue(this, "4");
193 		} catch (EvaluationException e) {
194 			assertTrue(e.getMessage().startsWith("EL1053E"));
195 		}
196 	}
197 
198 	@Test
199 	public void indexIntoPropertyContainingList() {
200 		List<Integer> property = new ArrayList<Integer>();
201 		property.add(3);
202 		this.parameterizedList = property;
203 		SpelExpressionParser parser = new SpelExpressionParser();
204 		Expression expression = parser.parseExpression("parameterizedList");
205 		assertEquals("java.util.ArrayList<java.lang.Integer>", expression.getValueTypeDescriptor(this).toString());
206 		assertEquals(property, expression.getValue(this));
207 		expression = parser.parseExpression("parameterizedList[0]");
208 		assertEquals(3, expression.getValue(this));
209 	}
210 
211 	public List<Integer> parameterizedList;
212 
213 	@Test
214 	public void indexIntoPropertyContainingListOfList() {
215 		List<List<Integer>> property = new ArrayList<List<Integer>>();
216 		property.add(Arrays.asList(3));
217 		this.parameterizedListOfList = property;
218 		SpelExpressionParser parser = new SpelExpressionParser();
219 		Expression expression = parser.parseExpression("parameterizedListOfList[0]");
220 		assertEquals("java.util.Arrays$ArrayList<java.lang.Integer>", expression.getValueTypeDescriptor(this).toString());
221 		assertEquals(property.get(0), expression.getValue(this));
222 		expression = parser.parseExpression("parameterizedListOfList[0][0]");
223 		assertEquals(3, expression.getValue(this));
224 	}
225 
226 	public List<List<Integer>> parameterizedListOfList;
227 
228 	@Test
229 	public void setPropertyContainingList() {
230 		List<Integer> property = new ArrayList<Integer>();
231 		property.add(3);
232 		this.parameterizedList = property;
233 		SpelExpressionParser parser = new SpelExpressionParser();
234 		Expression expression = parser.parseExpression("parameterizedList");
235 		assertEquals("java.util.ArrayList<java.lang.Integer>", expression.getValueTypeDescriptor(this).toString());
236 		assertEquals(property, expression.getValue(this));
237 		expression = parser.parseExpression("parameterizedList[0]");
238 		assertEquals(3, expression.getValue(this));
239 		expression.setValue(this, "4");
240 		assertEquals(4, expression.getValue(this));
241 	}
242 
243 	@Test
244 	public void indexIntoGenericPropertyContainingNullList() {
245 		SpelParserConfiguration configuration = new SpelParserConfiguration(true, true);
246 		SpelExpressionParser parser = new SpelExpressionParser(configuration);
247 		Expression expression = parser.parseExpression("property");
248 		assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.lang.Object", expression.getValueTypeDescriptor(this).toString());
249 		assertEquals(property, expression.getValue(this));
250 		expression = parser.parseExpression("property[0]");
251 		try {
252 			assertEquals("bar", expression.getValue(this));
253 		} catch (EvaluationException e) {
254 			assertTrue(e.getMessage().startsWith("EL1027E"));
255 		}
256 	}
257 
258 	@Test
259 	public void indexIntoGenericPropertyContainingGrowingList() {
260 		List<String> property = new ArrayList<String>();
261 		this.property = property;
262 		SpelParserConfiguration configuration = new SpelParserConfiguration(true, true);
263 		SpelExpressionParser parser = new SpelExpressionParser(configuration);
264 		Expression expression = parser.parseExpression("property");
265 		assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.ArrayList<?>", expression.getValueTypeDescriptor(this).toString());
266 		assertEquals(property, expression.getValue(this));
267 		expression = parser.parseExpression("property[0]");
268 		try {
269 			assertEquals("bar", expression.getValue(this));
270 		} catch (EvaluationException e) {
271 			assertTrue(e.getMessage().startsWith("EL1053E"));
272 		}
273 	}
274 
275 	@Test
276 	public void indexIntoGenericPropertyContainingGrowingList2() {
277 		List<String> property2 = new ArrayList<String>();
278 		this.property2 = property2;
279 		SpelParserConfiguration configuration = new SpelParserConfiguration(true, true);
280 		SpelExpressionParser parser = new SpelExpressionParser(configuration);
281 		Expression expression = parser.parseExpression("property2");
282 		assertEquals("java.util.ArrayList<?>", expression.getValueTypeDescriptor(this).toString());
283 		assertEquals(property2, expression.getValue(this));
284 		expression = parser.parseExpression("property2[0]");
285 		try {
286 			assertEquals("bar", expression.getValue(this));
287 		} catch (EvaluationException e) {
288 			assertTrue(e.getMessage().startsWith("EL1053E"));
289 		}
290 	}
291 
292 	public List property2;
293 
294 	@Test
295 	public void indexIntoGenericPropertyContainingArray() {
296 		String[] property = new String[] { "bar" };
297 		this.property = property;
298 		SpelExpressionParser parser = new SpelExpressionParser();
299 		Expression expression = parser.parseExpression("property");
300 		assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.lang.String[]", expression.getValueTypeDescriptor(this).toString());
301 		assertEquals(property, expression.getValue(this));
302 		expression = parser.parseExpression("property[0]");
303 		assertEquals("bar", expression.getValue(this));
304 	}
305 
306 	@Test
307 	public void emptyList() {
308 		listOfScalarNotGeneric = new ArrayList();
309 		SpelExpressionParser parser = new SpelExpressionParser();
310 		Expression expression = parser.parseExpression("listOfScalarNotGeneric");
311 		assertEquals("java.util.ArrayList<?>", expression.getValueTypeDescriptor(this).toString());
312 		assertEquals("", expression.getValue(this, String.class));
313 	}
314 
315 	@SuppressWarnings("unchecked")
316 	@Test
317 	public void resolveCollectionElementType() {
318 		listNotGeneric = new ArrayList(2);
319 		listNotGeneric.add(5);
320 		listNotGeneric.add(6);
321 		SpelExpressionParser parser = new SpelExpressionParser();
322 		Expression expression = parser.parseExpression("listNotGeneric");
323 		assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.ArrayList<?>", expression.getValueTypeDescriptor(this).toString());
324 		assertEquals("5,6", expression.getValue(this, String.class));
325 	}
326 
327 	@Test
328 	public void resolveCollectionElementTypeNull() {
329 		SpelExpressionParser parser = new SpelExpressionParser();
330 		Expression expression = parser.parseExpression("listNotGeneric");
331 		assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.List<?>", expression.getValueTypeDescriptor(this).toString());
332 	}
333 
334 	@FieldAnnotation
335 	public List listNotGeneric;
336 
337 	@Target({ElementType.FIELD})
338 	@Retention(RetentionPolicy.RUNTIME)
339 	public @interface FieldAnnotation {
340 
341 	}
342 
343 	@SuppressWarnings("unchecked")
344 	@Test
345 	public void resolveMapKeyValueTypes() {
346 		mapNotGeneric = new HashMap();
347 		mapNotGeneric.put("baseAmount", 3.11);
348 		mapNotGeneric.put("bonusAmount", 7.17);
349 		SpelExpressionParser parser = new SpelExpressionParser();
350 		Expression expression = parser.parseExpression("mapNotGeneric");
351 		assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.HashMap<?, ?>", expression.getValueTypeDescriptor(this).toString());
352 	}
353 
354 	@FieldAnnotation
355 	public Map mapNotGeneric;
356 
357 	@SuppressWarnings("unchecked")
358 	@Test
359 	public void testListOfScalar() {
360 		listOfScalarNotGeneric = new ArrayList(1);
361 		listOfScalarNotGeneric.add("5");
362 		SpelExpressionParser parser = new SpelExpressionParser();
363 		Expression expression = parser.parseExpression("listOfScalarNotGeneric[0]");
364 		assertEquals(new Integer(5), expression.getValue(this, Integer.class));
365 	}
366 
367 	public List listOfScalarNotGeneric;
368 
369 
370 	@SuppressWarnings("unchecked")
371 	@Test
372 	public void testListsOfMap() {
373 		listOfMapsNotGeneric = new ArrayList();
374 		Map map = new HashMap();
375 		map.put("fruit", "apple");
376 		listOfMapsNotGeneric.add(map);
377 		SpelExpressionParser parser = new SpelExpressionParser();
378 		Expression expression = parser.parseExpression("listOfMapsNotGeneric[0]['fruit']");
379 		assertEquals("apple", expression.getValue(this, String.class));
380 	}
381 
382 	public List listOfMapsNotGeneric;
383 
384 }