added basic version of case

This commit is contained in:
Timo Westkämper 2009-11-09 13:09:26 +00:00
parent 0d1f2c1083
commit bb1d5b738a
7 changed files with 184 additions and 9 deletions

View File

@ -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<A> {
private final List<Expr<?>> exprs = new ArrayList<Expr<?>>();
private final Class<A> type;
public Cases(Class<A> type) {
this.type = type;
}
Cases<A> addCase(EBoolean condition, Expr<A> expr) {
exprs.add(OSimple.create(type, Ops.CASE_WHEN, condition, expr));
return this;
}
private Expr<A> createChain(List<Expr<?>> 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<A>(type, exprs, templateFactory.create(builder.toString()));
}
public Expr<A> otherwise(A constant) {
return otherwise(Expr.create(constant));
}
public Expr<A> otherwise(Expr<A> expr) {
exprs.add(OSimple.create(type, Ops.CASE_ELSE, expr));
return OSimple.create(type, Ops.CASE, createChain(exprs));
}
public CaseWhen<A> when(EBoolean b) {
return new CaseWhen<A>(this, b);
}
}
public class CaseWhen<A> {
private final EBoolean b;
private final Cases<A> cases;
public CaseWhen(Cases<A> cases, EBoolean b) {
this.cases = cases;
this.b = b;
}
public Cases<A> then(A constant) {
return cases.addCase(b, Expr.create(constant));
}
public Cases<A> then(Expr<A> expr) {
return cases.addCase(b, expr);
}
}
public class Initial {
private final EBoolean b;
public Initial(EBoolean b) {
this.b = b;
}
@SuppressWarnings("unchecked")
public <A> Cases<A> then(A constant) {
return new Cases<A>((Class) constant.getClass()).addCase(b, Expr.create(constant));
}
@SuppressWarnings("unchecked")
public <A> Cases<A> then(Expr<A> expr) {
return new Cases<A>((Class)expr.getType()).addCase(b, expr);
}
}
private static final TemplateFactory templateFactory = new TemplateFactory();
public Initial when(EBoolean b) {
return new Initial(b);
}
}

View File

@ -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}");

View File

@ -107,6 +107,11 @@ public interface Ops {
Operator<Boolean> STRING_CONTAINS = new OperatorImpl<Boolean>(String_x_2);
Operator<Boolean> LIKE = new OperatorImpl<Boolean>(String_x_2);
// case
Operator<Object> CASE = new OperatorImpl<Object>(Object.class);
Operator<Object> CASE_WHEN = new OperatorImpl<Object>(Boolean.class, Object.class);
Operator<Object> CASE_ELSE = new OperatorImpl<Object>(Object.class);
// subquery operations
Operator<Boolean> EXISTS = new OperatorImpl<Boolean>(Object.class);

View File

@ -81,6 +81,10 @@ public class CoverageTest {
Ops.XOR,
Ops.XNOR,
Ops.CASE,
Ops.CASE_WHEN,
Ops.CASE_ELSE,
// aggregation
Ops.AggOps.AVG_AGG,

View File

@ -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<String>)expr, (Path<String>)other, knownValue));
}
rv.addAll(comparable(expr, other, knownValue));
for (EString eq : projections.string(expr, other, knownValue)){
for (Expr<String> eq : projections.string(expr, other, knownValue)){
rv.add(eq.eq(other));
}
rv.add(expr.between("A", "Z"));

View File

@ -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<EString> string(EString expr, EString other, String knownValue){
HashSet<EString> rv = new HashSet<EString>();
Collection<Expr<String>> string(EString expr, EString other, String knownValue){
HashSet<Expr<String>> rv = new HashSet<Expr<String>>();
rv.addAll(stringProjections(expr, other));
rv.addAll(stringProjections(expr, EString.create(knownValue)));
return rv;
}
Collection<EString> stringProjections(EString expr, EString other){
HashSet<EString> rv = new HashSet<EString>();
Collection<Expr<String>> stringProjections(EString expr, EString other){
HashSet<Expr<String>> rv = new HashSet<Expr<String>>();
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());

View File

@ -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<String> 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());
}
}