diff --git a/querydsl-core/src/main/java/com/mysema/query/types/ConstructorExpression.java b/querydsl-core/src/main/java/com/mysema/query/types/ConstructorExpression.java index 365e69d6e..8c7a9bad2 100644 --- a/querydsl-core/src/main/java/com/mysema/query/types/ConstructorExpression.java +++ b/querydsl-core/src/main/java/com/mysema/query/types/ConstructorExpression.java @@ -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 extends ExpressionBase 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 extends ExpressionBase implements Facto private final List> args; private final Class[] parameterTypes; - + @Nullable private transient Constructor constructor; - + public ConstructorExpression(Class type, Class[] paramTypes, Expression... args) { this(type, paramTypes, Arrays.asList(args)); } @@ -94,7 +97,7 @@ public class ConstructorExpression extends ExpressionBase implements Facto /** * Create an alias for the expression * - * @return + * @retu rn */ public Expression as(String alias) { return as(new PathImpl(getType(), alias)); @@ -129,7 +132,22 @@ public class ConstructorExpression extends ExpressionBase 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) { diff --git a/querydsl-core/src/test/java/com/mysema/query/types/ProjectionsTest.java b/querydsl-core/src/test/java/com/mysema/query/types/ProjectionsTest.java index 4a65603a3..55a3a878e 100644 --- a/querydsl-core/src/test/java/com/mysema/query/types/ProjectionsTest.java +++ b/querydsl-core/src/test/java/com/mysema/query/types/ProjectionsTest.java @@ -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 expr = Projections.array(String[].class, new PathImpl(String.class, "p1"), new PathImpl(String.class, "p2")); + FactoryExpression 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 longVal = ConstantImpl.create(1l); Expression 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 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 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