fix up warnings in BasicDotIdentifierConsumer + genericize FullyQualifiedReflectivePathTerminal

This commit is contained in:
Gavin King 2024-09-10 08:08:47 +02:00
parent 0dedc62270
commit 4a974fe976
5 changed files with 62 additions and 51 deletions

View File

@ -30,18 +30,17 @@ import org.hibernate.type.descriptor.java.EnumJavaType;
import org.hibernate.type.descriptor.java.JavaType;
/**
* @asciidoc
*
* DotIdentifierHandler used to interpret paths outside of any specific
* context. This is the handler used at the root of the handler stack.
*
* It can recognize any number of types of paths -
*
* * fully-qualified class names (entity or otherwise)
* * static field references, e.g. `MyClass.SOME_FIELD`
* * enum value references, e.g. `Sex.MALE`
* * navigable-path
* * others?
* A {@link DotIdentifierConsumer} used to interpret paths outside any
* specific context. This is the handler used at the root of the handler
* stack.
* <p>
* It can recognize any number of types of paths:
* <ul>
* <li>fully-qualified class names (entity or otherwise)
* <li>static field references, e.g. {@code MyClass.SOME_FIELD}
* <li>enum value references, e.g. {@code Sex.MALE}
* <li>navigable-path
* </ul>
*
* @author Steve Ebersole
*/
@ -189,11 +188,11 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
final NodeBuilder nodeBuilder = creationContext.getNodeBuilder();
if ( importableName != null ) {
final ManagedDomainType<?> managedType = jpaMetamodel.managedType( importableName );
if ( managedType instanceof EntityDomainType<?> ) {
return new SqmLiteralEntityType<>( (EntityDomainType<?>) managedType, nodeBuilder );
if ( managedType instanceof EntityDomainType<?> entityDomainType ) {
return new SqmLiteralEntityType<>( entityDomainType, nodeBuilder );
}
else if ( managedType instanceof EmbeddableDomainType<?> ) {
return new SqmLiteralEmbeddableType<>( (EmbeddableDomainType<?>) managedType, nodeBuilder );
else if ( managedType instanceof EmbeddableDomainType<?> embeddableDomainType ) {
return new SqmLiteralEmbeddableType<>( embeddableDomainType, nodeBuilder );
}
}
@ -217,7 +216,41 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
try {
final EnumJavaType<?> enumType = jpaMetamodel.getEnumType( prefix );
if ( enumType != null ) {
return new SqmEnumLiteral(
return sqmEnumLiteral( jpaMetamodel, enumType, terminal, nodeBuilder );
}
final JavaType<?> fieldJtdTest = jpaMetamodel.getJavaConstantType( prefix, terminal );
if ( fieldJtdTest != null ) {
return sqmFieldLiteral( jpaMetamodel, prefix, terminal, fieldJtdTest, nodeBuilder );
}
}
catch (Exception ignore) {
}
}
throw new SemanticException( "Could not interpret path expression '" + path + "'" );
}
private static <E> SqmFieldLiteral<E> sqmFieldLiteral(
JpaMetamodelImplementor jpaMetamodel,
String prefix,
String terminal,
JavaType<E> fieldJtdTest,
NodeBuilder nodeBuilder) {
return new SqmFieldLiteral<>(
jpaMetamodel.getJavaConstant( prefix, terminal ),
fieldJtdTest,
terminal,
nodeBuilder
);
}
private static <E extends Enum<E>> SqmEnumLiteral<E> sqmEnumLiteral(
JpaMetamodelImplementor jpaMetamodel,
EnumJavaType<E> enumType,
String terminal,
NodeBuilder nodeBuilder) {
return new SqmEnumLiteral<>(
jpaMetamodel.enumValue( enumType, terminal ),
enumType,
terminal,
@ -225,27 +258,7 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
);
}
final JavaType<?> fieldJtdTest = jpaMetamodel.getJavaConstantType( prefix, terminal );
if ( fieldJtdTest != null ) {
final Object constantValue = jpaMetamodel.getJavaConstant( prefix, terminal );
return new SqmFieldLiteral( constantValue, fieldJtdTest, terminal, nodeBuilder );
}
}
catch (Exception ignore) {
}
}
throw new SemanticException(
String.format(
"Could not interpret path expression '%s'",
path
)
);
}
protected void validateAsRoot(SqmFrom<?, ?> pathRoot) {
}
@Override

View File

