diff --git a/querydsl-core/src/main/java/com/mysema/query/types/CaseBuilder.java b/querydsl-core/src/main/java/com/mysema/query/types/CaseBuilder.java new file mode 100644 index 000000000..d0b4ad8a8 --- /dev/null +++ b/querydsl-core/src/main/java/com/mysema/query/types/CaseBuilder.java @@ -0,0 +1,103 @@ +package com.mysema.query.types; + +import java.util.ArrayList; +import java.util.List; + +import com.mysema.query.types.custom.CSimple; +import com.mysema.query.types.expr.EBoolean; +import com.mysema.query.types.expr.Expr; +import com.mysema.query.types.operation.OSimple; +import com.mysema.query.types.operation.Ops; + +/** + * @author tiwe + * + */ +public class CaseBuilder { + + public class Cases { + + private final List> exprs = new ArrayList>(); + + private final Class type; + + public Cases(Class type) { + this.type = type; + } + + Cases addCase(EBoolean condition, Expr expr) { + exprs.add(OSimple.create(type, Ops.CASE_WHEN, condition, expr)); + return this; + } + + private Expr createChain(List> exprs) { + StringBuilder builder = new StringBuilder(exprs.size() * 4); + for (int i = 0; i < exprs.size(); i++){ + if (i > 0) builder.append(" "); + builder.append("{").append(i).append("}"); + } + return new CSimple(type, exprs, templateFactory.create(builder.toString())); + } + + public Expr otherwise(A constant) { + return otherwise(Expr.create(constant)); + } + + public Expr otherwise(Expr expr) { + exprs.add(OSimple.create(type, Ops.CASE_ELSE, expr)); + return OSimple.create(type, Ops.CASE, createChain(exprs)); + } + + public CaseWhen when(EBoolean b) { + return new CaseWhen(this, b); + } + + } + + public class CaseWhen { + + private final EBoolean b; + + private final Cases cases; + + public CaseWhen(Cases cases, EBoolean b) { + this.cases = cases; + this.b = b; + } + + public Cases then(A constant) { + return cases.addCase(b, Expr.create(constant)); + } + + public Cases then(Expr expr) { + return cases.addCase(b, expr); + } + } + + public class Initial { + + private final EBoolean b; + + public Initial(EBoolean b) { + this.b = b; + } + + @SuppressWarnings("unchecked") + public Cases then(A constant) { + return new Cases((Class) constant.getClass()).addCase(b, Expr.create(constant)); + } + + @SuppressWarnings("unchecked") + public Cases then(Expr expr) { + return new Cases((Class)expr.getType()).addCase(b, expr); + } + } + + private static final TemplateFactory templateFactory = new TemplateFactory(); + + + public Initial when(EBoolean b) { + return new Initial(b); + } + +} diff --git a/querydsl-core/src/main/java/com/mysema/query/types/Templates.java b/querydsl-core/src/main/java/com/mysema/query/types/Templates.java index 9291bd135..4f031f973 100644 --- a/querydsl-core/src/main/java/com/mysema/query/types/Templates.java +++ b/querydsl-core/src/main/java/com/mysema/query/types/Templates.java @@ -163,6 +163,11 @@ public class Templates { add(PathType.LISTVALUE_CONSTANT, "{0}.get({1s})"); // serialized constant add(PathType.ARRAYVALUE_CONSTANT, "{0}[{1s}]"); // serialized constant + // case + add(Ops.CASE, "case {0} end"); + add(Ops.CASE_WHEN, "when {0} then {1}"); + add(Ops.CASE_ELSE, "else {0}"); + // subquery add(Ops.EXISTS, "exists {0}"); diff --git a/querydsl-core/src/main/java/com/mysema/query/types/operation/Ops.java b/querydsl-core/src/main/java/com/mysema/query/types/operation/Ops.java index 4b695715a..c18f52f32 100644 --- a/querydsl-core/src/main/java/com/mysema/query/types/operation/Ops.java +++ b/querydsl-core/src/main/java/com/mysema/query/types/operation/Ops.java @@ -107,6 +107,11 @@ public interface Ops { Operator STRING_CONTAINS = new OperatorImpl(String_x_2); Operator LIKE = new OperatorImpl(String_x_2); + // case + Operator CASE = new OperatorImpl(Object.class); + Operator CASE_WHEN = new OperatorImpl(Boolean.class, Object.class); + Operator CASE_ELSE = new OperatorImpl(Object.class); + // subquery operations Operator EXISTS = new OperatorImpl(Object.class); diff --git a/querydsl-core/src/test/java/com/mysema/query/CoverageTest.java b/querydsl-core/src/test/java/com/mysema/query/CoverageTest.java index 5fee49aa3..1127e1eee 100644 --- a/querydsl-core/src/test/java/com/mysema/query/CoverageTest.java +++ b/querydsl-core/src/test/java/com/mysema/query/CoverageTest.java @@ -81,6 +81,10 @@ public class CoverageTest { Ops.XOR, Ops.XNOR, + + Ops.CASE, + Ops.CASE_WHEN, + Ops.CASE_ELSE, // aggregation Ops.AggOps.AVG_AGG, diff --git a/querydsl-core/src/test/java/com/mysema/query/Filters.java b/querydsl-core/src/test/java/com/mysema/query/Filters.java index 5fcdd2149..64596a358 100644 --- a/querydsl-core/src/test/java/com/mysema/query/Filters.java +++ b/querydsl-core/src/test/java/com/mysema/query/Filters.java @@ -32,13 +32,13 @@ public class Filters { private final Projections projections; - private final Module module; +// private final Module module; private final Target target; public Filters(Projections projections, Module module, Target target) { this.projections = projections; - this.module = module; +// this.module = module; this.target = target; } @@ -186,7 +186,7 @@ public class Filters { rv.addAll(pathFilters((Path)expr, (Path)other, knownValue)); } rv.addAll(comparable(expr, other, knownValue)); - for (EString eq : projections.string(expr, other, knownValue)){ + for (Expr eq : projections.string(expr, other, knownValue)){ rv.add(eq.eq(other)); } rv.add(expr.between("A", "Z")); diff --git a/querydsl-core/src/test/java/com/mysema/query/Projections.java b/querydsl-core/src/test/java/com/mysema/query/Projections.java index 7f77d471c..c64d1988b 100644 --- a/querydsl-core/src/test/java/com/mysema/query/Projections.java +++ b/querydsl-core/src/test/java/com/mysema/query/Projections.java @@ -28,12 +28,12 @@ import com.mysema.query.types.expr.Expr; */ public class Projections { - private final Module module; +// private final Module module; private final Target target; public Projections(Module module, Target target) { - this.module = module; +// this.module = module; this.target = target; } @@ -86,6 +86,12 @@ public class Projections { rv.add(expr.multiply(other)); rv.add(expr.sqrt()); rv.add(expr.subtract(other)); + +// CaseBuilder cases = new CaseBuilder(); +// rv.add(ENumber.create(1).add(cases +// .when(expr.gt(0)).then(1) +// .otherwise(0))); + return rv; } @@ -104,15 +110,15 @@ public class Projections { } } - Collection string(EString expr, EString other, String knownValue){ - HashSet rv = new HashSet(); + Collection> string(EString expr, EString other, String knownValue){ + HashSet> rv = new HashSet>(); rv.addAll(stringProjections(expr, other)); rv.addAll(stringProjections(expr, EString.create(knownValue))); return rv; } - Collection stringProjections(EString expr, EString other){ - HashSet rv = new HashSet(); + Collection> stringProjections(EString expr, EString other){ + HashSet> rv = new HashSet>(); rv.add(expr.append("Hello")); rv.add(expr.append(other)); @@ -128,6 +134,12 @@ public class Projections { rv.add(expr.substring(1)); rv.add(expr.substring(0, 1)); + +// CaseBuilder cases = new CaseBuilder(); +// rv.add(cases.when(expr.eq("A")).then("a") +// .when(expr.eq("B")).then("b") +// .when(expr.eq("C")).then("c") +// .otherwise("x")); rv.add(expr.trim()); diff --git a/querydsl-core/src/test/java/com/mysema/query/types/CaseBuilderTest.java b/querydsl-core/src/test/java/com/mysema/query/types/CaseBuilderTest.java new file mode 100644 index 000000000..25290d2d2 --- /dev/null +++ b/querydsl-core/src/test/java/com/mysema/query/types/CaseBuilderTest.java @@ -0,0 +1,46 @@ +package com.mysema.query.types; + +import static com.mysema.query.alias.Alias.$; +import static com.mysema.query.alias.Alias.alias; +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.mysema.query.types.expr.Expr; + +public class CaseBuilderTest { + + public static class Customer{ + private long annualSpending; + public long getAnnualSpending() { + return annualSpending; + } + } + + @Test + public void test(){ +// CASE +// WHEN c.annualSpending > 10000 THEN 'Premier' +// WHEN c.annualSpending > 5000 THEN 'Gold' +// WHEN c.annualSpending > 2000 THEN 'Silver' +// ELSE 'Bronze' +// END + + Customer c = alias(Customer.class, "customer"); + Expr cases = new CaseBuilder() + .when($(c.getAnnualSpending()).gt(10000)).then("Premier") + .when($(c.getAnnualSpending()).gt(5000)).then("Gold") + .when($(c.getAnnualSpending()).gt(2000)).then("Silver") + .otherwise("Bronze"); + + assertEquals( + "case " + + "when customer.annualSpending > 10000 then Premier " + + "when customer.annualSpending > 5000 then Gold " + + "when customer.annualSpending > 2000 then Silver " + + "else Bronze " + + "end", cases.toString()); + + } + +}