org.babyfish.jimmer.sql.ast.impl.CaseBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jimmer-sql Show documentation
Show all versions of jimmer-sql Show documentation
A revolutionary ORM framework for both java and kotlin
package org.babyfish.jimmer.sql.ast.impl;
import org.babyfish.jimmer.sql.ast.*;
import org.babyfish.jimmer.sql.ast.impl.render.AbstractSqlBuilder;
import org.babyfish.jimmer.sql.ast.tuple.Tuple2;
import org.babyfish.jimmer.sql.runtime.SqlBuilder;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class CaseBuilder {
private Class type;
private List>> whens = new ArrayList<>();
CaseBuilder(Class type) {
this.type = type;
}
public CaseBuilder when(Predicate cond, T then) {
return when(cond, Literals.any(then));
}
public CaseBuilder when(Predicate cond, Expression then) {
whens.add(new Tuple2<>(cond, then));
return this;
}
public Expression otherwise(T otherwise) {
return otherwise(Literals.any(otherwise));
}
@SuppressWarnings({"unchecked", "rawtypes"})
public Expression otherwise(Expression otherwise) {
List>> whens = new ArrayList<>(this.whens);
if (String.class.isAssignableFrom(type)) {
return (Expression) new StrExpr(
(List>>)(List>)whens,
(Expression)otherwise
);
}
if (type.isPrimitive() || Number.class.isAssignableFrom(type)) {
return (Expression) new NumExpr(
type,
whens,
otherwise
);
}
if (Comparable.class.isAssignableFrom(type)) {
return (Expression) new CmpExpr(
type,
whens,
otherwise
);
}
return new AnyExpr<>(type, whens, otherwise);
}
public static class Str extends CaseBuilder {
Str() {
super(String.class);
}
@Override
public Str when(Predicate cond, String then) {
return (Str) super.when(cond, then);
}
@Override
public Str when(Predicate cond, Expression then) {
return (Str) super.when(cond, then);
}
@Override
public StringExpression otherwise(String otherwise) {
return (StringExpression) super.otherwise(otherwise);
}
@Override
public StringExpression otherwise(Expression otherwise) {
return (StringExpression) super.otherwise(otherwise);
}
}
public static class Num> extends CaseBuilder {
Num(Class type) {
super(type);
}
@Override
public Num when(Predicate cond, N then) {
return (Num)super.when(cond, then);
}
@Override
public Num when(Predicate cond, Expression then) {
return (Num)super.when(cond, then);
}
@Override
public NumericExpression otherwise(N otherwise) {
return (NumericExpression) super.otherwise(otherwise);
}
@Override
public NumericExpression otherwise(Expression otherwise) {
return (NumericExpression) super.otherwise(otherwise);
}
}
public static class Cmp> extends CaseBuilder {
Cmp(Class type) {
super(type);
}
@Override
public Cmp when(Predicate cond, T then) {
return (Cmp) super.when(cond, then);
}
@Override
public Cmp when(Predicate cond, Expression then) {
return (Cmp) super.when(cond, then);
}
@Override
public ComparableExpression otherwise(T otherwise) {
return (ComparableExpression) super.otherwise(otherwise);
}
@Override
public ComparableExpression otherwise(Expression otherwise) {
return (ComparableExpression) super.otherwise(otherwise);
}
}
private static class AnyExpr extends AbstractExpression {
private final Class type;
private List>> whens;
private Expression otherwise;
AnyExpr(
Class type,
List>> whens,
Expression otherwise
) {
this.type = type;
this.whens = whens;
this.otherwise = otherwise;
}
@Override
public Class getType() {
return type;
}
@Override
public int precedence() {
return 0;
}
@Override
public void accept(@NotNull AstVisitor visitor) {
for (Tuple2> when : whens) {
((Ast) when.get_1()).accept(visitor);
((Ast) when.get_2()).accept(visitor);
}
((Ast) otherwise).accept(visitor);
}
@Override
public void renderTo(@NotNull AbstractSqlBuilder> builder) {
usingLowestPrecedence(() -> {
builder.sql("case");
for (Tuple2> when : whens) {
builder.sql(" when ");
renderChild((Ast) when.get_1(), builder);
builder.sql(" then ");
renderChild((Ast) when.get_2(), builder);
}
builder.sql(" else ");
renderChild((Ast) otherwise, builder);
builder.sql(" end");
});
}
@Override
protected boolean determineHasVirtualPredicate() {
return whens.stream().anyMatch(it -> hasVirtualPredicate(it.get_1()) || hasVirtualPredicate(it.get_2())) ||
hasVirtualPredicate(otherwise);
}
@Override
protected Ast onResolveVirtualPredicate(AstContext ctx) {
this.whens = whens.stream().map(
it -> new Tuple2<>(
ctx.resolveVirtualPredicate(it.get_1()),
ctx.resolveVirtualPredicate(it.get_2())
)
).collect(Collectors.toList());
this.otherwise = ctx.resolveVirtualPredicate(otherwise);
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AnyExpr> anyExpr = (AnyExpr>) o;
return type.equals(anyExpr.type) && whens.equals(anyExpr.whens) && otherwise.equals(anyExpr.otherwise);
}
@Override
public int hashCode() {
return Objects.hash(type, whens, otherwise);
}
}
private static class StrExpr extends AnyExpr implements StringExpressionImplementor {
StrExpr(
List>> whens,
Expression otherwise
) {
super(String.class, whens, otherwise);
}
}
private static class NumExpr> extends AnyExpr implements NumericExpressionImplementor {
NumExpr(
Class type,
List>> whens,
Expression otherwise
) {
super(type, whens, otherwise);
}
}
private static class CmpExpr> extends AnyExpr implements ComparableExpressionImplementor {
CmpExpr(
Class type,
List>> whens,
Expression otherwise
) {
super(type, whens, otherwise);
}
}
}