Permalink
Browse files

Fix #76, #77, #78, #79

- add sortArray and sortList to SortContext for backwards support (marked deprecated)
- cleaned up SortContext for consistency and performance
- add HTMLContext for HTML-based pagination support for legacy support
- updated BeanAnalzyer to attempt to fix bridge method issues
- add missing messages in type checker properties
  • Loading branch information...
Nicholas Hagen
Nicholas Hagen committed Apr 11, 2012
1 parent c787619 commit d81feffad7c7c92f9dd11ef0681d2de2f2e6068f
@@ -1550,7 +1550,7 @@ protected Expression checkForTypeExpression(Expression expr) {
}
// otherwise, fail with unknown variable
- error("variable.not.declared", expr);
+ error("variable.not.declared", name, expr);
return null;
}
}
@@ -1619,7 +1619,7 @@ else if (expr instanceof Lookup) {
}
// otherwise, fail with unknown variable
- error("variable.not.declared", expr);
+ error("variable.not.declared", name, expr);
return null;
}
}
@@ -69,19 +69,6 @@
createPropertiesCache() {
return Collections.synchronizedMap(new IdentityMap(32768));
}
-
- /**
- * Test program.
- */
- public static void main(String[] args) throws Exception {
- Map<String, PropertyDescriptor> map = getAllProperties(new GenericType(Class.forName(args[0])));
- Iterator<String> keys = map.keySet().iterator();
- while (keys.hasNext()) {
- String key = (String)keys.next();
- PropertyDescriptor desc = (PropertyDescriptor)map.get(key);
- System.out.println(key + " = " + desc);
- }
- }
/**
* A function that returns a Map of all the available properties on
@@ -157,7 +144,59 @@ public static void main(String[] args) throws Exception {
for (int i=0; i<length; i++) {
PropertyDescriptor desc = pdArray[i];
// This check will discard standard pure indexed properties.
- if (desc.getPropertyType() != null) {
+ Class<?> propertyType = desc.getPropertyType();
+ if (propertyType != null) {
+ boolean modified = false;
+
+ // check if read method is bridge and lookup real method
+ Method readMethod = desc.getReadMethod();
+ if (readMethod != null && readMethod.isBridge()) {
+ try {
+ readMethod = clazz.getMethod(
+ readMethod.getName()
+ );
+
+ modified = true;
+ propertyType = readMethod.getReturnType();
+ }
+ catch (NoSuchMethodException nsme) {
+ // ignore and use existing method
+ }
+ catch (Exception e) {
+ throw new IntrospectionException(e.toString());
+ }
+ }
+
+ // check if write method is bridge and lookup real method
+ Method writeMethod = desc.getWriteMethod();
+ if (writeMethod != null && writeMethod.isBridge()) {
+ try {
+ writeMethod = clazz.getMethod(
+ writeMethod.getName(), propertyType
+ );
+
+ modified = true;
+ }
+ catch (NoSuchMethodException nsme) {
+ // ignore and use existing method
+ }
+ catch (Exception e) {
+ throw new IntrospectionException(e.toString());
+ }
+ }
+
+ // overwrite the methods if they were modified...note that
+ // we must set writeMethod to null first since invoking the
+ // setter will attempt to vaildate the types are the same
+ // which may not be the case if the read method was setup
+ // incorrectly with its bridge type
+ if (modified) {
+ desc.setWriteMethod(null);
+ desc.setReadMethod(readMethod);
+ desc.setWriteMethod(writeMethod);
+ }
+
+ // save the property
properties.put(desc.getName(), desc);
}
}
@@ -326,14 +365,14 @@ else if (String.class.isAssignableFrom(clazz)) {
properties.put(KEYED_PROPERTY_NAME, keyed);
int size = keyedMethods.size();
- keyed.setKeyedReadMethods
- ((Method[])keyedMethods.toArray(new Method[size]));
+ keyed.setKeyedReadMethods(
+ keyedMethods.toArray(new Method[size]));
}
// Filter out properties with names that contain '$' characters.
Iterator<String> it = properties.keySet().iterator();
while (it.hasNext()) {
- String propertyName = (String)it.next();
+ String propertyName = it.next();
if (propertyName.indexOf('$') >= 0) {
it.remove();
}
@@ -17,6 +17,8 @@ variable.declared=\
Variable ''{0}'' already declared
variable.declared.here=\
Variable ''{0}'' declared here
+variable.not.declared=\
+ Variable ''{0}'' not declared
variable.undefined=\
Internal error: variable ''{0}'' undefined
variable.primitive.uninitialized=\
@@ -29,6 +29,7 @@ public void testSpread() throws Exception {
assertEquals("11", executeTest(TEST_SOURCE_11));
assertEquals("44", executeTest(TEST_SOURCE_12));
assertEquals("11", executeTest(TEST_SOURCE_13));
+ assertEquals("java.lang.Integer", executeTest(TEST_SOURCE_14));
}
protected String executeTest(String source) throws Exception {
@@ -37,6 +38,11 @@ protected String executeTest(String source) throws Exception {
}
public static class VarargsContext {
+
+ public Number getRandom() {
+ return Integer.valueOf(1);
+ }
+
public String doSomething(String test, Object... blah) {
return "1";
}
@@ -124,4 +130,7 @@ public VarargsContext getContext() {
protected static final String TEST_SOURCE_13 =
"doSomething('test', 5.2, 2.3, 2.9, 'test');" +
"getContext()?.doSomething('test', 5.2, 2.3, 2.9, 'test');"; // 1
+
+ protected static final String TEST_SOURCE_14 =
+ "a = getRandom(); b = getRandom(); c = a + b; c.class.name";
}
@@ -0,0 +1,49 @@
+package org.teatrove.tea.util;
+
+import static org.junit.Assert.assertEquals;
+
+import java.beans.PropertyDescriptor;
+import java.util.Map;
+
+import org.junit.Test;
+import org.teatrove.trove.generics.GenericType;
+
+public class BeanAnalyzerTest {
+
+ @Test
+ public void testCovariants() throws Exception {
+ Map<String, PropertyDescriptor> properties =
+ BeanAnalyzer.getAllProperties(new GenericType(Int.class));
+ PropertyDescriptor value = properties.get("value");
+ assertEquals(Integer.class, value.getPropertyType());
+ assertEquals(Integer.class, value.getReadMethod().getReturnType());
+ }
+
+ @Test
+ public void testGenerics() throws Exception {
+ Map<String, PropertyDescriptor> properties =
+ BeanAnalyzer.getAllProperties(new GenericType(IntGenerics.class));
+ PropertyDescriptor value = properties.get("value");
+ assertEquals(Integer.class, value.getPropertyType());
+ assertEquals(Integer.class, value.getReadMethod().getReturnType());
+ assertEquals(Integer.class, value.getWriteMethod().getParameterTypes()[0]);
+ }
+
+ public static class Base {
+ public Number getValue() { return null; }
+ }
+
+ public static class Int extends Base {
+ public Integer getValue() { return null; }
+ }
+
+ public static class BaseGenerics<T extends Number> {
+ public T getValue() { return null; }
+ public void setValue(T value) { }
+ }
+
+ public static class IntGenerics extends BaseGenerics<Integer> {
+ public Integer getValue() { return null; }
+ public void setValue(Integer value) { }
+ }
+}
@@ -24,7 +24,24 @@
* @author Nicholas Hagen
*/
public class ArrayContext {
-
+
+ /**
+ * Clone the given array into a new instance of the same type and
+ * dimensions. The values are directly copied by memory, so this is not
+ * a deep clone operation. However, manipulation of the contents of the
+ * array will not impact the given array.
+ *
+ * @param array The array to clone
+ *
+ * @return The new cloned array
+ */
+ public Object[] cloneArray(Object[] array) {
+ Class<?> clazz = array.getClass().getComponentType();
+ Object newArray = Array.newInstance(clazz, array.length);
+ System.arraycopy(array, 0, newArray, 0, array.length);
+ return (Object[]) newArray;
+ }
+
/**
* Determine whether the provided object is an array or not. This returns
* <code>true</code> if the object is non-<code>null</code> and the class
Oops, something went wrong.

0 comments on commit d81feff

Please sign in to comment.