mirror of
https://github.com/querydsl/querydsl.git
synced 2026-07-03 21:07:49 +08:00
added support for constants in Evaluator
This commit is contained in:
parent
4c284540c4
commit
d43c95d623
@ -5,7 +5,9 @@
|
||||
*/
|
||||
package com.mysema.codegen;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -27,6 +29,18 @@ public final class ClassUtils {
|
||||
return cl.getName().replace('$', '.');
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> normalize(Class<?> clazz){
|
||||
if (List.class.isAssignableFrom(clazz)){
|
||||
return List.class;
|
||||
}else if (Set.class.isAssignableFrom(clazz)){
|
||||
return Set.class;
|
||||
}else if (Collection.class.isAssignableFrom(clazz)){
|
||||
return Collection.class;
|
||||
}else{
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
private ClassUtils(){}
|
||||
}
|
||||
|
||||
@ -9,12 +9,14 @@ import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
@ -54,7 +56,7 @@ public class EvaluatorFactory {
|
||||
}
|
||||
|
||||
private void compile(String source, Class<?> projectionType,
|
||||
String[] names, Class<?>[] types, String id) throws IOException {
|
||||
String[] names, Class<?>[] types, String id, Map<String,Object> constants) throws IOException {
|
||||
// create source
|
||||
StringWriter writer = new StringWriter();
|
||||
JavaWriter javaw = new JavaWriter(writer);
|
||||
@ -63,8 +65,17 @@ public class EvaluatorFactory {
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
params[i] = ClassUtils.getName(types[i]) + " " + names[i];
|
||||
}
|
||||
|
||||
for (Map.Entry<String,Object> entry : constants.entrySet()){
|
||||
String className = ClassUtils.getName(ClassUtils.normalize(entry.getValue().getClass()));
|
||||
javaw.publicField(className, entry.getKey());
|
||||
}
|
||||
|
||||
javaw.beginStaticMethod(ClassUtils.getName(projectionType), "eval", params);
|
||||
if (constants.isEmpty()){
|
||||
javaw.beginStaticMethod(ClassUtils.getName(projectionType), "eval", params);
|
||||
}else{
|
||||
javaw.beginPublicMethod(ClassUtils.getName(projectionType), "eval", params);
|
||||
}
|
||||
javaw.line("return ", source, ";");
|
||||
javaw.end();
|
||||
javaw.end();
|
||||
@ -94,10 +105,14 @@ public class EvaluatorFactory {
|
||||
* @param projectionType type of the source expression
|
||||
* @param names names of the arguments
|
||||
* @param types types of the arguments
|
||||
* @param constants
|
||||
* @return
|
||||
*/
|
||||
public <T> Evaluator<T> createEvaluator(String source,
|
||||
final Class<? extends T> projectionType, String[] names, Class<?>[] types) {
|
||||
public <T> Evaluator<T> createEvaluator(
|
||||
String source,
|
||||
final Class<? extends T> projectionType,
|
||||
String[] names, Class<?>[] types,
|
||||
Map<String,Object> constants) {
|
||||
|
||||
try {
|
||||
String id = toId(source, projectionType, types);
|
||||
@ -105,10 +120,17 @@ public class EvaluatorFactory {
|
||||
try{
|
||||
clazz = loader.loadClass(id);
|
||||
}catch(ClassNotFoundException e){
|
||||
compile(source, projectionType, names, types, id);
|
||||
compile(source, projectionType, names, types, id, constants);
|
||||
// reload
|
||||
clazz = loader.loadClass(id);
|
||||
}
|
||||
|
||||
final Object object = !constants.isEmpty() ? clazz.newInstance() : null;
|
||||
|
||||
for (Map.Entry<String, Object> entry : constants.entrySet()){
|
||||
Field field = clazz.getField(entry.getKey());
|
||||
field.set(object, entry.getValue());
|
||||
}
|
||||
|
||||
final Method method = clazz.getMethod("eval", types);
|
||||
return new Evaluator<T>() {
|
||||
@ -116,7 +138,7 @@ public class EvaluatorFactory {
|
||||
@Override
|
||||
public T evaluate(Object... args) {
|
||||
try {
|
||||
return (T) method.invoke(null, args);
|
||||
return (T) method.invoke(object, args);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
@ -135,14 +157,20 @@ public class EvaluatorFactory {
|
||||
throw new CodegenException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new CodegenException(e);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new CodegenException(e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new CodegenException(e);
|
||||
} catch (IOException e) {
|
||||
throw new CodegenException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new CodegenException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new CodegenException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected String toId(String source, Class<?> returnType, Class<?>... types) {
|
||||
StringBuilder b = new StringBuilder("Q");
|
||||
b.append("_").append(source.hashCode());
|
||||
|
||||
@ -5,11 +5,15 @@
|
||||
*/
|
||||
package com.mysema.codegen;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@ -50,11 +54,11 @@ public class EvaluatorFactoryTest {
|
||||
@Test
|
||||
public void testSimple(){
|
||||
for (String expr : Arrays.asList("a.equals(b)", "a.startsWith(b)", "a.equalsIgnoreCase(b)")){
|
||||
test(expr, boolean.class, names, strings, Arrays.asList("a","b"));
|
||||
evaluate(expr, boolean.class, names, strings, Arrays.asList("a","b"), Collections.<String,Object>emptyMap());
|
||||
}
|
||||
|
||||
for (String expr : Arrays.asList("a != b", "a < b", "a > b", "a <= b", "a >= b")){
|
||||
test(expr, boolean.class, names, ints, Arrays.asList(0,1));
|
||||
evaluate(expr, boolean.class, names, ints, Arrays.asList(0,1), Collections.<String,Object>emptyMap());
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,24 +74,35 @@ public class EvaluatorFactoryTest {
|
||||
test("a + b", int.class, names, ints, Arrays.asList(1,2), 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithConstants(){
|
||||
Map<String,Object> constants = new HashMap<String,Object>();
|
||||
constants.put("x", "Hello World");
|
||||
List<Class<?>> types = Arrays.<Class<?>>asList(String.class);
|
||||
List<String> names = Arrays.asList("a");
|
||||
assertEquals(Boolean.TRUE, evaluate("a.equals(x)", boolean.class, names, types, Arrays.asList("Hello World"), constants));
|
||||
assertEquals(Boolean.FALSE, evaluate("a.equals(x)", boolean.class, names, types, Arrays.asList("Hello"), constants));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomType(){
|
||||
test("a.getName()", String.class,
|
||||
Collections.singletonList("a"), Collections.singletonList(TestEntity.class),
|
||||
Collections.singletonList("a"), Collections.<Class<?>>singletonList(TestEntity.class),
|
||||
Arrays.asList(new TestEntity("Hello World")), "Hello World");
|
||||
|
||||
}
|
||||
|
||||
private void test(String source, Class<?> projectionType, List<String> names, List<? extends Class<?>> types, List<?> args, Object expectedResult){
|
||||
Assert.assertEquals(expectedResult, test(source, projectionType, names, types, args));
|
||||
private void test(String source, Class<?> projectionType, List<String> names, List<Class<?>> types, List<?> args, Object expectedResult){
|
||||
Assert.assertEquals(expectedResult, evaluate(source, projectionType, names, types, args, Collections.<String,Object>emptyMap()));
|
||||
}
|
||||
|
||||
private Object test(String source, Class<?> projectionType, List<String> names, List<? extends Class<?>> types, List<?> args) {
|
||||
private Object evaluate(String source, Class<?> projectionType, List<String> names, List<Class<?>> types, List<?> args, Map<String,Object> constants) {
|
||||
Evaluator<?> evaluator = factory.createEvaluator(
|
||||
source,
|
||||
projectionType,
|
||||
names.toArray(new String[names.size()]),
|
||||
types.toArray(new Class[types.size()]));
|
||||
types.toArray(new Class[types.size()]),
|
||||
constants);
|
||||
return evaluator.evaluate(args.toArray());
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user