/*
* 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.sqm.produce.spi;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.hibernate.query.sqm.AliasCollisionException;
import org.hibernate.query.sqm.produce.internal.NavigableBindingHelper;
import org.hibernate.query.sqm.tree.expression.domain.SqmNavigableReference;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.select.SqmSelection;
/**
* @author Andrea Boriero
*/
public class AliasRegistry {
private Map<String, SqmNavigableReference> navigableBindingsByAlias = new HashMap<>();
private Map<String, SqmSelection> selectionsByAlias = new HashMap<>();
private AliasRegistry parent;
public AliasRegistry() {
}
public AliasRegistry(AliasRegistry parent) {
this.parent = parent;
}
public AliasRegistry getParent() {
return parent;
}
public void registerAlias(SqmSelection selection) {
if ( selection.getAlias() != null ) {
checkResultVariable( selection );
selectionsByAlias.put( selection.getAlias(), selection );
}
}
public void registerAlias(SqmNavigableReference binding) {
final SqmFrom exportedFromElement = NavigableBindingHelper.resolveExportedFromElement( binding );
final SqmNavigableReference old = navigableBindingsByAlias.put( exportedFromElement.getIdentificationVariable(), binding );
if ( old != null ) {
throw new AliasCollisionException(
String.format(
Locale.ENGLISH,
"Alias [%s] used for multiple from-clause-elements : %s, %s",
exportedFromElement.getIdentificationVariable(),
old,
binding
)
);
}
}
public SqmSelection findSelectionByAlias(String alias) {
return selectionsByAlias.get( alias );
}
public SqmNavigableReference findFromElementByAlias(String alias) {
if ( navigableBindingsByAlias.containsKey( alias ) ) {
return navigableBindingsByAlias.get( alias );
}
else if ( parent != null ) {
return parent.findFromElementByAlias( alias );
}
return null;
}
private void checkResultVariable(SqmSelection selection) {
final String alias = selection.getAlias();
if ( selectionsByAlias.containsKey( alias ) ) {
throw new AliasCollisionException(
String.format(
Locale.ENGLISH,
"Alias [%s] is already used in same select clause",
alias
)
);
}
final SqmNavigableReference binding = navigableBindingsByAlias.get( alias );
if ( binding != null ) {
if ( !selection.getExpression().getExpressionType().equals( binding.getReferencedNavigable().getExportedDomainType() ) ) {
throw new AliasCollisionException(
String.format(
Locale.ENGLISH,
"Alias [%s] used in select-clause for %s is also used in from element: %s for %s",
alias,
selection.getExpression().getExpressionType(),
binding,
binding.getReferencedNavigable()
)
);
}
}
}
}