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"));
     }
 
 }


Reply via email to