Author: henrib Date: Mon Oct 12 16:46:15 2009 New Revision: 824414 URL: http://svn.apache.org/viewvc?rev=824414&view=rev Log: Fixed bug in DuckSetExecutor: search for 'set' method, not 'put', modified existing tests accordingly; Added equals/hashCode methods on *Executor: added tests to verify the discovery behaviors
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/AbstractExecutor.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/BooleanGetExecutor.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/DuckGetExecutor.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/DuckSetExecutor.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/Introspector.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/ListGetExecutor.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/ListSetExecutor.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/MapGetExecutor.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/MapSetExecutor.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/PropertyGetExecutor.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/PropertySetExecutor.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/CacheTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/JexlTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/util/introspection/DiscoveryTest.java Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/AbstractExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/AbstractExecutor.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/AbstractExecutor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/AbstractExecutor.java Mon Oct 12 16:46:15 2009 @@ -79,6 +79,46 @@ method = theMethod; } + /** {...@inheritdoc} */ + @Override + public boolean equals(Object arg) { + return this == arg || (arg instanceof AbstractExecutor && equals((AbstractExecutor) arg)); + } + + /** {...@inheritdoc} */ + @Override + public int hashCode() { + return method.hashCode(); + } + + /** + * Indicates whether some other executor is equivalent to this one. + * @param arg the other executor to check + * @return true if both executors are equivalent, false otherwise + */ + public boolean equals(AbstractExecutor arg) { + // common equality check + if (!this.getClass().equals(arg.getClass())) { + return false; + } + if (!this.getMethod().equals(arg.getMethod())) { + return false; + } + if (!this.getTargetClass().equals(arg.getTargetClass())) { + return false; + } + // specific equality check + Object lhsp = this.getTargetProperty(); + Object rhsp = arg.getTargetProperty(); + if (lhsp == null && rhsp == null) { + return true; + } + if (lhsp != null && rhsp != null) { + return lhsp.equals(rhsp); + } + return false; + } + /** * Tell whether the executor is alive by looking * at the value of the method. @@ -108,6 +148,22 @@ } /** + * Gets the object class targeted by this executor. + * @return the target object class + */ + public final Class<?> getTargetClass() { + return objectClass; + } + + /** + * Gets the property targeted by this executor. + * @return the target property + */ + public Object getTargetProperty() { + return null; + } + + /** * Gets the method name used. * @return method name */ @@ -147,6 +203,12 @@ /** * Tries to reuse this executor, checking that it is compatible with * the actual set of arguments. + * <p>Compatibility means that: + * <code>o</code> must be of the same class as this executor's + * target class and + * <code>property</code> must be of the same class as this + * executor's target property (for list and map based executors) and have the same + * value (for other types).</p> * @param o The object to get the property from. * @param property The property to get from the object. * @return The property value or TRY_FAILED if checking failed. @@ -189,6 +251,14 @@ /** * Tries to reuse this executor, checking that it is compatible with * the actual set of arguments. + * <p>Compatibility means that: + * <code>o</code> must be of the same class as this executor's + * target class, + * <code>property</code> must be of the same class as this + * executor's target property (for list and map based executors) and have the same + * value (for other types) + * and that <code>arg</code> must be a valid argument for this + * executor underlying method.</p> * @param o The object to invoke the method from. * @param property The property to set in the object. * @param arg The value to use as the property value. @@ -240,6 +310,12 @@ return execute(o, args); } + /** {...@inheritdoc} */ + @Override + public Object getTargetProperty() { + return key; + } + /** * Returns the return type of the method invoked. * @return return type Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/BooleanGetExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/BooleanGetExecutor.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/BooleanGetExecutor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/BooleanGetExecutor.java Mon Oct 12 16:46:15 2009 @@ -36,6 +36,12 @@ /** {...@inheritdoc} */ @Override + public Object getTargetProperty() { + return property; + } + + /** {...@inheritdoc} */ + @Override public Object execute(Object o) throws IllegalAccessException, InvocationTargetException { return method == null ? null : method.invoke(o, (Object[]) null); Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/DuckGetExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/DuckGetExecutor.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/DuckGetExecutor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/DuckGetExecutor.java Mon Oct 12 16:46:15 2009 @@ -47,6 +47,12 @@ property = identifier; } + /** {...@inheritdoc} */ + @Override + public Object getTargetProperty() { + return property; + } + /** * Get the property from the object. * @param o the object. Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/DuckSetExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/DuckSetExecutor.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/DuckSetExecutor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/DuckSetExecutor.java Mon Oct 12 16:46:15 2009 @@ -46,6 +46,12 @@ /** {...@inheritdoc} */ @Override + public Object getTargetProperty() { + return property; + } + + /** {...@inheritdoc} */ + @Override public Object execute(Object o, Object arg) throws IllegalAccessException, InvocationTargetException { Object[] pargs = {property, arg}; @@ -64,7 +70,8 @@ && objectClass.equals(o.getClass())) { try { Object[] args = {property, arg}; - return method.invoke(o, args); + method.invoke(o, args); + return arg; } catch (InvocationTargetException xinvoke) { return TRY_FAILED; // fail } catch (IllegalAccessException xill) { @@ -84,6 +91,6 @@ */ private static java.lang.reflect.Method discover(Introspector is, Class<?> clazz, Object identifier, Object arg) { - return is.getMethod(clazz, "put", makeArgs(identifier, arg)); + return is.getMethod(clazz, "set", makeArgs(identifier, arg)); } } \ No newline at end of file Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/Introspector.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/Introspector.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/Introspector.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/Introspector.java Mon Oct 12 16:46:15 2009 @@ -207,7 +207,7 @@ return executor; } } - // if that didn't work, look for get("foo") + // if that didn't work, look for set("foo") executor = new DuckGetExecutor(this, claz, identifier); if (executor.isAlive()) { return executor; Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/ListGetExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/ListGetExecutor.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/ListGetExecutor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/ListGetExecutor.java Mon Oct 12 16:46:15 2009 @@ -42,6 +42,12 @@ property = index; } + /** {...@inheritdoc} */ + @Override + public Object getTargetProperty() { + return property; + } + /** * Get the property from the list or array. * @param list the List/array. @@ -59,7 +65,7 @@ /** {...@inheritdoc} */ @Override public Object tryExecute(final Object list, Object index) { - if (method == discover(list.getClass()) + if (list != null && method != null && objectClass.equals(list.getClass()) && index instanceof Integer) { if (method == ARRAY_GET) { Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/ListSetExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/ListSetExecutor.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/ListSetExecutor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/ListSetExecutor.java Mon Oct 12 16:46:15 2009 @@ -45,6 +45,12 @@ /** {...@inheritdoc} */ @Override + public Object getTargetProperty() { + return property; + } + + /** {...@inheritdoc} */ + @Override public Object execute(final Object list, Object arg) { if (method == ARRAY_SET) { java.lang.reflect.Array.set(list, property.intValue(), arg); @@ -59,17 +65,17 @@ /** {...@inheritdoc} */ @Override public Object tryExecute(final Object list, Object index, Object arg) { - if (method == discover(list.getClass()) + if (list != null && method != null && objectClass.equals(list.getClass()) && index instanceof Integer) { - Integer idx = (Integer) index; - if (method == ARRAY_SET) { - java.lang.reflect.Array.set(list, idx.intValue(), arg); - } else { - @SuppressWarnings("unchecked") - final List<Object> asList = (List<Object>) list; - asList.set(idx.intValue(), arg); - } + if (method == ARRAY_SET) { + Array.set(list, (Integer) index, arg); + } else { + @SuppressWarnings("unchecked") + final List<Object> asList = (List<Object>) list; + asList.set((Integer) index, arg); + } + return arg; } return TRY_FAILED; } Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/MapGetExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/MapGetExecutor.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/MapGetExecutor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/MapGetExecutor.java Mon Oct 12 16:46:15 2009 @@ -40,6 +40,12 @@ property = key; } + /** {...@inheritdoc} */ + @Override + public Object getTargetProperty() { + return property; + } + /** * Get the property from the map. * @param map the map. @@ -55,7 +61,8 @@ @SuppressWarnings("unchecked") @Override public Object tryExecute(final Object map, Object key) { - if (objectClass.equals(map.getClass()) + if (map != null && method != null + && objectClass.equals(map.getClass()) && (key == null || property.getClass().equals(key.getClass()))) { return ((Map<Object, ?>) map).get(key); } Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/MapSetExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/MapSetExecutor.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/MapSetExecutor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/MapSetExecutor.java Mon Oct 12 16:46:15 2009 @@ -40,6 +40,12 @@ } /** {...@inheritdoc} */ + @Override + public Object getTargetProperty() { + return property; + } + + /** {...@inheritdoc} */ @SuppressWarnings("unchecked") @Override public Object execute(final Object map, Object value) @@ -52,9 +58,11 @@ @SuppressWarnings("unchecked") @Override public Object tryExecute(final Object map, Object key, Object value) { - if (objectClass.equals(map.getClass()) + if (map != null && method != null + && objectClass.equals(map.getClass()) && (key == null || property.getClass().equals(key.getClass()))) { - return ((Map<Object, Object>) map).put(key, value); + ((Map<Object, Object>) map).put(key, value); + return value; } return TRY_FAILED; } Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/PropertyGetExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/PropertyGetExecutor.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/PropertyGetExecutor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/PropertyGetExecutor.java Mon Oct 12 16:46:15 2009 @@ -40,6 +40,12 @@ /** {...@inheritdoc} */ @Override + public Object getTargetProperty() { + return property; + } + + /** {...@inheritdoc} */ + @Override public Object execute(Object o) throws IllegalAccessException, InvocationTargetException { return method == null ? null : method.invoke(o, (Object[]) null); Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/PropertySetExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/PropertySetExecutor.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/PropertySetExecutor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/util/PropertySetExecutor.java Mon Oct 12 16:46:15 2009 @@ -41,6 +41,12 @@ /** {...@inheritdoc} */ @Override + public Object getTargetProperty() { + return property; + } + + /** {...@inheritdoc} */ + @Override public Object execute(Object o, Object arg) throws IllegalAccessException, InvocationTargetException { Object[] pargs = {arg}; Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/CacheTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/CacheTest.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/CacheTest.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/CacheTest.java Mon Oct 12 16:46:15 2009 @@ -162,7 +162,7 @@ throw new RuntimeException("no such property"); } - public void put(String p, Object v) { + public void set(String p, Object v) { if (v == null) { v = "na"; } Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/JexlTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/JexlTest.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/JexlTest.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/JexlTest.java Mon Oct 12 16:46:15 2009 @@ -755,7 +755,7 @@ return -1; } @SuppressWarnings("boxing") - public void put(String val, Object value) { + public void set(String val, Object value) { if ("user".equals(val)) { if ("zero".equals(value)) user = 0; Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/util/introspection/DiscoveryTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/util/introspection/DiscoveryTest.java?rev=824414&r1=824413&r2=824414&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/util/introspection/DiscoveryTest.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/util/introspection/DiscoveryTest.java Mon Oct 12 16:46:15 2009 @@ -21,9 +21,14 @@ import java.util.List; import java.util.Map; -import junit.framework.TestCase; +import org.apache.commons.jexl.JexlTestCase; import org.apache.commons.jexl.util.Introspector; +import org.apache.commons.jexl.util.AbstractExecutor; +import org.apache.commons.jexl.util.PropertyGetExecutor; +import org.apache.commons.jexl.util.PropertySetExecutor; +import org.apache.commons.jexl.util.DuckGetExecutor; +import org.apache.commons.jexl.util.DuckSetExecutor; import org.apache.commons.jexl.util.ListGetExecutor; import org.apache.commons.jexl.util.ListSetExecutor; import org.apache.commons.jexl.util.MapGetExecutor; @@ -34,30 +39,180 @@ * * @since 2.0 */ -public class DiscoveryTest extends TestCase { +public class DiscoveryTest extends JexlTestCase { - public void testListIntrospection() throws Exception { + public static class Duck { + private String value; + private String eulav; + public Duck(String v, String e) { + value = v; + eulav = e; + } + public String get(String prop) { + if ("value".equals(prop)) { + return value; + } + if ("eulav".equals(prop)) { + return eulav; + } + return "no such property"; + } + public void set(String prop, String v) { + if ("value".equals(prop)) { + value = v; + } else if ("eulav".equals(prop)) { + eulav = v; + } + } + } + + public static class Bean { + private String value; + private String eulav; + private boolean flag; + public Bean(String v, String e) { + value = v; + eulav = e; + flag = true; + } + public String getValue() { + return value; + } + public void setValue(String v) { + value = v; + } + public String getEulav() { + return eulav; + } + public void setEulav(String v) { + eulav = v; + } + public boolean isFlag() { + return flag; + } + public void setFlag(boolean f) { + flag = f; + } + } + + + public void testBeanIntrospection() throws Exception { Uberspect uber = Introspector.getUberspect(); Introspector intro = (Introspector) uber; - List<Object> list = new ArrayList<Object>(); + Bean bean = new Bean("JEXL", "LXEJ"); - assertTrue(intro.getGetExecutor(list, "1") instanceof ListGetExecutor); - assertTrue(intro.getSetExecutor(list, "1", "foo") instanceof ListSetExecutor); + AbstractExecutor.Get get = intro.getGetExecutor(bean, "value"); + AbstractExecutor.Set set = intro.getSetExecutor(bean, "value", "foo"); + assertTrue("bean property getter", get instanceof PropertyGetExecutor); + assertTrue("bean property setter", set instanceof PropertySetExecutor); + // introspector and uberspect should return same result + assertEquals(get, uber.getPropertyGet(bean, "value", null)); + assertEquals(set, uber.getPropertySet(bean, "value", "foo", null)); + // different property should return different setter/getter + assertFalse(get.equals(intro.getGetExecutor(bean, "eulav"))); + assertFalse(set.equals(intro.getSetExecutor(bean, "eulav", "foo"))); + // setter returns argument + Object bar = set.execute(bean, "bar"); + assertEquals("bar", bar); + // getter should return last value + assertEquals("bar", get.execute(bean)); + // tryExecute should succeed on same property + Object quux = set.tryExecute(bean, "value", "quux"); + assertEquals("quux", quux); + assertEquals("quux", get.execute(bean)); + // tryExecute should fail on different property + assertEquals(AbstractExecutor.TRY_FAILED, set.tryExecute(bean, "eulav", "nope")); - assertTrue(uber.getPropertyGet(list, "1", null) instanceof ListGetExecutor); - assertTrue(uber.getPropertySet(list, "1", "foo", null) instanceof ListSetExecutor); } - public void testMapIntrospection() throws Exception { + public void testDuckIntrospection() throws Exception { Uberspect uber = Introspector.getUberspect(); Introspector intro = (Introspector) uber; - Map<String, Object> list = new HashMap<String, Object>(); + Duck duck = new Duck("JEXL", "LXEJ"); - assertTrue(intro.getGetExecutor(list, "foo") instanceof MapGetExecutor); - assertTrue(intro.getSetExecutor(list, "foo", "bar") instanceof MapSetExecutor); + AbstractExecutor.Get get = intro.getGetExecutor(duck, "value"); + AbstractExecutor.Set set = intro.getSetExecutor(duck, "value", "foo"); + assertTrue("duck property getter", get instanceof DuckGetExecutor); + assertTrue("duck property setter", set instanceof DuckSetExecutor); + // introspector and uberspect should return same result + assertEquals(get, (AbstractExecutor) uber.getPropertyGet(duck, "value", null)); + assertEquals(set, uber.getPropertySet(duck, "value", "foo", null)); + // different property should return different setter/getter + assertFalse(get.equals(intro.getGetExecutor(duck, "eulav"))); + assertFalse(set.equals(intro.getSetExecutor(duck, "eulav", "foo"))); + // setter returns argument + Object bar = set.execute(duck, "bar"); + assertEquals("bar", bar); + // getter should return last value + assertEquals("bar", get.execute(duck)); + // tryExecute should succeed on same property + Object quux = set.tryExecute(duck, "value", "quux"); + assertEquals("quux", quux); + assertEquals("quux", get.execute(duck)); + // tryExecute should fail on different property + assertEquals(AbstractExecutor.TRY_FAILED, set.tryExecute(duck, "eulav", "nope")); + } - assertTrue(uber.getPropertyGet(list, "foo", null) instanceof MapGetExecutor); - assertTrue(uber.getPropertySet(list, "foo", "bar", null) instanceof MapSetExecutor); + public void testListIntrospection() throws Exception { + Uberspect uber = Introspector.getUberspect(); + Introspector intro = (Introspector) uber; + List<Object> list = new ArrayList<Object>(); + list.add("LIST"); + list.add("TSIL"); + + AbstractExecutor.Get get = intro.getGetExecutor(list, 1); + AbstractExecutor.Set set = intro.getSetExecutor(list, 1, "foo"); + assertTrue("list property getter", get instanceof ListGetExecutor); + assertTrue("list property setter", set instanceof ListSetExecutor); + // introspector and uberspect should return same result + assertEquals(get, uber.getPropertyGet(list, 1, null)); + assertEquals(set, uber.getPropertySet(list, 1, "foo", null)); + // different property should return different setter/getter + assertFalse(get.equals(intro.getGetExecutor(list, 0))); + assertFalse(get.equals(intro.getSetExecutor(list, 0, "foo"))); + // setter returns argument + Object bar = set.execute(list, "bar"); + assertEquals("bar", bar); + // getter should return last value + assertEquals("bar", get.execute(list)); + // tryExecute should succeed on integer property + Object quux = set.tryExecute(list, 1, "quux"); + assertEquals("quux", quux); + // getter should return last value + assertEquals("quux", get.execute(list)); + // tryExecute should fail on non-integer property class + assertEquals(AbstractExecutor.TRY_FAILED, set.tryExecute(list, "eulav", "nope")); + } + + public void testMapIntrospection() throws Exception { + Uberspect uber = Introspector.getUberspect(); + Introspector intro = (Introspector) uber; + Map<String, Object> map = new HashMap<String, Object>(); + map.put("value", "MAP"); + map.put("eulav", "PAM"); + + AbstractExecutor.Get get = intro.getGetExecutor(map, "value"); + AbstractExecutor.Set set = intro.getSetExecutor(map, "value", "foo"); + assertTrue("map property getter", get instanceof MapGetExecutor); + assertTrue("map property setter", set instanceof MapSetExecutor); + // introspector and uberspect should return same result + assertEquals(get, uber.getPropertyGet(map, "value", null)); + assertEquals(set, uber.getPropertySet(map, "value", "foo", null)); + // different property should return different setter/getter + assertFalse(get.equals(intro.getGetExecutor(map, "eulav"))); + assertFalse(get.equals(intro.getSetExecutor(map, "eulav", "foo"))); + // setter returns argument + Object bar = set.execute(map, "bar"); + assertEquals("bar", bar); + // getter should return last value + assertEquals("bar", get.execute(map)); + // tryExecute should succeed on same property class + Object quux = set.tryExecute(map, "value", "quux"); + assertEquals("quux", quux); + // getter should return last value + assertEquals("quux", get.execute(map)); + // tryExecute should fail on different property class + assertEquals(AbstractExecutor.TRY_FAILED, set.tryExecute(map, 1, "nope")); } }