/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
 * third-party contributors as indicated by either @author tags or express
 * copyright attribution statements applied by the authors.  All
 * third-party contributions are distributed under license by Red Hat Inc.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
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;

Models what ANSI SQL terms a searched case expression. This is a CASE expression in the form
CASE
    WHEN [firstCondition] THEN [firstResult]
    WHEN [secondCondition] THEN [secondResult]
    ELSE [defaultResult]
END
Author:Steve Ebersole
/** * Models what ANSI SQL terms a <tt>searched case expression</tt>. This is a <tt>CASE</tt> expression * in the form<pre> * CASE * WHEN [firstCondition] THEN [firstResult] * WHEN [secondCondition] THEN [secondResult] * ELSE [defaultResult] * END * </pre> * * @author Steve Ebersole */
public class SearchedCaseExpression<R> extends ExpressionImpl<R> implements Case<R>, Serializable { private Class<R> javaType; // overrides the javaType kept on tuple-impl so that we can adjust it 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 ); } }