/* * 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.engine.spi.SessionFactoryImplementor; import org.hibernate.persister.common.spi.Navigable; import org.hibernate.query.sqm.ParsingException; import org.hibernate.query.sqm.produce.internal.NavigableBindingHelper; import org.hibernate.query.sqm.tree.expression.domain.SqmNavigableReference; import org.hibernate.query.sqm.tree.expression.domain.SqmNavigableSourceReference; import org.hibernate.query.sqm.tree.from.SqmFrom; import org.jboss.logging.Logger; /** * Represents contextual information for each parse * * @author Steve Ebersole */ public class ParsingContext { private static final Logger log = Logger.getLogger( ParsingContext.class ); private final SessionFactoryImplementor sessionFactory; private final ImplicitAliasGenerator aliasGenerator = new ImplicitAliasGenerator(); private final Map<String,SqmFrom> globalFromElementMap = new HashMap<>(); private Map<SqmNavigableSourceReference,Map<Navigable,SqmNavigableReference>> navigableReferenceMapBySource; public ParsingContext(SessionFactoryImplementor sessionFactory) { this.sessionFactory = sessionFactory; } public SessionFactoryImplementor getSessionFactory() { return sessionFactory; } public ImplicitAliasGenerator getImplicitAliasGenerator() { return aliasGenerator; } private long uidSequence = 0; public String makeUniqueIdentifier() { return "<uid:" + ++uidSequence + ">"; } public void registerFromElementByUniqueId(SqmFrom fromElement) { final SqmFrom old = globalFromElementMap.put( fromElement.getUniqueIdentifier(), fromElement ); assert old == null; } public void findElementByUniqueId(String uid) { globalFromElementMap.get( uid ); } public void cacheNavigableBinding(SqmNavigableReference binding) { assert binding.getSourceReference() != null; Map<Navigable, SqmNavigableReference> navigableBindingMap = null; if ( navigableReferenceMapBySource == null ) { navigableReferenceMapBySource = new HashMap<>(); } else { navigableBindingMap = navigableReferenceMapBySource.get( binding.getSourceReference() ); } if ( navigableBindingMap == null ) { navigableBindingMap = new HashMap<>(); navigableReferenceMapBySource.put( binding.getSourceReference(), navigableBindingMap ); } final SqmNavigableReference previous = navigableBindingMap.put( binding.getReferencedNavigable(), binding ); if ( previous != null ) { log.debugf( "Caching NavigableBinding [%s] over-wrote previous cache entry [%s]", binding, previous ); } } public SqmNavigableReference getCachedNavigableBinding(SqmNavigableSourceReference source, Navigable navigable) { if ( navigableReferenceMapBySource == null ) { return null; } final Map<Navigable, SqmNavigableReference> navigableBindingMap = navigableReferenceMapBySource.get( source ); if ( navigableBindingMap == null ) { return null; } return navigableBindingMap.get( navigable ); } public SqmNavigableReference findOrCreateNavigableBinding( SqmNavigableSourceReference lhs, String navigableName) { final Navigable sqmNavigable = lhs.getReferencedNavigable().findNavigable( navigableName ); if ( sqmNavigable == null ) { throw new ParsingException( String.format( Locale.ROOT, "Could not resolve SqmNavigable for [%s].[%s]", lhs.getNavigablePath().getFullPath(), navigableName ) ); } return findOrCreateNavigableBinding( lhs, sqmNavigable ); } public SqmNavigableReference findOrCreateNavigableBinding( SqmNavigableSourceReference lhs, Navigable navigable) { Map<Navigable,SqmNavigableReference> bindingsMap = null; if ( navigableReferenceMapBySource == null ) { navigableReferenceMapBySource = new HashMap<>(); } else { bindingsMap = navigableReferenceMapBySource.get( lhs ); } if ( bindingsMap == null ) { bindingsMap = new HashMap<>(); navigableReferenceMapBySource.put( lhs, bindingsMap ); } return bindingsMap.computeIfAbsent( navigable, k -> NavigableBindingHelper.createNavigableBinding( lhs, navigable ) ); } }