Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- 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 committed Apr 11, 2012
1 parent c787619 commit d81feff
Show file tree
Hide file tree
Showing 11 changed files with 849 additions and 120 deletions.
4 changes: 2 additions & 2 deletions tea/src/main/java/org/teatrove/tea/compiler/TypeChecker.java
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
}
}
Expand Down
73 changes: 56 additions & 17 deletions tea/src/main/java/org/teatrove/tea/util/BeanAnalyzer.java
Expand Up @@ -69,19 +69,6 @@ public class BeanAnalyzer {
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
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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();
}
Expand Down
Expand Up @@ -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=\
Expand Down
9 changes: 9 additions & 0 deletions tea/src/test/java/org/teatrove/tea/templates/VarargsTest.java
Expand Up @@ -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 {
Expand All @@ -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";
}
Expand Down Expand Up @@ -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";
}
49 changes: 49 additions & 0 deletions tea/src/test/java/org/teatrove/tea/util/BeanAnalyzerTest.java
@@ -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) { }
}
}
Expand Up @@ -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
Expand Down

0 comments on commit d81feff

Please sign in to comment.