HHH-15132 - Improvements for NavigablePath
- dropped `NavigablePath#fullPath` field - `#getFullPath` is now "(re)built" on demand - adjust uses of `NavigablePath#getFullPath` - refactor `NavigablePath` constructors
This commit is contained in:
parent
f474449e7d
commit
e496ec45ea
|
@ -11,6 +11,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
@ -662,8 +663,11 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
|||
for ( int i = 1; i < propertyPathParts.length; i++ ) {
|
||||
if ( ! ( fetchable instanceof FetchableContainer ) ) {
|
||||
throw new MappingException(
|
||||
"Non-terminal property path [" + navigablePath.getFullPath()
|
||||
+ " did not reference FetchableContainer"
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Non-terminal property path did not reference FetchableContainer - %s ",
|
||||
navigablePath
|
||||
)
|
||||
);
|
||||
}
|
||||
fetchable = (Fetchable) ( (FetchableContainer) fetchable ).findSubPart( propertyPathParts[i], null );
|
||||
|
@ -869,7 +873,11 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
|||
this.tableAlias = hbmCollectionReturn.getAlias();
|
||||
if ( tableAlias == null ) {
|
||||
throw new MappingException(
|
||||
"<return-collection/> did not specify alias [" + collectionPath.getFullPath() + "]"
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"<return-collection/> did not specify alias - %s",
|
||||
collectionPath
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -407,8 +407,11 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
|||
for ( int i = 1; i < propertyPathParts.length; i++ ) {
|
||||
if ( ! ( subPart instanceof ModelPartContainer ) ) {
|
||||
throw new MappingException(
|
||||
"Non-terminal property path [" + navigablePath.getFullPath()
|
||||
+ " did not reference FetchableContainer"
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Non-terminal property path did not reference FetchableContainer - %s ",
|
||||
navigablePath
|
||||
)
|
||||
);
|
||||
}
|
||||
navigablePath = navigablePath.append( propertyPathParts[ i ] );
|
||||
|
|
|
@ -899,8 +899,8 @@ public class ToOneAttributeMapping
|
|||
final NavigablePath parentPath = grandparentNavigablePath.getParent();
|
||||
// This can be null for a collection loader
|
||||
if ( parentPath == null ) {
|
||||
return grandparentNavigablePath.getFullPath().equals(
|
||||
entityMappingType.findSubPart( bidirectionalAttributeName ).getNavigableRole().getFullPath()
|
||||
return grandparentNavigablePath.equals(
|
||||
entityMappingType.findSubPart( bidirectionalAttributeName ).getNavigableRole()
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -78,8 +78,8 @@ public class QualifiedJoinPredicatePathConsumer extends BasicDotIdentifierConsum
|
|||
String.format(
|
||||
Locale.ROOT,
|
||||
"SqmQualifiedJoin predicate referred to SqmRoot [`%s`] other than the join's root [`%s`]",
|
||||
pathRoot.getNavigablePath().getFullPath(),
|
||||
sqmJoin.getNavigablePath().getFullPath()
|
||||
pathRoot.getNavigablePath(),
|
||||
sqmJoin.getNavigablePath()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -110,8 +110,8 @@ public class QualifiedJoinPredicatePathConsumer extends BasicDotIdentifierConsum
|
|||
String.format(
|
||||
Locale.ROOT,
|
||||
"SqmQualifiedJoin predicate referred to SqmRoot [`%s`] other than the join's root [`%s`]",
|
||||
pathRoot.getNavigablePath().getFullPath(),
|
||||
sqmJoin.getNavigablePath().getFullPath()
|
||||
pathRoot.getNavigablePath(),
|
||||
sqmJoin.getNavigablePath()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2291,7 +2291,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
throw new NotYetImplementedFor6Exception( "Path continuation from `id()` reference not yet implemented" );
|
||||
}
|
||||
|
||||
throw new SemanticException( "Path does not resolve to an entity type '" + sqmPath.getNavigablePath().getFullPath() + "'" );
|
||||
throw new SemanticException( "Path does not resolve to an entity type '" + sqmPath.getNavigablePath() + "'" );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2312,7 +2312,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
throw new SemanticException(
|
||||
String.format(
|
||||
"Path '%s' resolved to entity type '%s' which does not define a version",
|
||||
sqmPath.getNavigablePath().getFullPath(), identifiableType.getTypeName()
|
||||
sqmPath.getNavigablePath(),
|
||||
identifiableType.getTypeName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -2320,7 +2321,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
return sqmPath.get( versionAttribute );
|
||||
}
|
||||
|
||||
throw new SemanticException( "Path does not resolve to an entity type '" + sqmPath.getNavigablePath().getFullPath() + "'" );
|
||||
throw new SemanticException( "Path does not resolve to an entity type '" + sqmPath.getNavigablePath() + "'" );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2341,7 +2342,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
throw new SemanticException(
|
||||
String.format(
|
||||
"Path '%s' resolved to entity type '%s' which does not define a natural id",
|
||||
sqmPath.getNavigablePath().getFullPath(), identifiableType.getTypeName()
|
||||
sqmPath.getNavigablePath(),
|
||||
identifiableType.getTypeName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -2349,7 +2351,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
throw new SemanticException(
|
||||
String.format(
|
||||
"Path '%s' resolved to entity type '%s' which defines multiple natural ids",
|
||||
sqmPath.getNavigablePath().getFullPath(), identifiableType.getTypeName()
|
||||
sqmPath.getNavigablePath(),
|
||||
identifiableType.getTypeName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -2360,7 +2363,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
return sqmPath.get( naturalIdAttribute );
|
||||
}
|
||||
|
||||
throw new SemanticException( "Path does not resolve to an entity type '" + sqmPath.getNavigablePath().getFullPath() + "'" );
|
||||
throw new SemanticException( "Path does not resolve to an entity type '" + sqmPath.getNavigablePath() + "'" );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2381,7 +2384,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
String.format(
|
||||
Locale.ROOT,
|
||||
"`%s` used in `fk()` only supported for to-one mappings, but found `%s`",
|
||||
sqmPath.getNavigablePath().getFullPath(),
|
||||
sqmPath.getNavigablePath(),
|
||||
toOneReference
|
||||
)
|
||||
);
|
||||
|
|
|
@ -55,7 +55,7 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
|
|||
|
||||
@Override
|
||||
public void register(SqmPath<?> sqmPath) {
|
||||
SqmTreeCreationLogger.LOGGER.tracef( "SqmProcessingIndex#register(SqmPath) : %s", sqmPath.getNavigablePath().getFullPath() );
|
||||
SqmTreeCreationLogger.LOGGER.tracef( "SqmProcessingIndex#register(SqmPath) : %s", sqmPath.getNavigablePath() );
|
||||
|
||||
// Generally we:
|
||||
// 1) add the path to the path-by-path map
|
||||
|
|
|
@ -26,7 +26,7 @@ public class UnknownPathException extends SemanticException {
|
|||
"Could not resolve path `%s` relative to %s (%s)",
|
||||
name,
|
||||
base.getReferencedPathSource().getSqmPathType().getTypeName(),
|
||||
base.getNavigablePath().getFullPath()
|
||||
base.getNavigablePath()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
processStanza(
|
||||
"delete",
|
||||
() -> {
|
||||
logWithIndentation( "[target = %s]", statement.getTarget().getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "[target = %s]", statement.getTarget().getNavigablePath() );
|
||||
visitWhereClause( statement.getWhereClause() );
|
||||
}
|
||||
);
|
||||
|
@ -298,7 +298,7 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
processStanza(
|
||||
"insert",
|
||||
() -> {
|
||||
logWithIndentation( "[target = %s]", statement.getTarget().getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "[target = %s]", statement.getTarget().getNavigablePath() );
|
||||
processStanza(
|
||||
"into",
|
||||
() -> statement.getInsertionTargetPaths().forEach( sqmPath -> sqmPath.accept( this ) )
|
||||
|
@ -317,7 +317,7 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
processStanza(
|
||||
"insert",
|
||||
() -> {
|
||||
logWithIndentation( "[target = %s]", statement.getTarget().getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "[target = %s]", statement.getTarget().getNavigablePath() );
|
||||
processStanza(
|
||||
"into",
|
||||
() -> statement.getInsertionTargetPaths().forEach( sqmPath -> sqmPath.accept( this ) )
|
||||
|
@ -361,7 +361,7 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
processStanza(
|
||||
statement.isVersioned() ? "update versioned" : "update",
|
||||
() -> {
|
||||
logWithIndentation( "[target = %s]", statement.getTarget().getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "[target = %s]", statement.getTarget().getNavigablePath() );
|
||||
|
||||
visitSetClause( statement.getSetClause() );
|
||||
|
||||
|
@ -495,7 +495,7 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
public Object visitRootPath(SqmRoot sqmRoot) {
|
||||
processStanza(
|
||||
"root",
|
||||
'`' + sqmRoot.getNavigablePath().getFullPath() + '`',
|
||||
"`" + sqmRoot.getNavigablePath() + "`",
|
||||
() -> processJoins( sqmRoot )
|
||||
);
|
||||
|
||||
|
@ -517,7 +517,7 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
public Object visitCrossJoin(SqmCrossJoin joinedFromElement) {
|
||||
processStanza(
|
||||
"cross",
|
||||
'`' + joinedFromElement.getNavigablePath().getFullPath() + '`',
|
||||
"`" + joinedFromElement.getNavigablePath() + "`",
|
||||
() -> processJoins( joinedFromElement )
|
||||
);
|
||||
|
||||
|
@ -528,7 +528,7 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
public Object visitPluralPartJoin(SqmPluralPartJoin<?, ?> joinedFromElement) {
|
||||
processStanza(
|
||||
"plural-part",
|
||||
'`' + joinedFromElement.getNavigablePath().getFullPath() + '`',
|
||||
"`" + joinedFromElement.getNavigablePath() + "`",
|
||||
() -> processJoins( joinedFromElement )
|
||||
);
|
||||
|
||||
|
@ -552,12 +552,12 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
@Override
|
||||
public Object visitQualifiedEntityJoin(SqmEntityJoin joinedFromElement) {
|
||||
if ( inJoinPredicate ) {
|
||||
logWithIndentation( "-> [joined-path] - `%s`", joinedFromElement.getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "-> [joined-path] - `%s`", joinedFromElement.getNavigablePath() );
|
||||
}
|
||||
else {
|
||||
processStanza(
|
||||
"entity",
|
||||
'`' + joinedFromElement.getNavigablePath().getFullPath() + '`',
|
||||
"`" + joinedFromElement.getNavigablePath() + "`",
|
||||
() -> {
|
||||
processJoinPredicate( joinedFromElement );
|
||||
processJoins( joinedFromElement );
|
||||
|
@ -570,12 +570,12 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
@Override
|
||||
public Object visitQualifiedAttributeJoin(SqmAttributeJoin joinedFromElement) {
|
||||
if ( inJoinPredicate ) {
|
||||
logWithIndentation( "-> [joined-path] - `%s`", joinedFromElement.getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "-> [joined-path] - `%s`", joinedFromElement.getNavigablePath() );
|
||||
}
|
||||
else {
|
||||
processStanza(
|
||||
"attribute",
|
||||
'`' + joinedFromElement.getNavigablePath().getFullPath() + '`',
|
||||
"`" + joinedFromElement.getNavigablePath() + "`",
|
||||
() -> {
|
||||
logIndented( "[fetched = " + joinedFromElement.isFetched() + ']' );
|
||||
|
||||
|
@ -589,56 +589,56 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
|
||||
@Override
|
||||
public Object visitBasicValuedPath(SqmBasicValuedSimplePath path) {
|
||||
logWithIndentation( "-> [basic-path] - `%s`", path.getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "-> [basic-path] - `%s`", path.getNavigablePath() );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitEmbeddableValuedPath(SqmEmbeddedValuedSimplePath path) {
|
||||
logWithIndentation( "-> [embedded-path] - `%s`", path.getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "-> [embedded-path] - `%s`", path.getNavigablePath() );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAnyValuedValuedPath(SqmAnyValuedSimplePath<?> path) {
|
||||
logWithIndentation( "-> [any-path] - `%s`", path.getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "-> [any-path] - `%s`", path.getNavigablePath() );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitNonAggregatedCompositeValuedPath(NonAggregatedCompositeSimplePath<?> path) {
|
||||
logWithIndentation( "-> [non-aggregated-composite-path] - `%s`", path.getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "-> [non-aggregated-composite-path] - `%s`", path.getNavigablePath() );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitFkExpression(SqmFkExpression<?> fkExpression) {
|
||||
logWithIndentation( "-> [fk-ref] - `%s`", fkExpression.getToOnePath().getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "-> [fk-ref] - `%s`", fkExpression.getToOnePath().getNavigablePath() );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitSelfInterpretingSqmPath(SelfInterpretingSqmPath<?> sqmPath) {
|
||||
logWithIndentation( "-> [self-interpreting-path] - `%s`", sqmPath.getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "-> [self-interpreting-path] - `%s`", sqmPath.getNavigablePath() );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitEntityValuedPath(SqmEntityValuedSimplePath path) {
|
||||
logWithIndentation( "-> [entity-path] - `%s`", path.getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "-> [entity-path] - `%s`", path.getNavigablePath() );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitPluralValuedPath(SqmPluralValuedSimplePath path) {
|
||||
logWithIndentation( "-> [plural-path] - `%s`", path.getNavigablePath().getFullPath() );
|
||||
logWithIndentation( "-> [plural-path] - `%s`", path.getNavigablePath() );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ public class BasicValuedPathInterpretation<T> extends AbstractSqmPathInterpretat
|
|||
}
|
||||
}
|
||||
|
||||
throw new SemanticException( "`" + sqmPath.getNavigablePath().getFullPath() + "` did not reference a known model part" );
|
||||
throw new SemanticException( "`" + sqmPath.getNavigablePath() + "` did not reference a known model part" );
|
||||
}
|
||||
|
||||
final TableReference tableReference = tableGroup.resolveTableReference(
|
||||
|
@ -148,7 +148,7 @@ public class BasicValuedPathInterpretation<T> extends AbstractSqmPathInterpretat
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BasicValuedPathInterpretation(" + getNavigablePath().getFullPath() + ')';
|
||||
return "BasicValuedPathInterpretation(" + getNavigablePath() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -102,7 +102,7 @@ public class EmbeddableValuedPathInterpretation<T> extends AbstractSqmPathInterp
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EmbeddableValuedPathInterpretation(" + getNavigablePath().getFullPath() + ')';
|
||||
return "EmbeddableValuedPathInterpretation(" + getNavigablePath() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -434,7 +434,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
|||
"Passed attribute name [%s] did not correspond to a collection (bag) reference [%s] relative to %s",
|
||||
attributeName,
|
||||
joinedPathSource,
|
||||
getNavigablePath().getFullPath()
|
||||
getNavigablePath()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -465,7 +465,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
|||
"Passed attribute name [%s] did not correspond to a collection (set) reference [%s] relative to %s",
|
||||
attributeName,
|
||||
joinedPathSource,
|
||||
getNavigablePath().getFullPath()
|
||||
getNavigablePath()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -496,7 +496,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
|||
"Passed attribute name [%s] did not correspond to a collection (list) reference [%s] relative to %s",
|
||||
attributeName,
|
||||
joinedPathSource,
|
||||
getNavigablePath().getFullPath()
|
||||
getNavigablePath()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -527,7 +527,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
|||
"Passed attribute name [%s] did not correspond to a collection (map) reference [%s] relative to %s",
|
||||
attributeName,
|
||||
joinedPathSource,
|
||||
getNavigablePath().getFullPath()
|
||||
getNavigablePath()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -659,7 +659,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
|||
"Passed attribute [%s] did not correspond to a joinable reference [%s] relative to %s",
|
||||
joinedPathSource.getPathName(),
|
||||
joinedPathSource,
|
||||
getNavigablePath().getFullPath()
|
||||
getNavigablePath()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -195,6 +195,6 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "(" + navigablePath.getFullPath() + ")";
|
||||
return getClass().getSimpleName() + "(" + navigablePath + ")";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ public class SqmPluralPartJoin<O,T> extends AbstractSqmJoin<O,T> implements SqmQ
|
|||
return String.format(
|
||||
Locale.ROOT,
|
||||
"SqmPluralPartJoin(%s : %s)",
|
||||
getNavigablePath().getFullPath(),
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource().getPathName()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ public class SqmSingularJoin<O,T> extends AbstractSqmAttributeJoin<O,T> {
|
|||
return String.format(
|
||||
Locale.ROOT,
|
||||
"SqmSingularJoin(%s : %s)",
|
||||
getNavigablePath().getFullPath(),
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource().getPathName()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@ public interface DotIdentifierSequence {
|
|||
/**
|
||||
* The full sequence text. E.g., given the sequence `a.b.c`,
|
||||
* this returns `a.b.c`
|
||||
*
|
||||
* @implNote This method may dynamically build the returned
|
||||
* String and should be avoided for critical paths (comparisons, e.g.).
|
||||
*/
|
||||
String getFullPath();
|
||||
|
||||
|
|
|
@ -24,62 +24,79 @@ public class EntityIdentifierNavigablePath extends NavigablePath {
|
|||
this.identifierAttributeName = identifierAttributeName;
|
||||
}
|
||||
|
||||
public String getIdentifierAttributeName() {
|
||||
return identifierAttributeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalName() {
|
||||
return EntityIdentifierMapping.ROLE_LOCAL_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getParent().getFullPath().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if ( other == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( other == this ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! ( other instanceof NavigablePath ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final NavigablePath otherPath = (NavigablePath) other;
|
||||
|
||||
if ( getFullPath().equals( ( (NavigablePath) other ).getFullPath() ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( getParent() == null ) {
|
||||
if ( otherPath.getParent() != null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//noinspection RedundantIfStatement
|
||||
if ( localNamesMatch( otherPath) ) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( otherPath.getParent() == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getParent().equals( otherPath.getParent() )
|
||||
&& localNamesMatch( otherPath );
|
||||
}
|
||||
|
||||
private boolean localNamesMatch(NavigablePath otherPath) {
|
||||
protected boolean localNamesMatch(DotIdentifierSequence otherPath) {
|
||||
final String otherLocalName = otherPath.getLocalName();
|
||||
|
||||
return otherLocalName.equals( getLocalName() )
|
||||
|| otherLocalName.equals( identifierAttributeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean localNamesMatch(EntityIdentifierNavigablePath otherPath) {
|
||||
return super.localNamesMatch( otherPath );
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public int hashCode() {
|
||||
// return getParent().getFullPath().hashCode();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean equals(Object other) {
|
||||
// if ( other == null ) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// if ( other == this ) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// if ( ! ( other instanceof NavigablePath ) ) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// final NavigablePath otherPath = (NavigablePath) other;
|
||||
//
|
||||
// if ( getFullPath().equals( ( (NavigablePath) other ).getFullPath() ) ) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// if ( getParent() == null ) {
|
||||
// if ( otherPath.getParent() != null ) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// //noinspection RedundantIfStatement
|
||||
// if ( localNamesMatch( otherPath) ) {
|
||||
// return true;
|
||||
//
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// if ( otherPath.getParent() == null ) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return getParent().equals( otherPath.getParent() )
|
||||
// && localNamesMatch( otherPath );
|
||||
// }
|
||||
//
|
||||
// private boolean localNamesMatch(NavigablePath otherPath) {
|
||||
// final String otherLocalName = otherPath.getLocalName();
|
||||
//
|
||||
// return otherLocalName.equals( getLocalName() )
|
||||
// || otherLocalName.equals( identifierAttributeName );
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
@ -25,41 +26,9 @@ public class NavigablePath implements DotIdentifierSequence, Serializable {
|
|||
private final NavigablePath parent;
|
||||
private final String localName;
|
||||
private final String alias;
|
||||
|
||||
private final String identifierForTableGroup;
|
||||
|
||||
private final String fullPath;
|
||||
|
||||
public NavigablePath(NavigablePath parent, String navigableName) {
|
||||
this.parent = parent;
|
||||
this.alias = null;
|
||||
|
||||
// the _identifierMapper is a "hidden property" on entities with composite keys.
|
||||
// concatenating it will prevent the path from correctly being used to look up
|
||||
// various things such as criteria paths and fetch profile association paths
|
||||
if ( IDENTIFIER_MAPPER_PROPERTY.equals( navigableName ) ) {
|
||||
this.localName = "";
|
||||
this.identifierForTableGroup = parent != null ? parent.getIdentifierForTableGroup() : "";
|
||||
|
||||
this.fullPath = parent != null ? parent.getFullPath() : "";
|
||||
}
|
||||
else {
|
||||
this.localName = navigableName;
|
||||
if ( parent != null ) {
|
||||
final String parentFullPath = parent.getFullPath();
|
||||
this.fullPath = StringHelper.isEmpty( parentFullPath )
|
||||
? navigableName
|
||||
: parentFullPath + "." + navigableName;
|
||||
this.identifierForTableGroup = StringHelper.isEmpty( parent.getIdentifierForTableGroup() )
|
||||
? navigableName
|
||||
: parent.getIdentifierForTableGroup() + "." + navigableName;
|
||||
}
|
||||
else {
|
||||
this.fullPath = navigableName;
|
||||
this.identifierForTableGroup = navigableName;
|
||||
}
|
||||
}
|
||||
}
|
||||
private final FullPathCalculator fullPathCalculator;
|
||||
private final int hashCode;
|
||||
|
||||
public NavigablePath(String localName) {
|
||||
this( localName, null );
|
||||
|
@ -67,88 +36,69 @@ public class NavigablePath implements DotIdentifierSequence, Serializable {
|
|||
|
||||
public NavigablePath(String rootName, String alias) {
|
||||
this.parent = null;
|
||||
this.alias = StringHelper.nullIfEmpty( alias );
|
||||
this.alias = alias = StringHelper.nullIfEmpty( alias );
|
||||
this.localName = rootName;
|
||||
this.identifierForTableGroup = rootName;
|
||||
|
||||
this.fullPath = alias == null ? rootName : rootName + "(" + alias + ")";
|
||||
this.fullPathCalculator = NavigablePath::calculateRootFullPath;
|
||||
|
||||
this.hashCode = localName.hashCode() + ( alias == null ? 0 : alias.hashCode() );
|
||||
}
|
||||
|
||||
public NavigablePath(NavigablePath parent, String property, String alias) {
|
||||
alias = StringHelper.nullIfEmpty( alias );
|
||||
final String navigableName = alias == null
|
||||
? property
|
||||
: property + '(' + alias + ')';
|
||||
public NavigablePath(NavigablePath parent, String navigableName) {
|
||||
this( parent, navigableName, null );
|
||||
}
|
||||
|
||||
public NavigablePath(NavigablePath parent, String localName, String alias) {
|
||||
assert parent != null;
|
||||
|
||||
this.parent = parent;
|
||||
this.alias = alias;
|
||||
this.alias = alias = StringHelper.nullIfEmpty( alias );
|
||||
|
||||
final String aliasedLocalName = alias == null
|
||||
? localName
|
||||
: localName + '(' + alias + ')';
|
||||
|
||||
this.hashCode = parent.hashCode() + aliasedLocalName.hashCode();
|
||||
|
||||
// the _identifierMapper is a "hidden property" on entities with composite keys.
|
||||
// concatenating it will prevent the path from correctly being used to look up
|
||||
// various things such as criteria paths and fetch profile association paths
|
||||
if ( IDENTIFIER_MAPPER_PROPERTY.equals( navigableName ) ) {
|
||||
this.fullPath = parent != null ? parent.getFullPath() : "";
|
||||
if ( IDENTIFIER_MAPPER_PROPERTY.equals( localName ) ) {
|
||||
this.localName = "";
|
||||
identifierForTableGroup = parent != null ? parent.getFullPath() : "";
|
||||
this.identifierForTableGroup = parent.getFullPath();
|
||||
this.fullPathCalculator = NavigablePath::calculateIdMapperFullPath;
|
||||
}
|
||||
else {
|
||||
this.localName = property;
|
||||
if ( parent != null ) {
|
||||
final String parentFullPath = parent.getFullPath();
|
||||
this.fullPath = StringHelper.isEmpty( parentFullPath )
|
||||
? navigableName
|
||||
: parentFullPath + "." + navigableName;
|
||||
this.identifierForTableGroup = StringHelper.isEmpty( parent.getIdentifierForTableGroup() )
|
||||
? navigableName
|
||||
: parent.getIdentifierForTableGroup() + "." + property;
|
||||
}
|
||||
else {
|
||||
this.fullPath = navigableName;
|
||||
this.identifierForTableGroup = property;
|
||||
}
|
||||
this.localName = localName;
|
||||
this.identifierForTableGroup = StringHelper.isEmpty( parent.getIdentifierForTableGroup() )
|
||||
? aliasedLocalName
|
||||
: parent.getIdentifierForTableGroup() + "." + localName;
|
||||
this.fullPathCalculator = NavigablePath::calculateNormalFullPath;
|
||||
}
|
||||
}
|
||||
|
||||
public NavigablePath() {
|
||||
this( "" );
|
||||
}
|
||||
|
||||
public NavigablePath(
|
||||
NavigablePath parent,
|
||||
String fullPath,
|
||||
String localName,
|
||||
String identifierForTableGroup) {
|
||||
String alias,
|
||||
String identifierForTableGroup,
|
||||
FullPathCalculator fullPathCalculator,
|
||||
int hashCode) {
|
||||
this.parent = parent;
|
||||
this.alias = null;
|
||||
this.fullPath = fullPath;
|
||||
this.localName = localName;
|
||||
this.hashCode = hashCode;
|
||||
this.alias = StringHelper.nullIfEmpty( alias );
|
||||
this.identifierForTableGroup = identifierForTableGroup;
|
||||
this.fullPathCalculator = fullPathCalculator;
|
||||
}
|
||||
|
||||
public NavigablePath treatAs(String entityName) {
|
||||
return new TreatedNavigablePath( this, entityName );
|
||||
}
|
||||
|
||||
public NavigablePath treatAs(String entityName, String alias) {
|
||||
return new TreatedNavigablePath( this, entityName, alias );
|
||||
}
|
||||
|
||||
public NavigablePath append(String property) {
|
||||
return new NavigablePath( this, property );
|
||||
}
|
||||
|
||||
public NavigablePath append(String property, String alias) {
|
||||
return new NavigablePath( this, property, alias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getParent() {
|
||||
return parent instanceof TreatedNavigablePath ? parent.getParent() : parent;
|
||||
}
|
||||
|
||||
public NavigablePath getRealParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalName() {
|
||||
return localName;
|
||||
}
|
||||
|
@ -162,17 +112,75 @@ public class NavigablePath implements DotIdentifierSequence, Serializable {
|
|||
}
|
||||
|
||||
public String getIdentifierForTableGroup() {
|
||||
// todo (6.0) : is this `if` really needed? seems this is already handled in constructors
|
||||
if ( parent == null ) {
|
||||
return fullPath;
|
||||
}
|
||||
return identifierForTableGroup;
|
||||
}
|
||||
|
||||
public String getFullPath() {
|
||||
return fullPath;
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if ( this == other ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( other == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final DotIdentifierSequence otherPath = (DotIdentifierSequence) other;
|
||||
if ( ! localNamesMatch( otherPath ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( otherPath instanceof NavigablePath ) {
|
||||
final NavigablePath otherNavigablePath = (NavigablePath) otherPath;
|
||||
if ( ! Objects.equals( getAlias(), otherNavigablePath.getAlias() ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return Objects.equals( getParent(), otherPath.getParent() );
|
||||
}
|
||||
|
||||
protected boolean localNamesMatch(DotIdentifierSequence other) {
|
||||
if ( other instanceof EntityIdentifierNavigablePath ) {
|
||||
return localNamesMatch( (EntityIdentifierNavigablePath) other );
|
||||
}
|
||||
|
||||
return Objects.equals( getLocalName(), other.getLocalName() );
|
||||
}
|
||||
|
||||
protected boolean localNamesMatch(EntityIdentifierNavigablePath other) {
|
||||
return Objects.equals( getLocalName(), other.getLocalName() )
|
||||
|| Objects.equals( getLocalName(), other.getIdentifierAttributeName() );
|
||||
}
|
||||
|
||||
public NavigablePath append(String property) {
|
||||
return new NavigablePath( this, property );
|
||||
}
|
||||
|
||||
public NavigablePath append(String property, String alias) {
|
||||
return new NavigablePath( this, property, alias );
|
||||
}
|
||||
|
||||
public NavigablePath treatAs(String entityName) {
|
||||
return new TreatedNavigablePath( this, entityName );
|
||||
}
|
||||
|
||||
public NavigablePath treatAs(String entityName, String alias) {
|
||||
return new TreatedNavigablePath( this, entityName, alias );
|
||||
}
|
||||
|
||||
public NavigablePath getRealParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this path is part of the given path's parent
|
||||
*/
|
||||
public boolean isParent(NavigablePath navigablePath) {
|
||||
while ( navigablePath != null ) {
|
||||
if ( this.equals( navigablePath.getParent() ) ) {
|
||||
|
@ -183,45 +191,49 @@ public class NavigablePath implements DotIdentifierSequence, Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullPath() {
|
||||
return fullPathCalculator.calculateFullPath( parent, localName, alias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fullPath;
|
||||
return getFullPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return fullPath.hashCode();
|
||||
/**
|
||||
* Effectively a tri-function
|
||||
*/
|
||||
@FunctionalInterface
|
||||
protected interface FullPathCalculator extends Serializable {
|
||||
String calculateFullPath(NavigablePath parent, String localName, String alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if ( this == other ) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* The pattern used for root NavigablePaths
|
||||
*/
|
||||
protected static String calculateRootFullPath(NavigablePath parent, String rootName, String alias) {
|
||||
assert parent == null;
|
||||
return alias == null ? rootName : rootName + "(" + alias + ")";
|
||||
}
|
||||
|
||||
if ( other instanceof EntityIdentifierNavigablePath ) {
|
||||
final EntityIdentifierNavigablePath otherPath = (EntityIdentifierNavigablePath) other;
|
||||
return otherPath.equals( this );
|
||||
}
|
||||
/**
|
||||
* The normal pattern used for the "full path"
|
||||
*/
|
||||
private static String calculateNormalFullPath(NavigablePath parent, String localName, String alias) {
|
||||
assert parent != null;
|
||||
|
||||
if ( ! ( other instanceof NavigablePath ) ) {
|
||||
return false;
|
||||
}
|
||||
final String parentFullPath = parent.getFullPath();
|
||||
final String baseFullPath = StringHelper.isEmpty( parentFullPath )
|
||||
? localName
|
||||
: parentFullPath + "." + localName;
|
||||
return alias == null ? baseFullPath : baseFullPath + "(" + alias + ")";
|
||||
}
|
||||
|
||||
final NavigablePath otherPath = (NavigablePath) other;
|
||||
|
||||
// todo (6.0) : checking the full paths is definitely better performance
|
||||
// But I'm not sure it is correct in all cases. Take cases referencing
|
||||
// an identifier at some level - the actual EntityIdentifierNavigablePath
|
||||
// subclass has special handling for one path using the "role name" (`"{id}"`)
|
||||
// while the other might instead use the attribute name
|
||||
// return Objects.equals( getFullPath(), otherPath.getFullPath() );
|
||||
|
||||
if ( getParent() == null ) {
|
||||
return otherPath.getParent() == null;
|
||||
}
|
||||
|
||||
return getParent().equals( otherPath.getParent() )
|
||||
&& getLocalName().equals( otherPath.getLocalName() );
|
||||
/**
|
||||
* Pattern used for `_identifierMapper`
|
||||
*/
|
||||
protected static String calculateIdMapperFullPath(NavigablePath parent, String localName, String alias) {
|
||||
return parent != null ? parent.getFullPath() : "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,14 +23,21 @@ public class TreatedNavigablePath extends NavigablePath {
|
|||
public TreatedNavigablePath(NavigablePath parent, String entityTypeName, String alias) {
|
||||
super(
|
||||
parent,
|
||||
alias == null ? "treat(" + parent.getFullPath() + " as " + entityTypeName + ")"
|
||||
: "treat(" + parent.getFullPath() + " as " + entityTypeName + ")(" + alias + ")",
|
||||
entityTypeName,
|
||||
"treat(" + parent.getFullPath() + " as " + entityTypeName + ")"
|
||||
alias,
|
||||
"treat(" + parent + " as " + entityTypeName + ")",
|
||||
TreatedNavigablePath::calculateTreatedFullPath,
|
||||
1
|
||||
);
|
||||
assert !( parent instanceof TreatedNavigablePath );
|
||||
}
|
||||
|
||||
protected static String calculateTreatedFullPath(NavigablePath parent, String localName, String alias) {
|
||||
return alias == null
|
||||
? "treat(" + parent + " as " + localName + ")"
|
||||
: "treat(" + parent + " as " + localName + ")(" + alias + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath treatAs(String entityName) {
|
||||
return new TreatedNavigablePath( getRealParent(), entityName );
|
||||
|
@ -41,25 +48,25 @@ public class TreatedNavigablePath extends NavigablePath {
|
|||
return new TreatedNavigablePath( getRealParent(), entityName, alias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getFullPath().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if ( other == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( other == this ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! ( other instanceof NavigablePath ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getFullPath().equals( ( (NavigablePath) other ).getFullPath() );
|
||||
}
|
||||
// @Override
|
||||
// public int hashCode() {
|
||||
// return getFullPath().hashCode();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean equals(Object other) {
|
||||
// if ( other == null ) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// if ( other == this ) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// if ( ! ( other instanceof NavigablePath ) ) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return getFullPath().equals( ( (NavigablePath) other ).getFullPath() );
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public abstract class AbstractColumnReferenceQualifier implements ColumnReferenc
|
|||
Locale.ROOT,
|
||||
"Unable to determine TableReference (`%s`) for `%s`",
|
||||
tableExpression,
|
||||
navigablePath.getFullPath()
|
||||
navigablePath
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public abstract class DerivedTableReference extends AbstractTableReference {
|
|||
boolean allowFkOptimization) {
|
||||
throw new UnknownTableReferenceException(
|
||||
tableExpression,
|
||||
"TableReferences cannot be resolved relative to DerivedTableReferences - `" + tableExpression + "` : " + navigablePath.getFullPath()
|
||||
"TableReferences cannot be resolved relative to DerivedTableReferences - `" + tableExpression + "` : " + navigablePath
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ public class LazyTableGroup extends DelegatingTableGroup {
|
|||
Locale.ROOT,
|
||||
"Unable to determine TableReference (`%s`) for `%s`",
|
||||
tableExpression,
|
||||
navigablePath.getFullPath()
|
||||
navigablePath
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ public class MappedByTableGroup extends DelegatingTableGroup implements VirtualT
|
|||
Locale.ROOT,
|
||||
"Unable to determine TableReference (`%s`) for `%s`",
|
||||
tableExpression,
|
||||
navigablePath.getFullPath()
|
||||
navigablePath
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ public class NamedTableReference extends AbstractTableReference {
|
|||
Locale.ROOT,
|
||||
"Unable to determine TableReference (`%s`) for `%s`",
|
||||
tableExpression,
|
||||
navigablePath.getFullPath()
|
||||
navigablePath
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ public class UnionTableReference extends NamedTableReference {
|
|||
Locale.ROOT,
|
||||
"Unable to determine TableReference (`%s`) for `%s`",
|
||||
tableExpression,
|
||||
navigablePath.getFullPath()
|
||||
navigablePath
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -290,7 +290,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
EntityLoadingLogging.ENTITY_LOADING_LOGGER.tracef(
|
||||
"(%s) Beginning Initializer#resolveKey process for entity : %s",
|
||||
StringHelper.collapse( this.getClass().getName() ),
|
||||
getNavigablePath().getFullPath()
|
||||
getNavigablePath()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,6 @@ public class EntityResultInitializer extends AbstractEntityInitializer {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return CONCRETE_NAME + "(" + getNavigablePath().getFullPath() + ")";
|
||||
return CONCRETE_NAME + "(" + getNavigablePath() + ")";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ public class ResultsHelper {
|
|||
initializerMap.forEach( (navigablePath, initializer) -> {
|
||||
ResultsLogger.RESULTS_MESSAGE_LOGGER.debugf(
|
||||
" %s -> %s@%s (%s)",
|
||||
navigablePath.getFullPath(),
|
||||
navigablePath,
|
||||
initializer,
|
||||
initializer.hashCode(),
|
||||
initializer.getInitializedPart()
|
||||
|
|
Loading…
Reference in New Issue