#163 fixed constructor expression issues

This commit is contained in:
Timo Westkämper 2012-06-07 22:58:49 +03:00
parent 7398c23fc0
commit ffa6bc0068
2 changed files with 64 additions and 9 deletions

View File

@ -13,6 +13,7 @@
*/
package com.mysema.query.types;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
@ -39,8 +40,10 @@ public class ConstructorExpression<T> extends ExpressionBase<T> implements Facto
private static Class<?>[] getRealParameters(Class<?> type, Class<?>[] givenTypes) {
for (Constructor<?> c : type.getConstructors()){
Class<?>[] paramTypes = c.getParameterTypes();
if (paramTypes.length == givenTypes.length) {
Class<?>[] paramTypes = c.getParameterTypes();
if (c.isVarArgs()) {
return paramTypes;
} else if (paramTypes.length == givenTypes.length) {
boolean found = true;
for (int i = 0; i < paramTypes.length; i++) {
if (!normalize(paramTypes[i]).isAssignableFrom(normalize(givenTypes[i]))) {
@ -67,10 +70,10 @@ public class ConstructorExpression<T> extends ExpressionBase<T> implements Facto
private final List<Expression<?>> args;
private final Class<?>[] parameterTypes;
@Nullable
private transient Constructor<?> constructor;
public ConstructorExpression(Class<T> type, Class<?>[] paramTypes, Expression<?>... args) {
this(type, paramTypes, Arrays.asList(args));
}
@ -94,7 +97,7 @@ public class ConstructorExpression<T> extends ExpressionBase<T> implements Facto
/**
* Create an alias for the expression
*
* @return
* @retu rn
*/
public Expression<T> as(String alias) {
return as(new PathImpl<T>(getType(), alias));
@ -129,7 +132,22 @@ public class ConstructorExpression<T> extends ExpressionBase<T> implements Facto
if (constructor == null) {
constructor = getType().getConstructor(parameterTypes);
}
return (T) constructor.newInstance(args);
if (constructor.isVarArgs()) {
Class<?>[] paramTypes = constructor.getParameterTypes();
// constructor args
Object[] cargs = new Object[paramTypes.length];
System.arraycopy(args, 0, cargs, 0, cargs.length - 1);
// array with vargs
int size = args.length - cargs.length + 1;
Object array = Array.newInstance(
paramTypes[paramTypes.length - 1].getComponentType(), size);
cargs[cargs.length - 1] = array;
System.arraycopy(args, cargs.length - 1, array, 0, size);
return (T) constructor.newInstance(cargs);
} else {
return (T) constructor.newInstance(args);
}
} catch (SecurityException e) {
throw new ExpressionException(e.getMessage(), e);
} catch (NoSuchMethodException e) {

View File

@ -13,7 +13,7 @@
*/
package com.mysema.query.types;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.*;
import org.junit.Test;
@ -22,10 +22,31 @@ import com.mysema.query.types.path.PathBuilder;
public class ProjectionsTest {
public static class VarArgs {
String[] args;
public VarArgs(String... strs) {
args = strs;
}
}
public static class VarArgs2 {
String arg;
String[] args;
public VarArgs2(String s, String... strs) {
arg = s;
args = strs;
}
}
@SuppressWarnings("unchecked")
@Test
public void Array() {
FactoryExpression<String[]> expr = Projections.array(String[].class, new PathImpl(String.class, "p1"), new PathImpl(String.class, "p2"));
FactoryExpression<String[]> expr = Projections.array(String[].class,
new PathImpl(String.class, "p1"), new PathImpl(String.class, "p2"));
assertEquals(String[].class, expr.newInstance("1","2").getClass());
}
@ -43,7 +64,23 @@ public class ProjectionsTest {
public void Constructor() {
Expression<Long> longVal = ConstantImpl.create(1l);
Expression<String> stringVal = ConstantImpl.create("");
assertEquals(ProjectionExample.class, Projections.constructor(ProjectionExample.class, longVal, stringVal).newInstance(0l,"").getClass());
assertEquals(ProjectionExample.class, Projections.constructor(ProjectionExample.class, longVal, stringVal)
.newInstance(0l,"").getClass());
}
@Test
public void Constructor_VarArgs() {
Expression<String> stringVal = ConstantImpl.create("");
VarArgs instance = Projections.constructor(VarArgs.class, stringVal).newInstance("X", "Y");
assertArrayEquals(new String[]{"X", "Y"}, instance.args);
}
@Test
public void Constructor_VarArgs2() {
Expression<String> stringVal = ConstantImpl.create("");
VarArgs2 instance = Projections.constructor(VarArgs2.class, stringVal).newInstance("X", "Y", "Z");
assertEquals("X", instance.arg);
assertArrayEquals(new String[]{"Y", "Z"}, instance.args);
}
@Test