diff --git a/spring-context/src/main/java/org/springframework/context/expression/MapAccessor.java b/spring-context/src/main/java/org/springframework/context/expression/MapAccessor.java index fb51e880b1..97ecdc5855 100644 --- a/spring-context/src/main/java/org/springframework/context/expression/MapAccessor.java +++ b/spring-context/src/main/java/org/springframework/context/expression/MapAccessor.java @@ -89,7 +89,7 @@ public class MapAccessor implements CompilablePropertyAccessor { public void write(EvaluationContext context, @Nullable Object target, String name, @Nullable Object newValue) throws AccessException { - Assert.state(target instanceof Map, "Target must be a Map"); + Assert.state(target instanceof Map, "Target must be of type Map"); Map map = (Map) target; map.put(name, newValue); } @@ -114,7 +114,7 @@ public class MapAccessor implements CompilablePropertyAccessor { CodeFlow.insertCheckCast(mv, "Ljava/util/Map"); } mv.visitLdcInsn(propertyName); - mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get","(Ljava/lang/Object;)Ljava/lang/Object;",true); + mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", true); } diff --git a/spring-context/src/test/java/org/springframework/context/expression/MapAccessorTests.java b/spring-context/src/test/java/org/springframework/context/expression/MapAccessorTests.java index 8c7c63fd0f..a82b2e75c6 100644 --- a/spring-context/src/test/java/org/springframework/context/expression/MapAccessorTests.java +++ b/spring-context/src/test/java/org/springframework/context/expression/MapAccessorTests.java @@ -17,6 +17,7 @@ package org.springframework.context.expression; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; @@ -36,7 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat; class MapAccessorTests { @Test - void mapAccessorCompilable() { + void compilationSupport() { Map testMap = getSimpleTestMap(); StandardEvaluationContext sec = new StandardEvaluationContext(); sec.addPropertyAccessor(new MapAccessor()); @@ -44,72 +45,79 @@ class MapAccessorTests { // basic Expression ex = sep.parseExpression("foo"); - assertThat(ex.getValue(sec,testMap)).isEqualTo("bar"); + assertThat(ex.getValue(sec, testMap)).isEqualTo("bar"); assertThat(SpelCompiler.compile(ex)).isTrue(); - assertThat(ex.getValue(sec,testMap)).isEqualTo("bar"); + assertThat(ex.getValue(sec, testMap)).isEqualTo("bar"); // compound expression ex = sep.parseExpression("foo.toUpperCase()"); - assertThat(ex.getValue(sec,testMap)).isEqualTo("BAR"); + assertThat(ex.getValue(sec, testMap)).isEqualTo("BAR"); assertThat(SpelCompiler.compile(ex)).isTrue(); - assertThat(ex.getValue(sec,testMap)).isEqualTo("BAR"); + assertThat(ex.getValue(sec, testMap)).isEqualTo("BAR"); // nested map - Map> nestedMap = getNestedTestMap(); + Map> nestedMap = getNestedTestMap(); ex = sep.parseExpression("aaa.foo.toUpperCase()"); - assertThat(ex.getValue(sec,nestedMap)).isEqualTo("BAR"); + assertThat(ex.getValue(sec, nestedMap)).isEqualTo("BAR"); assertThat(SpelCompiler.compile(ex)).isTrue(); - assertThat(ex.getValue(sec,nestedMap)).isEqualTo("BAR"); + assertThat(ex.getValue(sec, nestedMap)).isEqualTo("BAR"); // avoiding inserting checkcast because first part of expression returns a Map ex = sep.parseExpression("getMap().foo"); MapGetter mapGetter = new MapGetter(); - assertThat(ex.getValue(sec,mapGetter)).isEqualTo("bar"); + assertThat(ex.getValue(sec, mapGetter)).isEqualTo("bar"); assertThat(SpelCompiler.compile(ex)).isTrue(); - assertThat(ex.getValue(sec,mapGetter)).isEqualTo("bar"); + assertThat(ex.getValue(sec, mapGetter)).isEqualTo("bar"); // basic isWritable ex = sep.parseExpression("foo"); - assertThat(ex.isWritable(sec,testMap)).isTrue(); + assertThat(ex.isWritable(sec, testMap)).isTrue(); // basic write ex = sep.parseExpression("foo2"); ex.setValue(sec, testMap, "bar2"); - assertThat(ex.getValue(sec,testMap)).isEqualTo("bar2"); + assertThat(ex.getValue(sec, testMap)).isEqualTo("bar2"); assertThat(SpelCompiler.compile(ex)).isTrue(); - assertThat(ex.getValue(sec,testMap)).isEqualTo("bar2"); + assertThat(ex.getValue(sec, testMap)).isEqualTo("bar2"); } @Test - void mapAccessorNotWritable() { + void isWritable() { Map testMap = getSimpleTestMap(); StandardEvaluationContext sec = new StandardEvaluationContext(); - sec.addPropertyAccessor(new MapAccessor(false)); SpelExpressionParser sep = new SpelExpressionParser(); Expression ex = sep.parseExpression("foo"); + + assertThat(ex.isWritable(sec, testMap)).isFalse(); + + sec.setPropertyAccessors(List.of(new MapAccessor(true))); + assertThat(ex.isWritable(sec, testMap)).isTrue(); + + sec.setPropertyAccessors(List.of(new MapAccessor(false))); assertThat(ex.isWritable(sec, testMap)).isFalse(); } + + @SuppressWarnings({"rawtypes", "unchecked"}) public static class MapGetter { - Map map = new HashMap<>(); + Map map = new HashMap<>(); public MapGetter() { - map.put("foo", "bar"); + this.map.put("foo", "bar"); } - @SuppressWarnings("rawtypes") public Map getMap() { - return map; + return this.map; } } - public Map getSimpleTestMap() { + private static Map getSimpleTestMap() { Map map = new HashMap<>(); map.put("foo","bar"); return map; } - public Map> getNestedTestMap() { + private static Map> getNestedTestMap() { Map map = new HashMap<>(); map.put("foo","bar"); Map> map2 = new HashMap<>();