Revision: 761
          http://stripes.svn.sourceforge.net/stripes/?rev=761&view=rev
Author:   tfenne
Date:     2008-01-18 18:22:35 -0800 (Fri, 18 Jan 2008)

Log Message:
-----------
Big hairy fix for STS-427.  Not convinced it fixes all possible cases, but it 
fixes all cases for which we have test cases!  Ha!

Modified Paths:
--------------
    
trunk/stripes/src/net/sourceforge/stripes/util/bean/PropertyExpressionEvaluation.java
    trunk/tests/src/net/sourceforge/stripes/controller/GenericsBindingTests.java
    
trunk/tests/src/net/sourceforge/stripes/controller/GenericsBindingTestsBaseClass.java
    trunk/tests/src/net/sourceforge/stripes/test/TestGenericBean.java

Modified: 
trunk/stripes/src/net/sourceforge/stripes/util/bean/PropertyExpressionEvaluation.java
===================================================================
--- 
trunk/stripes/src/net/sourceforge/stripes/util/bean/PropertyExpressionEvaluation.java
       2008-01-18 23:16:25 UTC (rev 760)
+++ 
trunk/stripes/src/net/sourceforge/stripes/util/bean/PropertyExpressionEvaluation.java
       2008-01-19 02:22:35 UTC (rev 761)
