package org.hibernate.jpa.criteria.compile;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.ParameterExpression;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.jpa.spi.HibernateEntityManagerImplementor;
import org.hibernate.type.Type;
public class CriteriaCompiler implements Serializable {
private final HibernateEntityManagerImplementor entityManager;
public CriteriaCompiler(HibernateEntityManagerImplementor entityManager) {
this.entityManager = entityManager;
}
public Query compile(CompilableCriteria criteria) {
try {
criteria.validate();
}
catch (IllegalStateException ise) {
throw new IllegalArgumentException( "Error occurred validating the Criteria", ise );
}
final Map<ParameterExpression<?>, ExplicitParameterInfo<?>> explicitParameterInfoMap =
new HashMap<ParameterExpression<?>, ExplicitParameterInfo<?>>();
final List<ImplicitParameterBinding> implicitParameterBindings = new ArrayList<ImplicitParameterBinding>();
RenderingContext renderingContext = new RenderingContext() {
private int aliasCount;
private int explicitParameterCount;
public String generateAlias() {
return "generatedAlias" + aliasCount++;
}
public String generateParameterName() {
return "param" + explicitParameterCount++;
}
@Override
@SuppressWarnings("unchecked")
public ExplicitParameterInfo registerExplicitParameter(ParameterExpression<?> criteriaQueryParameter) {
ExplicitParameterInfo parameterInfo = explicitParameterInfoMap.get( criteriaQueryParameter );
if ( parameterInfo == null ) {
if ( StringHelper.isNotEmpty( criteriaQueryParameter.getName() ) ) {
parameterInfo = new ExplicitParameterInfo(
criteriaQueryParameter.getName(),
null,
criteriaQueryParameter.getJavaType()
);
}
else if ( criteriaQueryParameter.getPosition() != null ) {
parameterInfo = new ExplicitParameterInfo(
null,
criteriaQueryParameter.getPosition(),
criteriaQueryParameter.getJavaType()
);
}
else {
parameterInfo = new ExplicitParameterInfo(
generateParameterName(),
null,
criteriaQueryParameter.getJavaType()
);
}
explicitParameterInfoMap.put( criteriaQueryParameter, parameterInfo );
}
return parameterInfo;
}
public String registerLiteralParameterBinding(final Object literal, final Class javaType) {
final String parameterName = generateParameterName();
final ImplicitParameterBinding binding = new ImplicitParameterBinding() {
public String getParameterName() {
return parameterName;
}
public Class getJavaType() {
return javaType;
}
public void bind(TypedQuery typedQuery) {
typedQuery.setParameter( parameterName, literal );
}
};
implicitParameterBindings.add( binding );
return parameterName;
}
public String getCastType(Class javaType) {
SessionFactoryImplementor factory =
( SessionFactoryImplementor ) entityManager.getFactory().getSessionFactory();
Type hibernateType = factory.getTypeResolver().heuristicType( javaType.getName() );
if ( hibernateType == null ) {
throw new IllegalArgumentException(
"Could not convert java type [" + javaType.getName() + "] to Hibernate type"
);
}
return hibernateType.getName();
}
};
return criteria.interpret( renderingContext ).buildCompiledQuery(
entityManager,
new InterpretedParameterMetadata() {
@Override
public Map<ParameterExpression<?>, ExplicitParameterInfo<?>> explicitParameterInfoMap() {
return explicitParameterInfoMap;
}
@Override
public List<ImplicitParameterBinding> implicitParameterBindings() {
return implicitParameterBindings;
}
}
);
}
}