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.util.HashMap;
20  import java.util.Map;
21  
22  import org.junit.Test;
23  
24  import org.springframework.expression.AccessException;
25  import org.springframework.expression.EvaluationContext;
26  import org.springframework.expression.Expression;
27  import org.springframework.expression.ExpressionParser;
28  import org.springframework.expression.PropertyAccessor;
29  import org.springframework.expression.TypedValue;
30  import org.springframework.expression.spel.standard.SpelExpressionParser;
31  import org.springframework.expression.spel.support.StandardEvaluationContext;
32  import org.springframework.tests.Assume;
33  import org.springframework.tests.TestGroup;
34  import org.springframework.util.StopWatch;
35  
36  import static org.hamcrest.Matchers.*;
37  import static org.junit.Assert.*;
38  
39  /**
40   * Testing variations on map access.
41   *
42   * @author Andy Clement
43   */
44  public class MapAccessTests extends AbstractExpressionTests {
45  
46  	@Test
47  	public void testSimpleMapAccess01() {
48  		evaluate("testMap.get('monday')", "montag", String.class);
49  	}
50  
51  	@Test
52  	public void testMapAccessThroughIndexer() {
53  		evaluate("testMap['monday']", "montag", String.class);
54  	}
55  
56  	@Test
57  	public void testCustomMapAccessor() throws Exception {
58  		ExpressionParser parser = new SpelExpressionParser();
59  		StandardEvaluationContext ctx = TestScenarioCreator.getTestEvaluationContext();
60  		ctx.addPropertyAccessor(new MapAccessor());
61  
62  		Expression expr = parser.parseExpression("testMap.monday");
63  		Object value = expr.getValue(ctx, String.class);
64  		assertEquals("montag", value);
65  	}
66  
67  	@Test
68  	public void testVariableMapAccess() throws Exception {
69  		ExpressionParser parser = new SpelExpressionParser();
70  		StandardEvaluationContext ctx = TestScenarioCreator.getTestEvaluationContext();
71  		ctx.setVariable("day", "saturday");
72  
73  		Expression expr = parser.parseExpression("testMap[#day]");
74  		Object value = expr.getValue(ctx, String.class);
75  		assertEquals("samstag", value);
76  	}
77  
78  	@Test
79  	public void testGetValue(){
80  		Map<String,String> props1 = new HashMap<String,String>();
81  		props1.put("key1", "value1");
82  		props1.put("key2", "value2");
83  		props1.put("key3", "value3");
84  
85  		Object bean = new TestBean("name1", new TestBean("name2", null, "Description 2", 15, props1), "description 1", 6, props1);
86  
87  		ExpressionParser parser = new SpelExpressionParser();
88  		Expression expr = parser.parseExpression("testBean.properties['key2']");
89  		assertEquals("value2", expr.getValue(bean));
90  	}
91  
92  	@Test
93  	public void testGetValueFromRootMap() {
94  		Map<String, String> map = new HashMap<String, String>();
95  		map.put("key", "value");
96  
97  		ExpressionParser spelExpressionParser = new SpelExpressionParser();
98  		Expression expr = spelExpressionParser.parseExpression("#root['key']");
99  		assertEquals("value", expr.getValue(map));
100 	}
101 
102 	@Test
103 	public void testGetValuePerformance() throws Exception {
104 		Assume.group(TestGroup.PERFORMANCE);
105 		Map<String, String> map = new HashMap<String, String>();
106 		map.put("key", "value");
107 		EvaluationContext context = new StandardEvaluationContext(map);
108 
109 		ExpressionParser spelExpressionParser = new SpelExpressionParser();
110 		Expression expr = spelExpressionParser.parseExpression("#root['key']");
111 
112 		StopWatch s = new StopWatch();
113 		s.start();
114 		for (int i = 0; i < 10000; i++) {
115 			expr.getValue(context);
116 		}
117 		s.stop();
118 		assertThat(s.getTotalTimeMillis(), lessThan(200L));
119 	}
120 
121 
122 	public static class TestBean {
123 
124 		private String name;
125 		private TestBean testBean;
126 		private String description;
127 		private Integer priority;
128 		private Map<String, String> properties;
129 
130 		public TestBean(String name, TestBean testBean, String description, Integer priority, Map<String, String> props) {
131 			this.name = name;
132 			this.testBean = testBean;
133 			this.description = description;
134 			this.priority = priority;
135 			this.properties = props;
136 		}
137 
138 		public String getName() {
139 			return name;
140 		}
141 
142 		public void setName(String name) {
143 			this.name = name;
144 		}
145 
146 		public TestBean getTestBean() {
147 			return testBean;
148 		}
149 
150 		public void setTestBean(TestBean testBean) {
151 			this.testBean = testBean;
152 		}
153 
154 		public String getDescription() {
155 			return description;
156 		}
157 
158 		public void setDescription(String description) {
159 			this.description = description;
160 		}
161 
162 		public Integer getPriority() {
163 			return priority;
164 		}
165 
166 		public void setPriority(Integer priority) {
167 			this.priority = priority;
168 		}
169 
170 		public Map<String,String> getProperties() {
171 			return properties;
172 		}
173 
174 		public void setProperties(Map<String,String> properties) {
175 			this.properties = properties;
176 		}
177 	}
178 
179 
180 	public static class MapAccessor implements PropertyAccessor {
181 
182 		@Override
183 		public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
184 			return (((Map<?, ?>) target).containsKey(name));
185 		}
186 
187 		@Override
188 		public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
189 			return new TypedValue(((Map<? ,?>) target).get(name));
190 		}
191 
192 		@Override
193 		public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
194 			return true;
195 		}
196 
197 		@Override
198 		@SuppressWarnings("unchecked")
199 		public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
200 			((Map<Object,Object>) target).put(name, newValue);
201 		}
202 
203 		@Override
204 		public Class<?>[] getSpecificTargetClasses() {
205 			return new Class<?>[] {Map.class};
206 		}
207 	}
208 
209 }