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