package org.mvel2.compiler;
import junit.framework.TestCase;
import org.mvel2.MVEL;
import org.mvel2.ParserContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Asserts that the element at the end of the parse chain has its type parameter correctly inferred
* IF the egress type is a parametric type (i.e. generic).
*
* @author Dhanji R. Prasanna (dhanji@gmail com)
*/
public class GenericsTypeInferenceTest extends TestCase {
private static final List<String> STRINGS = Arrays.asList("hi", "there", "dude");
public final void testInferLastTypeParametersFromProperty() {
ParserContext context = new ParserContext();
context.setStrongTyping(true);
context.addInput("a", A.class);
final CompiledExpression compiledExpression = new ExpressionCompiler("a.strings", context)
.compile();
final Object val = MVEL.executeExpression(compiledExpression, new AWrapper());
assertTrue("Expression did not evaluate correctly: " + val, STRINGS.equals(val));
assertTrue("No type parameters detected", null != context.getLastTypeParameters());
assertTrue("Wrong parametric type inferred", String.class.equals(context.getLastTypeParameters()[0]));
}
public final void testInferLastTypeParametersFromMethod() {
ParserContext context = new ParserContext();
context.setStrongTyping(true);
context.addInput("a", A.class);
final CompiledExpression compiledExpression = new ExpressionCompiler("a.values()", context)
.compile();
final Object val = MVEL.executeExpression(compiledExpression, new AWrapper());
assertTrue("Expression did not evaluate correctly: " + val, STRINGS.equals(val));
assertTrue("No type parameters detected", null != context.getLastTypeParameters());
assertTrue("Wrong parametric type inferred", String.class.equals(context.getLastTypeParameters()[0]));
}
public final void testInferLastTypeParametersFromPropertyMethod() {
ParserContext context = new ParserContext();
context.setStrongTyping(true);
context.addInput("a", A.class);
final CompiledExpression compiledExpression = new ExpressionCompiler("a.getFooMap()[\"key\"].someMethod()", context)
.compile();
final Object val = MVEL.executeExpression(compiledExpression, new AWrapper());
assertEquals("Expression did not evaluate correctly: ", "bar", val);
assertNotNull("No type parameters detected", context.getLastTypeParameters());
assertEquals("Wrong parametric type inferred", String.class, context.getLastTypeParameters()[0]);
}
public final void testTypeByMethod() {
ParserContext context = new ParserContext();
context.setStrongTyping(true);
context.addInput("a", A.class);
CompiledExpression compiledExpression = new ExpressionCompiler("!a.show", context).compile();
assertEquals(Boolean.class, compiledExpression.getKnownEgressType());
}
// public final void testInferLastTypeParametersFromPropertyMethod2() {
// ParserContext context = new ParserContext();
// context.setStrictTypeEnforcement( true );
//
// context.addInput("a", A.class);
//
// ExpressionCompiler compiler = new ExpressionCompiler("a.getBarMap()[\"key\"].someMethod();");
// final CompiledExpression compiledExpression = compiler.compileShared(context);
//
// Map<String,Object> vars = new HashMap<String,Object>();
// vars.put( "a", new A() );
// final Object val = MVEL.executeExpression(compiledExpression, vars);
//
// assertEquals("Expression did not evaluate correctly: ", "bar", val);
// assertNotNull("No type parameters detected", context.getLastTypeParameters());
// assertEquals("Wrong parametric type inferred", String.class, context.getLastTypeParameters()[0]);
// }
public static class AWrapper {
public A getA() {
return new A();
}
}
public static class A {
private boolean show;
public boolean isShow() {
return show;
}
public void setShow(boolean show) {
this.show = show;
}
public List<String> getStrings() {
return STRINGS;
}
public List<String> values() {
return STRINGS;
}
public Map<String, Foo> getFooMap() {
Map<String, Foo> map = new HashMap<String, Foo>();
map.put("key", new Foo() {
public String someMethod() {
return "bar";
}
});
return map;
}
public Map<String, Foo> getBarMap() {
Map<String, Foo> map = new HashMap<String, Foo>();
map.put("key", new FooImpl());
return map;
}
}
public static interface Foo {
public String someMethod();
}
public static class FooImpl implements Foo {
public String someMethod() {
return "bar";
}
}
public static class Amazed1 {
private List list = new ArrayList();
public List<Integer> getList() {
return this.list;
}
}
public static class Amazed2 {
private List list = new ArrayList();
public List getList() {
return this.list;
}
}
public void testAmazed() {
MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL = true;
try {
ParserContext context = new ParserContext();
context.setStrongTyping(true);
context.addInput("this",
Amazed1.class);
ExecutableStatement stmt = (ExecutableStatement) MVEL.compileExpression("list.size", context);
Amazed1 a1 = new Amazed1();
assertEquals(new Integer(0), MVEL.executeExpression(stmt, a1));
context = new ParserContext();
context.setStrongTyping(true);
context.addInput("this",
Amazed2.class);
stmt = (ExecutableStatement) MVEL.compileExpression("list.size", context);
Amazed2 a2 = new Amazed2();
assertEquals(new Integer(0), MVEL.executeExpression(stmt, a2));
}
finally {
MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL = false;
}
}
}