org.babyfish.jimmer.sql.ast.impl.SimpleCaseBuilder 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.ComparableExpression;
import org.babyfish.jimmer.sql.ast.Expression;
import org.babyfish.jimmer.sql.ast.NumericExpression;
import org.babyfish.jimmer.sql.ast.StringExpression;
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 SimpleCaseBuilder {
private Class type;
private Expression> expression;
private List, Expression>> whens = new ArrayList<>();
SimpleCaseBuilder(Class type, Expression> expression) {
this.type = type;
this.expression = expression;
}
public SimpleCaseBuilder when(C cond, T then) {
return when(Literals.any(cond), Literals.any(then));
}
public SimpleCaseBuilder when(Expression cond, T then) {
return when(cond, Literals.any(then));
}
public SimpleCaseBuilder when(C cond, Expression then) {
return when(Literals.any(cond), then);
}
public SimpleCaseBuilder when(Expression 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, Expression>> whens = new ArrayList<>(this.whens);
if (String.class.isAssignableFrom(type)) {
return (Expression) new StrExpr(
expression,
(List, Expression>>)(List>)whens,
(Expression)otherwise
);
}
if (type.isPrimitive() || Number.class.isAssignableFrom(type)) {
return (Expression) new NumExpr(
type,
expression,
whens,
otherwise
);
}
if (Comparable.class.isAssignableFrom(type)) {
return (Expression) new CmpExpr(
type,
expression,
whens,
otherwise
);
}
return new AnyExpr<>(type, expression, whens, otherwise);
}
public static class Str extends SimpleCaseBuilder {
Str(Expression> expression) {
super(String.class, expression);
}
@Override
public Str when(C cond, String then) {
return (Str) super.when(cond, then);
}
@Override
public Str when(Expression cond, String then) {
return (Str) super.when(cond, then);
}
@Override
public Str when(C cond, Expression then) {
return (Str) super.when(cond, then);
}
@Override
public Str when(Expression 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 SimpleCaseBuilder {
Num(Class type, Expression> expression) {
super(type, expression);
}
@Override
public Num when(C cond, N then) {
return (Num) super.when(cond, then);
}
@Override
public Num when(Expression cond, N then) {
return (Num)super.when(cond, then);
}
@Override
public Num when(C cond, Expression then) {
return (Num) super.when(cond, then);
}
@Override
public Num when(Expression 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 SimpleCaseBuilder {
Cmp(Class type, Expression> expression) {
super(type, expression);
}
@Override
public Cmp when(C cond, T then) {
return (Cmp) super.when(cond, then);
}
@Override
public Cmp when(Expression cond, T then) {
return (Cmp) super.when(cond, then);
}
@Override
public Cmp when(C cond, Expression then) {
return (Cmp) super.when(cond, then);
}
@Override
public Cmp when(Expression 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 Expression> expression;
private List, Expression>> whens;
private Expression otherwise;
AnyExpr(
Class type,
Expression> expression,
List, Expression>> whens,
Expression otherwise
) {
this.type = type;
this.expression = expression;
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) {
((Ast) expression).accept(visitor);
for (Tuple2, Expression> 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 ");
renderChild((Ast) expression, builder);
for (Tuple2, Expression> 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 hasVirtualPredicate(expression) ||
whens.stream().anyMatch(it -> hasVirtualPredicate(it.get_1()) || hasVirtualPredicate(it.get_2())) ||
hasVirtualPredicate(otherwise);
}
@SuppressWarnings("unchecked")
@Override
protected Ast onResolveVirtualPredicate(AstContext ctx) {
this.expression = ctx.resolveVirtualPredicate(expression);
this.whens = (List, Expression>>)(List>)this.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) && expression.equals(anyExpr.expression) && whens.equals(anyExpr.whens) && otherwise.equals(anyExpr.otherwise);
}
@Override
public int hashCode() {
return Objects.hash(type, expression, whens, otherwise);
}
}
private static class StrExpr extends AnyExpr implements StringExpressionImplementor {
StrExpr(
Expression> expression,
List, Expression>> whens,
Expression otherwise
) {
super(String.class, expression, whens, otherwise);
}
}
private static class NumExpr> extends AnyExpr implements NumericExpressionImplementor {
NumExpr(
Class type,
Expression> expression,
List, Expression>> whens,
Expression otherwise
) {
super(type, expression, whens, otherwise);
}
}
private static class CmpExpr> extends AnyExpr implements ComparableExpressionImplementor {
CmpExpr(
Class type,
Expression> expression, List, Expression>> whens,
Expression otherwise
) {
super(type, expression, whens, otherwise);
}
}
}