/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.query.criteria.internal.expression; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.function.BiFunction; import javax.persistence.criteria.CriteriaBuilder.SimpleCase; import javax.persistence.criteria.Expression; import org.hibernate.query.criteria.internal.CriteriaBuilderImpl; import org.hibernate.query.criteria.internal.ParameterRegistry; import org.hibernate.query.criteria.internal.Renderable; import org.hibernate.query.criteria.internal.compile.RenderingContext; /** * Models what ANSI SQL terms a simple case statement. This is a <tt>CASE</tt> expression in the form<pre> * CASE [expression] * WHEN [firstCondition] THEN [firstResult] * WHEN [secondCondition] THEN [secondResult] * ELSE [defaultResult] * END * </pre> * * @author Steve Ebersole */ public class SimpleCaseExpression<C,R> extends ExpressionImpl<R> implements SimpleCase<C,R>, Serializable { private final Expression<? extends C> expression; private List<WhenClause> whenClauses = new ArrayList<WhenClause>(); private Expression<? extends R> otherwiseResult; public class WhenClause { private final LiteralExpression<C> condition; private final Expression<? extends R> result; public WhenClause(LiteralExpression<C> condition, Expression<? extends R> result) { this.condition = condition; this.result = result; } public LiteralExpression<C> getCondition() { return condition; } public Expression<? extends R> getResult() { return result; } } public SimpleCaseExpression( CriteriaBuilderImpl criteriaBuilder, Class<R> javaType, Expression<? extends C> expression) { super( criteriaBuilder, javaType); this.expression = expression; } @SuppressWarnings({ "unchecked" }) public Expression<C> getExpression() { return (Expression<C>) expression; } public SimpleCase<C, R> when(C 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 SimpleCase<C, R> when(C condition, Expression<? extends R> result) { WhenClause whenClause = new WhenClause( new LiteralExpression<C>( criteriaBuilder(), condition ), result ); whenClauses.add( whenClause ); resetJavaType( result.getJavaType() ); return this; } public Expression<R> otherwise(R result) { return otherwise( buildLiteral(result) ); } public Expression<R> otherwise(Expression<? extends R> result) { this.otherwiseResult = result; resetJavaType( result.getJavaType() ); return this; } public Expression<? extends R> getOtherwiseResult() { return otherwiseResult; } public List<WhenClause> getWhenClauses() { return whenClauses; } public void registerParameters(ParameterRegistry registry) { Helper.possibleParameter( getExpression(), registry ); for ( WhenClause whenClause : getWhenClauses() ) { Helper.possibleParameter( whenClause.getResult(), registry ); } Helper.possibleParameter( getOtherwiseResult(), registry ); } public String render(RenderingContext renderingContext) { return render( renderingContext, (Renderable expression, RenderingContext context) -> expression.render( context ) ); } public String renderProjection(RenderingContext renderingContext) { return render( renderingContext, (Renderable expression, RenderingContext context) -> expression.renderProjection( context ) ); } private String render( RenderingContext renderingContext, BiFunction<Renderable, RenderingContext, String> formatter) { StringBuilder caseExpr = new StringBuilder(); caseExpr.append( "case " ) .append( formatter.apply( (Renderable) getExpression(), renderingContext ) ); for ( WhenClause whenClause : getWhenClauses() ) { caseExpr.append( " when " ) .append( formatter.apply( whenClause.getCondition(), renderingContext ) ) .append( " then " ) .append( formatter.apply( (Renderable) whenClause.getResult(), renderingContext ) ); } caseExpr.append( " else " ) .append( formatter.apply( (Renderable) getOtherwiseResult(), renderingContext ) ) .append( " end" ); return caseExpr.toString(); } }