@ -31,7 +31,7 @@ public class FullyQualifiedReflectivePath implements SemanticPathPart, FullyQual
boolean isTerminal,
SqmCreationState creationState) {
if ( isTerminal ) {
return new FullyQualifiedReflectivePathTerminal( this, name, creationState );
return new FullyQualifiedReflectivePathTerminal<>( this, name, creationState );
}
else {
return new FullyQualifiedReflectivePath( this, name );

View File

@ -35,17 +35,15 @@ import org.hibernate.type.descriptor.java.JavaType;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Predicate;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry;
/**
* @author Steve Ebersole
*/
public class FullyQualifiedReflectivePathTerminal
public class FullyQualifiedReflectivePathTerminal<E>
extends FullyQualifiedReflectivePath
implements SqmExpression {
private final @Nullable SqmExpressible<?> expressibleType;
implements SqmExpression<E> {
private final @Nullable SqmExpressible<E> expressibleType;
private final SqmCreationState creationState;
private final Function<SemanticQueryWalker<?>,?> handler;
@ -64,7 +62,7 @@ public class FullyQualifiedReflectivePathTerminal
}
@Override
public FullyQualifiedReflectivePathTerminal copy(SqmCopyContext context) {
public FullyQualifiedReflectivePathTerminal<E> copy(SqmCopyContext context) {
return this;
}
@ -139,23 +137,23 @@ public class FullyQualifiedReflectivePathTerminal
}
@Override
public @Nullable SqmExpressible<?> getNodeType() {
public @Nullable SqmExpressible<E> getNodeType() {
return expressibleType;
}
@Override
public Object accept(SemanticQueryWalker walker) {
return handler.apply( walker );
public <X> X accept(SemanticQueryWalker<X> walker) {
return (X) handler.apply( walker );
}
@Override
public JavaType<?> getJavaTypeDescriptor() {
public JavaType<E> getJavaTypeDescriptor() {
return expressibleType == null ? null : expressibleType.getExpressibleJavaType();
}
@Override
public void applyInferableType(@Nullable SqmExpressible type) {
public void applyInferableType(@Nullable SqmExpressible<?> type) {
}
@Override
@ -201,7 +199,7 @@ public class FullyQualifiedReflectivePathTerminal
}
@Override
public SqmExpression<?> as(Class type) {
public <X> SqmExpression<X> as(Class<X> type) {
return null;
}
@ -236,7 +234,7 @@ public class FullyQualifiedReflectivePathTerminal
}
@Override
public SqmExpression cast(Class type) {
public <X> SqmExpression<X> cast(Class<X> type) {
return null;
}
@ -266,7 +264,7 @@ public class FullyQualifiedReflectivePathTerminal
}
@Override
public JpaSelection<?> alias(String name) {
public JpaSelection<E> alias(String name) {
return null;
}

View File

@ -337,7 +337,7 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer {
@Override
public void consumeIdentifier(String identifier, boolean isTerminal, boolean allowReuse) {
if ( path.length() != 0 ) {
if ( !path.isEmpty() ) {
path.append( '.' );
}
path.append( identifier );

View File

@ -53,8 +53,8 @@ public class QualifiedJoinPredicatePathConsumer extends BasicDotIdentifierConsum
final SqmCreationProcessingState processingState = getCreationState().getCurrentProcessingState();
// First, we need to find out if the current join is part of current processing query
final SqmQuery<?> currentProcessingQuery = processingState.getProcessingQuery();
if ( currentProcessingQuery instanceof SqmSelectQuery<?> ) {
final SqmQuerySpec<?> querySpec = ( (SqmSelectQuery<?>) currentProcessingQuery ).getQuerySpec();
if ( currentProcessingQuery instanceof SqmSelectQuery<?> selectQuery ) {
final SqmQuerySpec<?> querySpec = selectQuery.getQuerySpec();
final SqmFromClause fromClause = querySpec.getFromClause();
// If the current processing query contains the root of the current join,
// then the root of the processing path must be a root of one of the parent queries
@ -96,8 +96,8 @@ public class QualifiedJoinPredicatePathConsumer extends BasicDotIdentifierConsum
SqmCreationProcessingState processingState) {
while ( processingState != null ) {
final SqmQuery<?> processingQuery = processingState.getProcessingQuery();
if ( processingQuery instanceof SqmSelectQuery<?> ) {
final SqmQuerySpec<?> querySpec = ( (SqmSelectQuery<?>) processingQuery ).getQuerySpec();
if ( processingQuery instanceof SqmSelectQuery<?> selectQuery ) {
final SqmQuerySpec<?> querySpec = selectQuery.getQuerySpec();
final SqmFromClause fromClause = querySpec.getFromClause();
// If we are in a subquery, the "foreign" from element could be one of the subquery roots,
// which is totally fine. The aim of this check is to prevent uses of different "spaces"