1212import org .hibernate .Incubating ;
1313import org .hibernate .internal .util .StringHelper ;
1414
15+ import org .checkerframework .checker .nullness .qual .Nullable ;
16+
17+ import static org .hibernate .internal .util .NullnessUtil .castNonNull ;
18+
1519/**
1620 * A compound name where the root path element is an entity name or a collection role
1721 * and each the path sub-path from the root references a domain or mapping model part
2327public class NavigablePath implements DotIdentifierSequence , Serializable {
2428 public static final String IDENTIFIER_MAPPER_PROPERTY = "_identifierMapper" ;
2529
26- private final NavigablePath parent ;
30+ private final @ Nullable NavigablePath parent ;
2731 private final String localName ;
28- private final String alias ;
32+ private final @ Nullable String alias ;
2933 private final String identifierForTableGroup ;
3034 private final FullPathCalculator fullPathCalculator ;
3135 private final int hashCode ;
@@ -34,7 +38,7 @@ public NavigablePath(String localName) {
3438 this ( localName , null );
3539 }
3640
37- public NavigablePath (String rootName , String alias ) {
41+ public NavigablePath (String rootName , @ Nullable String alias ) {
3842 this .parent = null ;
3943 this .alias = alias = StringHelper .nullIfEmpty ( alias );
4044 this .localName = rootName ;
@@ -49,7 +53,7 @@ public NavigablePath(NavigablePath parent, String navigableName) {
4953 this ( parent , navigableName , null );
5054 }
5155
52- public NavigablePath (NavigablePath parent , String localName , String alias ) {
56+ public NavigablePath (NavigablePath parent , String localName , @ Nullable String alias ) {
5357 assert parent != null ;
5458
5559 this .parent = parent ;
@@ -79,9 +83,9 @@ public NavigablePath(NavigablePath parent, String localName, String alias) {
7983 }
8084
8185 public NavigablePath (
82- NavigablePath parent ,
86+ @ Nullable NavigablePath parent ,
8387 String localName ,
84- String alias ,
88+ @ Nullable String alias ,
8589 String identifierForTableGroup ,
8690 FullPathCalculator fullPathCalculator ,
8791 int hashCode ) {
@@ -94,7 +98,7 @@ public NavigablePath(
9498 }
9599
96100 @ Override
97- public NavigablePath getParent () {
101+ public @ Nullable NavigablePath getParent () {
98102 return parent instanceof TreatedNavigablePath ? parent .getParent () : parent ;
99103 }
100104
@@ -103,7 +107,7 @@ public String getLocalName() {
103107 return localName ;
104108 }
105109
106- public String getAlias () {
110+ public @ Nullable String getAlias () {
107111 return alias ;
108112 }
109113
@@ -121,7 +125,7 @@ public int hashCode() {
121125 }
122126
123127 @ Override
124- public boolean equals (Object other ) {
128+ public boolean equals (@ Nullable Object other ) {
125129 if ( this == other ) {
126130 return true ;
127131 }
@@ -175,14 +179,14 @@ public NavigablePath treatAs(String entityName, String alias) {
175179 return new TreatedNavigablePath ( this , entityName , alias );
176180 }
177181
178- public NavigablePath getRealParent () {
182+ public @ Nullable NavigablePath getRealParent () {
179183 return parent ;
180184 }
181185
182186 /**
183187 * Determine whether this path is part of the given path's parent
184188 */
185- public boolean isParent (NavigablePath navigablePath ) {
189+ public boolean isParent (@ Nullable NavigablePath navigablePath ) {
186190 while ( navigablePath != null ) {
187191 if ( this .equals ( navigablePath .getParent () ) ) {
188192 return true ;
@@ -195,14 +199,15 @@ public boolean isParent(NavigablePath navigablePath) {
195199 /**
196200 * Determine whether the given path is a suffix of this path
197201 */
198- public boolean isSuffix (DotIdentifierSequence dotIdentifierSequence ) {
202+ public boolean isSuffix (@ Nullable DotIdentifierSequence dotIdentifierSequence ) {
199203 if ( dotIdentifierSequence == null ) {
200204 return true ;
201205 }
202206 if ( !localNamesMatch ( dotIdentifierSequence ) ) {
203207 return false ;
204208 }
205- return getParent () != null && getParent ().isSuffix ( dotIdentifierSequence .getParent () );
209+ NavigablePath parent = getParent ();
210+ return parent != null && parent .isSuffix ( dotIdentifierSequence .getParent () );
206211 }
207212
208213 /**
@@ -216,23 +221,24 @@ public boolean isSuffix(DotIdentifierSequence dotIdentifierSequence) {
216221 * or null if the NavigablePath does not contain the suffix.
217222 *
218223 */
219- public NavigablePath trimSuffix (DotIdentifierSequence suffix ) {
224+ public @ Nullable NavigablePath trimSuffix (@ Nullable DotIdentifierSequence suffix ) {
220225 if ( suffix == null ) {
221226 return this ;
222227 }
223228 if ( !getLocalName ().equals ( suffix .getLocalName () ) ) {
224229 return null ;
225230 }
226- if ( getParent () != null ) {
227- return getParent ().trimSuffix ( suffix .getParent () );
231+ NavigablePath parent = getParent ();
232+ if ( parent != null ) {
233+ return parent .trimSuffix ( suffix .getParent () );
228234 }
229235 return null ;
230236 }
231237
232238 /**
233239 * Determine whether this path is part of the given path's parent
234240 */
235- public boolean isParentOrEqual (NavigablePath navigablePath ) {
241+ public boolean isParentOrEqual (@ Nullable NavigablePath navigablePath ) {
236242 while ( navigablePath != null ) {
237243 if ( this .equals ( navigablePath ) ) {
238244 return true ;
@@ -242,15 +248,15 @@ public boolean isParentOrEqual(NavigablePath navigablePath) {
242248 return false ;
243249 }
244250
245- public boolean pathsMatch (NavigablePath p ) {
251+ public boolean pathsMatch (@ Nullable NavigablePath p ) {
246252 return this == p || p != null && localName .equals ( p .localName )
247253 && ( parent == null ? p .parent == null && Objects .equals ( alias , p .alias ) : parent .pathsMatch ( p .parent ) );
248254 }
249255
250256 /**
251257 * Ignores aliases in the resulting String
252258 */
253- public String relativize (NavigablePath base ) {
259+ public @ Nullable String relativize (NavigablePath base ) {
254260 // e.g.
255261 // - base = Root.sub
256262 // - this = Root.sub.stuff
@@ -284,7 +290,7 @@ public void collectPath(String path) {
284290 buffer .append ( path );
285291 }
286292
287- public String resolve () {
293+ public @ Nullable String resolve () {
288294 if ( buffer == null ) {
289295 // Return an empty string instead of null in case the two navigable paths are equal
290296 return matchedBase ? "" : null ;
@@ -323,24 +329,24 @@ public String toString() {
323329 */
324330 @ FunctionalInterface
325331 protected interface FullPathCalculator extends Serializable {
326- String calculateFullPath (NavigablePath parent , String localName , String alias );
332+ String calculateFullPath (@ Nullable NavigablePath parent , String localName , @ Nullable String alias );
327333 }
328334
329335 /**
330336 * The pattern used for root NavigablePaths
331337 */
332- protected static String calculateRootFullPath (NavigablePath parent , String rootName , String alias ) {
338+ protected static String calculateRootFullPath (@ Nullable NavigablePath parent , String rootName , @ Nullable String alias ) {
333339 assert parent == null ;
334340 return alias == null ? rootName : rootName + "(" + alias + ")" ;
335341 }
336342
337343 /**
338344 * The normal pattern used for the "full path"
339345 */
340- private static String calculateNormalFullPath (NavigablePath parent , String localName , String alias ) {
346+ private static String calculateNormalFullPath (@ Nullable NavigablePath parent , String localName , @ Nullable String alias ) {
341347 assert parent != null ;
342348
343- final String parentFullPath = parent .getFullPath ();
349+ final String parentFullPath = castNonNull ( parent ) .getFullPath ();
344350 final String baseFullPath = StringHelper .isEmpty ( parentFullPath )
345351 ? localName
346352 : parentFullPath + "." + localName ;
@@ -350,7 +356,7 @@ private static String calculateNormalFullPath(NavigablePath parent, String local
350356 /**
351357 * Pattern used for `_identifierMapper`
352358 */
353- protected static String calculateIdMapperFullPath (NavigablePath parent , String localName , String alias ) {
359+ protected static String calculateIdMapperFullPath (@ Nullable NavigablePath parent , String localName , @ Nullable String alias ) {
354360 return parent != null ? parent .getFullPath () : "" ;
355361 }
356362}
0 commit comments