diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/el/MapAdaptableELResolver.java b/spring-binding/src/main/java/org/springframework/binding/expression/el/MapAdaptableELResolver.java index 8493e963..3fdc6225 100644 --- a/spring-binding/src/main/java/org/springframework/binding/expression/el/MapAdaptableELResolver.java +++ b/spring-binding/src/main/java/org/springframework/binding/expression/el/MapAdaptableELResolver.java @@ -15,11 +15,14 @@ */ package org.springframework.binding.expression.el; +import java.util.Iterator; import java.util.Map; import javax.el.ELContext; +import javax.el.ELException; import javax.el.ELResolver; -import javax.el.MapELResolver; +import javax.el.PropertyNotFoundException; +import javax.el.PropertyNotWritableException; import org.springframework.binding.collection.MapAdaptable; @@ -27,35 +30,75 @@ import org.springframework.binding.collection.MapAdaptable; * An {@link ELResolver} for properly resolving variables in an instance of {@link MapAdaptable} * @author Jeremy Grelle */ -public class MapAdaptableELResolver extends MapELResolver { +public class MapAdaptableELResolver extends ELResolver { - public Class getType(ELContext context, Object base, Object property) { + public Class getCommonPropertyType(ELContext context, Object base) { if (base instanceof MapAdaptable) { - return super.getType(context, adapt(base), property); - } else { - return null; + return Object.class; } + return null; } - public Object getValue(ELContext context, Object base, Object property) { - if (base instanceof MapAdaptable) { - return super.getValue(context, adapt(base), property); - } else { - return null; - } + public Iterator getFeatureDescriptors(ELContext context, Object base) { + return null; } - public boolean isReadOnly(ELContext context, Object base, Object property) { - if (base instanceof MapAdaptable) { - return super.isReadOnly(context, adapt(base), property); - } else { - return false; + public Class getType(ELContext context, Object base, Object property) throws NullPointerException, + PropertyNotFoundException, ELException { + if (context == null) { + throw new NullPointerException("The ELContext is null."); } + + if (base instanceof MapAdaptable) { + context.setPropertyResolved(true); + Object obj = adapt(base).get(property); + return (obj != null) ? obj.getClass() : null; + } + + return null; } - public void setValue(ELContext context, Object base, Object property, Object value) { + public Object getValue(ELContext context, Object base, Object property) throws NullPointerException, + PropertyNotFoundException, ELException { + if (context == null) { + throw new NullPointerException("The ELContext is null."); + } + if (base instanceof MapAdaptable) { - super.setValue(context, adapt(base), property, value); + context.setPropertyResolved(true); + return adapt(base).get(property); + } + + return null; + } + + public boolean isReadOnly(ELContext context, Object base, Object property) throws NullPointerException, + PropertyNotFoundException, ELException { + if (context == null) { + throw new NullPointerException("The ELContext is null."); + } + + if (base instanceof MapAdaptable) { + context.setPropertyResolved(true); + } + + return false; + } + + public void setValue(ELContext context, Object base, Object property, Object value) throws NullPointerException, + PropertyNotFoundException, PropertyNotWritableException, ELException { + if (context == null) { + throw new NullPointerException("The ELContext is null."); + } + + if (base instanceof MapAdaptable) { + context.setPropertyResolved(true); + + try { + adapt(base).put(property, value); + } catch (UnsupportedOperationException e) { + throw new PropertyNotWritableException(e); + } } } diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/el/MapAdaptableELResolverTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/el/MapAdaptableELResolverTests.java new file mode 100644 index 00000000..b35319d0 --- /dev/null +++ b/spring-binding/src/test/java/org/springframework/binding/expression/el/MapAdaptableELResolverTests.java @@ -0,0 +1,69 @@ +package org.springframework.binding.expression.el; + +import java.util.HashMap; +import java.util.Map; + +import javax.el.ELContext; + +import junit.framework.TestCase; + +import org.springframework.binding.collection.MapAdaptable; + +public class MapAdaptableELResolverTests extends TestCase { + + private ELContext context; + + public void setUp() { + context = new DefaultELContext(new MapAdaptableELResolver(), null, null); + } + + public void testGetType() { + Class type = context.getELResolver().getType(context, new TestMapAdaptable(), "bar"); + assertTrue(context.isPropertyResolved()); + assertEquals(String.class, type); + } + + public void testGetType_UnknownProperty() { + Class type = context.getELResolver().getType(context, new TestMapAdaptable(), "foo"); + assertTrue(context.isPropertyResolved()); + assertEquals(null, type); + } + + public void testGetValue() { + Object value = context.getELResolver().getValue(context, new TestMapAdaptable(), "bar"); + assertTrue(context.isPropertyResolved()); + assertEquals("bar", value); + } + + public void testGetValue_UnknownProperty() { + Object value = context.getELResolver().getValue(context, new TestMapAdaptable(), "foo"); + assertTrue(context.isPropertyResolved()); + assertEquals(null, value); + } + + public void testSetValue() { + MapAdaptable testMap = new TestMapAdaptable(); + context.getELResolver().setValue(context, testMap, "foo", "foo"); + assertTrue(context.isPropertyResolved()); + assertEquals("foo", testMap.asMap().get("foo")); + } + + public void testSetValue_OverWrite() { + MapAdaptable testMap = new TestMapAdaptable(); + context.getELResolver().setValue(context, testMap, "bar", "foo"); + assertTrue(context.isPropertyResolved()); + assertEquals("foo", testMap.asMap().get("bar")); + } + + private class TestMapAdaptable implements MapAdaptable { + private Map map = new HashMap(); + + public TestMapAdaptable() { + map.put("bar", "bar"); + } + + public Map asMap() { + return map; + } + } +}