@@ -389,17 +389,21 @@
     /**
      * Scans backwards in the expression for the last node which contained a 
JavaBean type
      * and attempts to use the type arguments to that class to find a match 
for the
-     * TypeParameter provided.
+     * TypeParameter provided.  On it's way also collects information from any 
parameterized
+     * types and their super-types.
      *
      * @param evaluation the current NodeEvaluation
      * @param typeVar the TypeVariable to try and find a more concrete type for
      * @return the actual type argument for the type variable if possible, or 
null
      */
     protected Type getTypeVariableValue(NodeEvaluation evaluation, 
TypeVariable<?> typeVar) {
+        // Type maps from TypeVariables to the corresponding Type.  The first 
map contains entries
+        // from parameterized types (and their super-types) discovered while 
going back up the
+        // nodes.  The second map contains information gathered by going up 
the superclasses
+        // from the last concrete Class in the expression
+        List<HashMap<TypeVariable<?>, Type>> typemap1 = new 
ArrayList<HashMap<TypeVariable<?>, Type>>();
+        List<HashMap<TypeVariable<?>, Type>> typemap2 = new 
ArrayList<HashMap<TypeVariable<?>, Type>>();
 
-        // Type map from TypeVariables to the corresponding Type.
-        List<HashMap<TypeVariable<?>, Type>> typemap = new 
ArrayList<HashMap<TypeVariable<?>, Type>>();
-
         // Scan the evaluation chain for the first class or any parameterized 
types.
         Class<?> lastBean = this.bean.getClass();
         for (NodeEvaluation n = evaluation.getPrevious(); n != null; n = 
n.getPrevious()) {
@@ -409,10 +413,22 @@
             if (type instanceof Class) {
                 lastBean = (Class<?>) n.getValueType();
                 break;
+            }
+            // Parameterized type?  Add to the typemap along with parent 
parameterized types
+            else if (type instanceof ParameterizedType) {
+                ParameterizedType ptype = (ParameterizedType) type;
 
-            // Parameterized type?  Add to the typemap and keep going.
-            } else if (type instanceof ParameterizedType) {
-                addTypeMappings(typemap, (ParameterizedType) type);
+                while (ptype != null) {
+                    addTypeMappings(typemap1, ptype);
+
+                    // Now find the parent of the ptype and see if it's a 
ptype too!
+                    Type rawtype = ptype.getRawType();
+                    if (rawtype instanceof Class) {
+                        Class<?> superclass = (Class) rawtype;
+                        Type supertype = superclass.getGenericSuperclass();
+                        ptype = (supertype instanceof ParameterizedType) ?  
(ParameterizedType) supertype : null;
+                    }
+                }
             }
         }
 
@@ -420,27 +436,41 @@
         for (Class<?> c = lastBean; c != null; c = c.getSuperclass()) {
             Type t = c.getGenericSuperclass();
             if (t instanceof ParameterizedType) {
-                addTypeMappings(typemap, (ParameterizedType) t);
+                addTypeMappings(typemap2, (ParameterizedType) t);
             }
         }
 
-        // Now traverse the typemap list, mapping the TypeVariable.
+        Class<?> declaration = (Class) typeVar.getGenericDeclaration();
         Type type = null;
-        for (int i = typemap.size() - 1; i >= 0; i--) {
 
+        // If the type variable doesn't come from a direct superclass of the
+        // the last bean, check the mappings from parameterized types first
+        if (!declaration.isAssignableFrom(lastBean)) {
+            for (int i = typemap1.size() - 1; i >= 0; i--) {
+                // Map the type variable to a type.
+                if ((type = typemap1.get(i).get(typeVar)) != null) {
+                    // Reached a real class?  Done.
+                    if (type instanceof Class) { return type; }
+                    else if (type instanceof TypeVariable) {
+                        typeVar = (TypeVariable<?>) type;
+                    }
+                }
+            }
+        }
+
+        // If we did the above traverse and still ended up at another type
+        // variable, check the last bean (and parents') mappings
+        for (int i = typemap2.size() - 1; i >= 0; i--) {
             // Map the type variable to a type.
-            if ((type = typemap.get(i).get(typeVar)) != null) {
-
+            if ((type = typemap2.get(i).get(typeVar)) != null) {
                 // Reached a real class?  Done.
-                if (type instanceof Class) {
-                    break;
-
-                // Another TypeVariable? Keep going.
-                } else if (type instanceof TypeVariable) {
+                if (type instanceof Class) { return type; }
+                else if (type instanceof TypeVariable) {
                     typeVar = (TypeVariable<?>) type;
                 }
             }
         }
+
         return type;
     }
 
@@ -453,8 +483,7 @@
     *
     * @param paramType parameterized type to add to the map.
     */
-    private void addTypeMappings(List<HashMap<TypeVariable<?>, Type>> typemap,
-      ParameterizedType paramType) {
+    private void addTypeMappings(List<HashMap<TypeVariable<?>, Type>> typemap, 
ParameterizedType paramType) {
         Type rawType = paramType.getRawType();
         if (rawType instanceof Class) {
             Class<?> rawClass = (Class<?>) rawType;

Modified: 
trunk/tests/src/net/sourceforge/stripes/controller/GenericsBindingTests.java
===================================================================
--- 
trunk/tests/src/net/sourceforge/stripes/controller/GenericsBindingTests.java    
    2008-01-18 23:16:25 UTC (rev 760)
+++ 
trunk/tests/src/net/sourceforge/stripes/controller/GenericsBindingTests.java    
    2008-01-19 02:22:35 UTC (rev 761)
@@ -8,11 +8,13 @@
 import net.sourceforge.stripes.action.Resolution;
 import net.sourceforge.stripes.mock.MockRoundtrip;
 import net.sourceforge.stripes.test.TestBean;
+import net.sourceforge.stripes.test.TestGenericBean;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import java.util.Calendar;
 import java.util.Date;
+import java.lang.reflect.Method;
 
 /**
  *

Modified: 
trunk/tests/src/net/sourceforge/stripes/controller/GenericsBindingTestsBaseClass.java
===================================================================
--- 
trunk/tests/src/net/sourceforge/stripes/controller/GenericsBindingTestsBaseClass.java
       2008-01-18 23:16:25 UTC (rev 760)
+++ 
trunk/tests/src/net/sourceforge/stripes/controller/GenericsBindingTestsBaseClass.java
       2008-01-19 02:22:35 UTC (rev 761)
@@ -13,7 +13,7 @@
  */
 public class GenericsBindingTestsBaseClass<JB,N,E,K,V> {
     JB bean;
-    TestGenericBean<N,E> genericBean;
+    TestGenericBean.GenericBean<N,E> genericBean;
     N number;
     List<? extends E> list;
     Map<K,V> map;
@@ -21,8 +21,8 @@
     public JB getBean() { return bean; }
     public void setBean(JB bean) { this.bean = bean; }
 
-    public TestGenericBean<N,E> getGenericBean() { return genericBean; }
-    public void setGenericBean(TestGenericBean<N,E> genericBean) { 
this.genericBean = genericBean; }
+    public TestGenericBean.GenericBean<N,E> getGenericBean() { return 
genericBean; }
+    public void setGenericBean(TestGenericBean.GenericBean<N,E> genericBean) { 
this.genericBean = genericBean; }
 
     public N getNumber() { return number; }
     public void setNumber(N number) { this.number = number; }

Modified: trunk/tests/src/net/sourceforge/stripes/test/TestGenericBean.java
===================================================================
--- trunk/tests/src/net/sourceforge/stripes/test/TestGenericBean.java   
2008-01-18 23:16:25 UTC (rev 760)
+++ trunk/tests/src/net/sourceforge/stripes/test/TestGenericBean.java   
2008-01-19 02:22:35 UTC (rev 761)
@@ -1,5 +1,7 @@
 package net.sourceforge.stripes.test;
 
+import java.lang.reflect.Method;
+
 /**
  * A JavaBean that is a generic type.
  *
@@ -13,24 +15,21 @@
  *     class Class2<B,A> extends Class1<B,A> {}
  *     class Class3<X,Y> extends Class2<X,Y> {}
  *     public class TestGenericBean<A,B> extends Class3<A,B> {}
- * Stripes will fail to bind the properties of Class1 correctly.  See STS-XXX
+ * Stripes will fail to bind the properties of Class1 correctly.  See STS-427
  */
-public class TestGenericBean<A,B> {
-    private A genericA;
-    private B genericB;
-
-    public A getGenericA() {
-        return genericA;
+public class TestGenericBean {
+    public static class Class1<A,B> {
+        private A genericA;
+        private B genericB;
+        public A getGenericA() { return genericA; }
+        public void setGenericA(A genericA) { this.genericA = genericA; }
+        public B getGenericB() { return genericB; }
+        public void setGenericB(B genericB) { this.genericB = genericB; }
     }
-    public void setGenericA(A genericA) {
-        this.genericA = genericA;
-    }
 
-    public B getGenericB() {
-        return genericB;
-    }
+    public static class Class2<B,A> extends Class1<B,A> {}
+    public static class Class3<A,B> extends Class2<A,B> {}
 
-    public void setGenericB(B genericB) {
-        this.genericB = genericB;
-    }
-}
\ No newline at end of file
+    public static class GenericBean<G,H> extends Class3<G,H> {}
+}
+


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to