/*
* Copyright 2014 - 2017 Blazebit.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.blazebit.persistence.criteria.impl;
import com.blazebit.persistence.CommonQueryBuilder;
import com.blazebit.persistence.SubqueryInitiator;
import com.blazebit.persistence.criteria.impl.expression.AbstractSelection;
import com.blazebit.persistence.criteria.impl.expression.ParameterExpressionImpl;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Selection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Christian Beikov
* @since 1.2.0
*/
public class RenderContextImpl implements RenderContext {
private final Map<ParameterExpression<?>, String> explicitParameterMapping = new HashMap<ParameterExpression<?>, String>();
private final Map<String, ParameterExpression<?>> explicitParameterNameMapping = new HashMap<String, ParameterExpression<?>>();
private final List<ImplicitParameterBinding> implicitParameterBindings = new ArrayList<ImplicitParameterBinding>();
private final StringBuilder buffer;
private final List<SubqueryInitiator<?>> subqueryInitiatorStack;
private ClauseType clauseType;
private int aliasCount = 0;
private int explicitParameterCount = 0;
private int subqueryAliasCount = 0;
private Map<String, InternalQuery<?>> aliasToSubqueries = new HashMap<String, InternalQuery<?>>();
public RenderContextImpl() {
this.buffer = new StringBuilder();
this.subqueryInitiatorStack = new ArrayList<SubqueryInitiator<?>>();
}
@Override
public StringBuilder getBuffer() {
return buffer;
}
public String takeBuffer() {
String s = buffer.toString();
buffer.setLength(0);
return s;
}
@Override
public SubqueryInitiator<?> getSubqueryInitiator() {
return subqueryInitiatorStack.get(subqueryInitiatorStack.size() - 1);
}
public void pushSubqueryInitiator(SubqueryInitiator<?> subqueryInitiator) {
subqueryInitiatorStack.add(subqueryInitiator);
}
public void popSubqueryInitiator() {
subqueryInitiatorStack.remove(subqueryInitiatorStack.size() - 1);
}
@Override
public ClauseType getClauseType() {
return clauseType;
}
public void setClauseType(ClauseType clauseType) {
this.clauseType = clauseType;
}
@Override
public void apply(Selection<?> selection) {
((AbstractSelection<?>) selection).render(this);
}
@Override
public String generateAlias(Class<?> entityClass) {
return "generated" + entityClass.getSimpleName() + "_" + aliasCount++;
}
@Override
public String generateSubqueryAlias(InternalQuery<?> subquery) {
String subqueryAlias = "generatedSubquery_" + subqueryAliasCount++;
aliasToSubqueries.put(subqueryAlias, subquery);
return subqueryAlias;
}
public Map<String, InternalQuery<?>> takeAliasToSubqueryMap() {
if (subqueryAliasCount == 0) {
return Collections.emptyMap();
}
Map<String, InternalQuery<?>> map = aliasToSubqueries;
this.aliasToSubqueries = new HashMap<String, InternalQuery<?>>();
this.subqueryAliasCount = 0;
return map;
}
private String generateParameterName() {
return "generated_param_" + explicitParameterCount++;
}
@Override
public String registerExplicitParameter(ParameterExpression<?> criteriaQueryParameter) {
final String jpaqlParameterName;
if (explicitParameterMapping.containsKey(criteriaQueryParameter)) {
jpaqlParameterName = explicitParameterMapping.get(criteriaQueryParameter);
} else {
if (criteriaQueryParameter.getName() == null || criteriaQueryParameter.getName().isEmpty()) {
if (criteriaQueryParameter.getPosition() != null) {
throw new IllegalArgumentException("Positional parameters are not supported in criteria queries!");
} else {
jpaqlParameterName = generateParameterName();
((ParameterExpressionImpl<?>) criteriaQueryParameter).setName(jpaqlParameterName);
}
} else {
jpaqlParameterName = criteriaQueryParameter.getName();
}
explicitParameterNameMapping.put(jpaqlParameterName, criteriaQueryParameter);
explicitParameterMapping.put(criteriaQueryParameter, jpaqlParameterName);
}
return jpaqlParameterName;
}
@Override
public String registerLiteralParameterBinding(final Object literal, final Class javaType) {
final String parameterName = generateParameterName();
final ImplicitParameterBinding binding = new ImplicitParameterBinding() {
public void bind(CommonQueryBuilder<?> builder) {
builder.setParameter(parameterName, literal);
}
};
implicitParameterBindings.add(binding);
return parameterName;
}
public Map<String, ParameterExpression<?>> getExplicitParameterNameMapping() {
return explicitParameterNameMapping;
}
public List<ImplicitParameterBinding> getImplicitParameterBindings() {
return implicitParameterBindings;
}
}