package org.hibernate.jpa.criteria.expression;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder.Case;
import javax.persistence.criteria.Expression;
import org.hibernate.jpa.criteria.CriteriaBuilderImpl;
import org.hibernate.jpa.criteria.ParameterRegistry;
import org.hibernate.jpa.criteria.Renderable;
import org.hibernate.jpa.criteria.compile.RenderingContext;
public class SearchedCaseExpression<R>
extends ExpressionImpl<R>
implements Case<R>, Serializable {
private Class<R> javaType;
private List<WhenClause> whenClauses = new ArrayList<WhenClause>();
private Expression<? extends R> otherwiseResult;
public class WhenClause {
private final Expression<Boolean> condition;
private final Expression<? extends R> result;
public WhenClause(Expression<Boolean> condition, Expression<? extends R> result) {
this.condition = condition;
this.result = result;
}
public Expression<Boolean> getCondition() {
return condition;
}
public Expression<? extends R> getResult() {
return result;
}
}
public SearchedCaseExpression(
CriteriaBuilderImpl criteriaBuilder,
Class<R> javaType) {
super( criteriaBuilder, javaType);
this.javaType = javaType;
}
public Case<R> when(Expression<Boolean> condition, R result) {
return when( condition, buildLiteral(result) );
}
@SuppressWarnings({ "unchecked" })
private LiteralExpression<R> buildLiteral(R result) {
final Class<R> type = result != null
? (Class<R>) result.getClass()
: getJavaType();
return new LiteralExpression<R>( criteriaBuilder(), type, result );
}
public Case<R> when(Expression<Boolean> condition, Expression<? extends R> result) {
WhenClause whenClause = new WhenClause( condition, result );
whenClauses.add( whenClause );
adjustJavaType( result );
return this;
}
@SuppressWarnings({ "unchecked" })
private void adjustJavaType(Expression<? extends R> exp) {
if ( javaType == null ) {
javaType = (Class<R>) exp.getJavaType();
}
}
public Expression<R> otherwise(R result) {
return otherwise( buildLiteral(result) );
}
public Expression<R> otherwise(Expression<? extends R> result) {
this.otherwiseResult = result;
adjustJavaType( result );
return this;
}
public Expression<? extends R> getOtherwiseResult() {
return otherwiseResult;
}
public List<WhenClause> getWhenClauses() {
return whenClauses;
}
public void registerParameters(ParameterRegistry registry) {
Helper.possibleParameter( getOtherwiseResult(), registry );
for ( WhenClause whenClause : getWhenClauses() ) {
Helper.possibleParameter( whenClause.getCondition(), registry );
Helper.possibleParameter( whenClause.getResult(), registry );
}
}
public String render(RenderingContext renderingContext) {
StringBuilder caseStatement = new StringBuilder( "case" );
for ( WhenClause whenClause : getWhenClauses() ) {
caseStatement.append( " when " )
.append( ( (Renderable) whenClause.getCondition() ).render( renderingContext ) )
.append( " then " )
.append( ( (Renderable) whenClause.getResult() ).render( renderingContext ) );
}
caseStatement.append( " else " )
.append( ( (Renderable) getOtherwiseResult() ).render( renderingContext ) )
.append( " end" );
return caseStatement.toString();
}
public String renderProjection(RenderingContext renderingContext) {
return render( renderingContext );
}
}