mirror of
https://github.com/querydsl/querydsl.git
synced 2026-07-03 21:07:49 +08:00
added generic type system
updated version to 0.1.3
This commit is contained in:
parent
326c0825f3
commit
fab883348a
2
pom.xml
2
pom.xml
@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.mysema.codegen</groupId>
|
||||
<artifactId>codegen</artifactId>
|
||||
<version>0.1.2-SNAPSHOT</version>
|
||||
<version>0.1.3</version>
|
||||
<name>Codegen</name>
|
||||
<description>Code generation and compilation for Java</description>
|
||||
<parent>
|
||||
|
||||
@ -31,6 +31,30 @@ public final class ClassUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getName(Type<?> cl){
|
||||
return getName(cl, Collections.singleton(Object.class.getPackage()), Collections.<Class<?>>emptySet());
|
||||
}
|
||||
|
||||
public static String getName(Type<?> type, Set<Package> packages, Set<Class<?>> classes){
|
||||
if (type.getParameters().isEmpty()){
|
||||
return getName(type.getJavaClass(), packages, classes);
|
||||
}else{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(getName(type.getJavaClass(), packages, classes));
|
||||
builder.append("<");
|
||||
boolean first = true;
|
||||
for (Type<?> parameter : type.getParameters()){
|
||||
builder.append(getName(parameter, packages, classes));
|
||||
if (!first){
|
||||
builder.append(",");
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
builder.append(">");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> normalize(Class<?> clazz){
|
||||
if (List.class.isAssignableFrom(clazz)){
|
||||
return List.class;
|
||||
|
||||
@ -54,8 +54,8 @@ public class EvaluatorFactory {
|
||||
this.compilationOptions = Arrays.asList("-classpath", classpath, "-g:none");
|
||||
}
|
||||
|
||||
private void compile(String source, Class<?> projectionType,
|
||||
String[] names, Class<?>[] types, String id, Map<String,Object> constants) throws IOException {
|
||||
private void compile(String source, Type<?> projectionType,
|
||||
String[] names, Type<?>[] types, String id, Map<String,Object> constants) throws IOException {
|
||||
// create source
|
||||
StringWriter writer = new StringWriter();
|
||||
JavaWriter javaw = new JavaWriter(writer);
|
||||
@ -75,7 +75,7 @@ public class EvaluatorFactory {
|
||||
}else{
|
||||
javaw.beginPublicMethod(ClassUtils.getName(projectionType), "eval", params);
|
||||
}
|
||||
javaw.line("return ", source, ";");
|
||||
javaw.append(source);
|
||||
javaw.end();
|
||||
javaw.end();
|
||||
|
||||
@ -95,34 +95,46 @@ public class EvaluatorFactory {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Evaluator<T> createEvaluator(
|
||||
String source,
|
||||
Class<? extends T> projectionType,
|
||||
String[] names,
|
||||
Class<?>[] classes,
|
||||
Map<String,Object> constants) {
|
||||
Type<?>[] types = new Type[classes.length];
|
||||
for (int i = 0; i < types.length; i++){
|
||||
types[i] = new Type(classes[i]);
|
||||
}
|
||||
return createEvaluator(source, new Type(projectionType), names, types, classes, constants);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Evaluator instance
|
||||
*
|
||||
* @param <T> projection type
|
||||
* @param source expression in Java source code form
|
||||
* @param projectionType type of the source expression
|
||||
* @param projection 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,
|
||||
// TODO : support for generic projection types
|
||||
Class<? extends T> projectionType,
|
||||
String[] names,
|
||||
// TODO : support for generic argument type
|
||||
Class<?>[] types,
|
||||
Map<String,Object> constants) {
|
||||
|
||||
String source,
|
||||
Type<? extends T> projection,
|
||||
String[] names,
|
||||
Type<?>[] types,
|
||||
Class<?>[] classes,
|
||||
Map<String,Object> constants) {
|
||||
try {
|
||||
String id = toId(source, projectionType, types);
|
||||
String id = toId(source, projection, types);
|
||||
Class<?> clazz;
|
||||
try{
|
||||
clazz = loader.loadClass(id);
|
||||
}catch(ClassNotFoundException e){
|
||||
compile(source, projectionType, names, types, id, constants);
|
||||
compile(source, projection, names, types, id, constants);
|
||||
// reload
|
||||
clazz = loader.loadClass(id);
|
||||
}
|
||||
@ -134,8 +146,8 @@ public class EvaluatorFactory {
|
||||
field.set(object, entry.getValue());
|
||||
}
|
||||
|
||||
Method method = clazz.getMethod("eval", types);
|
||||
return new MethodEvaluator<T>(method, object, projectionType);
|
||||
Method method = clazz.getMethod("eval", classes);
|
||||
return new MethodEvaluator<T>(method, object, projection.getJavaClass());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new CodegenException(e);
|
||||
} catch (SecurityException e) {
|
||||
@ -156,11 +168,11 @@ public class EvaluatorFactory {
|
||||
|
||||
}
|
||||
|
||||
protected String toId(String source, Class<?> returnType, Class<?>... types) {
|
||||
protected String toId(String source, Type<?> returnType, Type<?>... types) {
|
||||
StringBuilder b = new StringBuilder("Q");
|
||||
b.append("_").append(source.hashCode());
|
||||
b.append("_").append(returnType.getName().hashCode());
|
||||
for (Class<?> type : types) {
|
||||
for (Type<?> type : types) {
|
||||
b.append("_").append(type.getName().hashCode());
|
||||
}
|
||||
return b.toString().replace('-', '0');
|
||||
|
||||
57
src/main/java/com/mysema/codegen/Type.java
Normal file
57
src/main/java/com/mysema/codegen/Type.java
Normal file
@ -0,0 +1,57 @@
|
||||
package com.mysema.codegen;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Type represents a generic type used in code generation
|
||||
*
|
||||
* @author tiwe
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class Type<T> {
|
||||
|
||||
private final Class<T> javaClass;
|
||||
|
||||
private final List<Type<?>> parameters;
|
||||
|
||||
public Type(Class<T> javaClass, List<Type<?>> parameters) {
|
||||
this.javaClass = javaClass;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public Type(Class<T> clazz, Type<?>... parameters) {
|
||||
this(clazz, Arrays.asList(parameters));
|
||||
}
|
||||
|
||||
public Class<T> getJavaClass() {
|
||||
return javaClass;
|
||||
}
|
||||
|
||||
public List<Type<?>> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return javaClass.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(){
|
||||
return javaClass.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o){
|
||||
if (o == this){
|
||||
return true;
|
||||
}else if (o instanceof Type<?>){
|
||||
Type<?> t = (Type<?>)o;
|
||||
return t.javaClass.equals(javaClass) && t.parameters.equals(parameters);
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
45
src/test/java/com/mysema/codegen/ComplexEvaluationTest.java
Normal file
45
src/test/java/com/mysema/codegen/ComplexEvaluationTest.java
Normal file
@ -0,0 +1,45 @@
|
||||
package com.mysema.codegen;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ComplexEvaluationTest {
|
||||
|
||||
private EvaluatorFactory factory = new EvaluatorFactory((URLClassLoader) getClass().getClassLoader());
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testComplex(){Type<String> stringType = new Type<String>(String.class);
|
||||
Type<List> resultType = new Type<List>(List.class, stringType);
|
||||
StringBuilder source = new StringBuilder();
|
||||
source.append("java.util.List<String> rv = new java.util.ArrayList<String>();\n");
|
||||
source.append("for (String a : a_){\n");
|
||||
source.append(" for (String b : b_){\n");
|
||||
source.append(" if (a.equals(b)){\n");
|
||||
source.append(" rv.add(a);\n");
|
||||
source.append(" }\n");
|
||||
source.append(" }\n");
|
||||
source.append("}\n");
|
||||
source.append("return rv;");
|
||||
|
||||
Evaluator<List> evaluator = factory.createEvaluator(
|
||||
source.toString(),
|
||||
resultType,
|
||||
new String[]{"a_","b_"},
|
||||
new Type[]{resultType, resultType},
|
||||
new Class[]{List.class,List.class},
|
||||
Collections.<String,Object>emptyMap());
|
||||
|
||||
List<String> a_ = Arrays.asList("1","2","3","4");
|
||||
List<String> b_ = Arrays.asList("2","4","6","8");
|
||||
|
||||
assertEquals(Arrays.asList("2","4"), evaluator.evaluate(a_, b_));
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
*/
|
||||
package com.mysema.codegen;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLClassLoader;
|
||||
@ -94,22 +94,23 @@ public class EvaluatorFactoryTest {
|
||||
public void testCustomType(){
|
||||
test("a.getName()", String.class,
|
||||
Collections.singletonList("a"), Collections.<Class<?>>singletonList(TestEntity.class),
|
||||
Arrays.asList(new TestEntity("Hello World")), "Hello World");
|
||||
|
||||
Arrays.asList(new TestEntity("Hello World")), "Hello World");
|
||||
}
|
||||
|
||||
|
||||
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 evaluate(String source, Class<?> projectionType, List<String> names, List<Class<?>> types, List<?> args, Map<String,Object> constants) {
|
||||
Evaluator<?> evaluator = factory.createEvaluator(
|
||||
source,
|
||||
"return " + source + ";",
|
||||
projectionType,
|
||||
names.toArray(new String[names.size()]),
|
||||
types.toArray(new Class[types.size()]),
|
||||
constants);
|
||||
return evaluator.evaluate(args.toArray());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user