Skip to content

Commit 6539565

Browse files
committed
light refactoring to a method of BasicDotIdentifierConsumer
1 parent 43cdff7 commit 6539565

File tree

1 file changed

+90
-51
lines changed

1 file changed

+90
-51
lines changed

hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java

Lines changed: 90 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
import org.hibernate.metamodel.model.domain.JpaMetamodel;
88
import org.hibernate.metamodel.model.domain.ManagedDomainType;
99
import org.hibernate.query.SemanticException;
10-
import org.hibernate.query.hql.HqlLogging;
1110
import org.hibernate.query.hql.spi.DotIdentifierConsumer;
1211
import org.hibernate.query.hql.spi.SemanticPathPart;
1312
import org.hibernate.query.hql.spi.SqmCreationState;
1413
import org.hibernate.query.hql.spi.SqmPathRegistry;
14+
import org.hibernate.query.spi.QueryEngine;
1515
import org.hibernate.query.sqm.NodeBuilder;
1616
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
1717
import org.hibernate.query.sqm.spi.SqmCreationContext;
@@ -27,6 +27,8 @@
2727
import org.hibernate.type.descriptor.java.EnumJavaType;
2828
import org.hibernate.type.descriptor.java.JavaType;
2929

30+
import static org.hibernate.query.hql.HqlLogging.QUERY_LOGGER;
31+
3032
/**
3133
* A {@link DotIdentifierConsumer} used to interpret paths outside any
3234
* specific context. This is the handler used at the root of the handler
@@ -78,7 +80,7 @@ public void consumeIdentifier(String identifier, boolean isBase, boolean isTermi
7880
}
7981
pathSoFar.append( identifier );
8082

81-
HqlLogging.QUERY_LOGGER.tracef(
83+
QUERY_LOGGER.tracef(
8284
"BasicDotIdentifierHandler#consumeIdentifier( %s, %s, %s ) - %s",
8385
identifier,
8486
isBase,
@@ -119,7 +121,7 @@ public SemanticPathPart resolvePathPart(
119121
String identifier,
120122
boolean isTerminal,
121123
SqmCreationState creationState) {
122-
HqlLogging.QUERY_LOGGER.tracef(
124+
QUERY_LOGGER.tracef(
123125
"BaseLocalSequencePart#consumeIdentifier( %s, %s, %s ) - %s",
124126
identifier,
125127
isBase,
@@ -129,87 +131,124 @@ public SemanticPathPart resolvePathPart(
129131

130132
if ( isBase ) {
131133
isBase = false;
132-
133-
final SqmPathRegistry sqmPathRegistry =
134-
creationState.getProcessingStateStack().getCurrent()
135-
.getPathRegistry();
136-
137-
final SqmFrom<?,?> pathRootByAlias = sqmPathRegistry.findFromByAlias( identifier, true );
138-
if ( pathRootByAlias != null ) {
139-
// identifier is an alias (identification variable)
140-
validateAsRoot( pathRootByAlias );
141-
return isTerminal ? pathRootByAlias : new DomainPathPart( pathRootByAlias );
142-
}
143-
144-
final SqmFrom<?, ?> pathRootByExposedNavigable = sqmPathRegistry.findFromExposing( identifier );
145-
if ( pathRootByExposedNavigable != null ) {
146-
// identifier is an "unqualified attribute reference"
147-
validateAsRoot( pathRootByExposedNavigable );
148-
final SqmPath<?> sqmPath = pathRootByExposedNavigable.get( identifier, true );
149-
return isTerminal ? sqmPath : new DomainPathPart( sqmPath );
134+
final SemanticPathPart pathPart =
135+
resolvePath( identifier, isTerminal, creationState );
136+
if ( pathPart != null ) {
137+
return pathPart;
150138
}
151139
}
152140

153-
// at the moment, below this point we wait to resolve the sequence until we hit the terminal
154-
//
155-
// we could check for "intermediate resolution", but that comes with a performance hit. E.g., consider
141+
// Below this point we wait to resolve the sequence until we hit the terminal.
142+
// We could check for "intermediate resolution", but that comes with a performance hit.
143+
// Consider:
156144
//
157-
// `org.hibernate.test.Sex.MALE`
145+
// org.hibernate.test.Sex.MALE
158146
//
159-
// we could check `org` and then `org.hibernate` and then `org.hibernate.test` and then ... until
160-
// we know it is a package, class or entity name. That gets expensive though. For now, plan on
161-
// resolving these at the terminal
162-
//
163-
// todo (6.0) : finish this logic. and see above note in `! isTerminal` block
164-
147+
// We could check 'org', then 'org.hibernate', then 'org.hibernate.test' and so on until
148+
// we know it's a package, class or entity name. That's more expensive though, and the
149+
// error message would not be better.
165150

166-
if ( ! isTerminal ) {
167-
return this;
168-
}
151+
return isTerminal ? resolveTerminal( creationState ) : this;
152+
}
169153

154+
private SemanticPathPart resolveTerminal(SqmCreationState creationState) {
170155
final SqmCreationContext creationContext = creationState.getCreationContext();
171-
final JpaMetamodel jpaMetamodel = creationContext.getJpaMetamodel();
172-
final String path = pathSoFar.toString();
173-
final String importableName = jpaMetamodel.qualifyImportableName( path );
174156
final NodeBuilder nodeBuilder = creationContext.getNodeBuilder();
175-
if ( importableName != null ) {
157+
final JpaMetamodel jpaMetamodel = creationContext.getJpaMetamodel();
158+
final QueryEngine queryEngine = creationContext.getQueryEngine();
159+
160+
final SemanticPathPart literalType =
161+
resolveLiteralType( jpaMetamodel, nodeBuilder );
162+
if ( literalType != null ) {
163+
return literalType;
164+
}
165+
166+
final SqmFunctionDescriptor functionDescriptor =
167+
resolveFunction( queryEngine );
168+
if ( functionDescriptor != null ) {
169+
return functionDescriptor.generateSqmExpression( null, queryEngine );
170+
}
171+
172+
final SemanticPathPart literalJava =
173+
resolveLiteralJavaElement( jpaMetamodel, nodeBuilder );
174+
if ( literalJava != null ) {
175+
return literalJava;
176+
}
177+
178+
throw new SemanticException( "Could not interpret path expression '" + pathSoFar + "'" );
179+
}
180+
181+
private SemanticPathPart resolvePath(String identifier, boolean isTerminal, SqmCreationState creationState) {
182+
final SqmPathRegistry sqmPathRegistry =
183+
creationState.getProcessingStateStack().getCurrent()
184+
.getPathRegistry();
185+
186+
final SqmFrom<?,?> pathRootByAlias =
187+
sqmPathRegistry.findFromByAlias( identifier, true );
188+
if ( pathRootByAlias != null ) {
189+
// identifier is an alias (identification variable)
190+
validateAsRoot( pathRootByAlias );
191+
return isTerminal ? pathRootByAlias : new DomainPathPart( pathRootByAlias );
192+
}
193+
194+
final SqmFrom<?, ?> pathRootByExposedNavigable =
195+
sqmPathRegistry.findFromExposing( identifier );
196+
if ( pathRootByExposedNavigable != null ) {
197+
// identifier is an "unqualified attribute reference"
198+
validateAsRoot( pathRootByExposedNavigable );
199+
final SqmPath<?> sqmPath =
200+
pathRootByExposedNavigable.get( identifier, true );
201+
return isTerminal ? sqmPath : new DomainPathPart( sqmPath );
202+
}
203+
204+
return null;
205+
}
206+
207+
private SqmFunctionDescriptor resolveFunction(QueryEngine queryEngine) {
208+
return queryEngine.getSqmFunctionRegistry().findFunctionDescriptor( pathSoFar.toString() );
209+
}
210+
211+
private SemanticPathPart resolveLiteralType(JpaMetamodel jpaMetamodel, NodeBuilder nodeBuilder) {
212+
final String importableName = jpaMetamodel.qualifyImportableName( pathSoFar.toString() );
213+
if ( importableName == null ) {
214+
return null;
215+
}
216+
else {
176217
final ManagedDomainType<?> managedType = jpaMetamodel.managedType( importableName );
177218
if ( managedType instanceof SqmEntityDomainType<?> entityDomainType ) {
178219
return new SqmLiteralEntityType<>( entityDomainType, nodeBuilder );
179220
}
180221
else if ( managedType instanceof SqmEmbeddableDomainType<?> embeddableDomainType ) {
181222
return new SqmLiteralEmbeddableType<>( embeddableDomainType, nodeBuilder );
182223
}
224+
else {
225+
return null;
226+
}
183227
}
228+
}
184229

185-
final SqmFunctionDescriptor functionDescriptor =
186-
creationContext.getQueryEngine().getSqmFunctionRegistry()
187-
.findFunctionDescriptor( path );
188-
if ( functionDescriptor != null ) {
189-
return functionDescriptor.generateSqmExpression( null, creationContext.getQueryEngine() );
190-
}
191-
230+
private SemanticPathPart resolveLiteralJavaElement(JpaMetamodel metamodel, NodeBuilder nodeBuilder) {
231+
final String path = pathSoFar.toString();
192232
// see if it is a named field/enum reference
193233
final int splitPosition = path.lastIndexOf( '.' );
194234
if ( splitPosition > 0 ) {
195235
final String prefix = path.substring( 0, splitPosition );
196236
final String terminal = path.substring( splitPosition + 1 );
197237
try {
198-
final EnumJavaType<?> enumType = jpaMetamodel.getEnumType( prefix );
238+
final EnumJavaType<?> enumType = metamodel.getEnumType( prefix );
199239
if ( enumType != null ) {
200-
return sqmEnumLiteral( jpaMetamodel, enumType, terminal, nodeBuilder );
240+
return sqmEnumLiteral( metamodel, enumType, terminal, nodeBuilder );
201241
}
202242

203-
final JavaType<?> fieldJtdTest = jpaMetamodel.getJavaConstantType( prefix, terminal );
243+
final JavaType<?> fieldJtdTest = metamodel.getJavaConstantType( prefix, terminal );
204244
if ( fieldJtdTest != null ) {
205-
return sqmFieldLiteral( jpaMetamodel, prefix, terminal, fieldJtdTest, nodeBuilder );
245+
return sqmFieldLiteral( metamodel, prefix, terminal, fieldJtdTest, nodeBuilder );
206246
}
207247
}
208248
catch (Exception ignore) {
209249
}
210250
}
211-
212-
throw new SemanticException( "Could not interpret path expression '" + path + "'" );
251+
return null;
213252
}
214253

215254
private static <E> SqmFieldLiteral<E> sqmFieldLiteral(

0 commit comments

Comments
 (0)