44 */
55package org .hibernate .query .sqm .internal ;
66
7- import java .util .ArrayList ;
8- import java .util .IdentityHashMap ;
9- import java .util .LinkedHashMap ;
10- import java .util .List ;
11- import java .util .Map ;
12-
7+ import org .checkerframework .checker .nullness .qual .NonNull ;
138import org .hibernate .query .internal .QueryParameterIdentifiedImpl ;
149import org .hibernate .query .internal .QueryParameterNamedImpl ;
1510import org .hibernate .query .internal .QueryParameterPositionalImpl ;
2015import org .hibernate .query .sqm .tree .expression .SqmParameter ;
2116import org .hibernate .type .BasicCollectionType ;
2217
18+ import java .util .ArrayList ;
19+ import java .util .IdentityHashMap ;
20+ import java .util .LinkedHashMap ;
21+ import java .util .List ;
22+ import java .util .Map ;
23+ import java .util .Set ;
24+
2325import static java .util .Collections .emptyList ;
2426
2527/**
2931 */
3032public class DomainParameterXref {
3133
32- public static final DomainParameterXref EMPTY = new DomainParameterXref (
33- new LinkedHashMap <>( 0 ),
34- new IdentityHashMap <>( 0 ),
35- SqmStatement .ParameterResolutions .empty ()
36- );
34+ public static final DomainParameterXref EMPTY = new DomainParameterXref ();
3735
3836 /**
3937 * Create a DomainParameterXref for the parameters defined in the SQM statement
4038 */
4139 public static DomainParameterXref from (SqmStatement <?> sqmStatement ) {
42- final SqmStatement .ParameterResolutions parameterResolutions = sqmStatement .resolveParameters ();
43- if ( parameterResolutions .getSqmParameters ().isEmpty () ) {
44- return EMPTY ;
45- }
46- else {
47- final int sqmParamCount = parameterResolutions .getSqmParameters ().size ();
48- final LinkedHashMap <QueryParameterImplementor <?>, List <SqmParameter <?>>> sqmParamsByQueryParam =
49- new LinkedHashMap <>( sqmParamCount );
50- final IdentityHashMap <SqmParameter <?>, QueryParameterImplementor <?>> queryParamBySqmParam =
51- new IdentityHashMap <>( sqmParamCount );
52-
53- for ( SqmParameter <?> sqmParameter : parameterResolutions .getSqmParameters () ) {
54- if ( sqmParameter instanceof JpaCriteriaParameter ) {
55- // see discussion on `SqmJpaCriteriaParameterWrapper#accept`
56- throw new UnsupportedOperationException (
57- "Unexpected JpaCriteriaParameter in SqmStatement#getSqmParameters. Criteria parameters " +
58- "should be represented as SqmJpaCriteriaParameterWrapper references in this collection"
59- );
60- }
61-
62- final QueryParameterImplementor <?> queryParameter ;
63- if ( sqmParameter .getName () != null ) {
64- queryParameter = QueryParameterNamedImpl .fromSqm ( sqmParameter );
65- }
66- else if ( sqmParameter .getPosition () != null ) {
67- queryParameter = QueryParameterPositionalImpl .fromSqm ( sqmParameter );
68- }
69- else if ( sqmParameter instanceof SqmJpaCriteriaParameterWrapper <?> criteriaParameter ) {
70- if ( sqmParameter .allowMultiValuedBinding ()
71- && sqmParameter .getExpressible () != null
72- && sqmParameter .getExpressible ().getSqmType () instanceof BasicCollectionType ) {
73- // The wrapper parameter was inferred to be of a basic collection type,
74- // so we disallow multivalued bindings, because binding a list of collections isn't useful
75- criteriaParameter .getJpaCriteriaParameter ().disallowMultiValuedBinding ();
76- }
77- queryParameter = QueryParameterIdentifiedImpl .fromSqm ( criteriaParameter );
78- }
79- else {
80- throw new UnsupportedOperationException (
81- "Unexpected SqmParameter type : " + sqmParameter );
82- }
83-
84- sqmParamsByQueryParam .computeIfAbsent ( queryParameter , impl -> new ArrayList <>() ).add ( sqmParameter );
85- queryParamBySqmParam .put ( sqmParameter , queryParameter );
86- }
87-
88- return new DomainParameterXref ( sqmParamsByQueryParam , queryParamBySqmParam , parameterResolutions );
89- }
40+ final var parameterResolutions = sqmStatement .resolveParameters ();
41+ final var parameters = parameterResolutions .getSqmParameters ();
42+ return parameters .isEmpty ()
43+ ? EMPTY
44+ : new DomainParameterXref ( parameterResolutions , parameters );
9045 }
9146
92-
9347 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9448 // Instance state
9549
@@ -100,28 +54,78 @@ else if ( sqmParameter instanceof SqmJpaCriteriaParameterWrapper<?> criteriaPara
10054
10155 private Map <SqmParameter <?>,List <SqmParameter <?>>> expansions ;
10256
103- private DomainParameterXref (
104- LinkedHashMap <QueryParameterImplementor <?>, List <SqmParameter <?>>> sqmParamsByQueryParam ,
105- IdentityHashMap <SqmParameter <?>, QueryParameterImplementor <?>> queryParamBySqmParam ,
106- SqmStatement .ParameterResolutions parameterResolutions ) {
107- this .sqmParamsByQueryParam = sqmParamsByQueryParam ;
108- this .queryParamBySqmParam = queryParamBySqmParam ;
109- this .parameterResolutions = parameterResolutions ;
57+ private DomainParameterXref () {
58+ sqmParamsByQueryParam = new LinkedHashMap <>( 0 );
59+ queryParamBySqmParam = new IdentityHashMap <>( 0 );
60+ parameterResolutions = SqmStatement .ParameterResolutions .empty ();
11061 }
11162
112- public DomainParameterXref copy () {
63+ private DomainParameterXref (DomainParameterXref that ) {
64+ sqmParamsByQueryParam = that .sqmParamsByQueryParam ;
11365 //noinspection unchecked
114- final var clone =
66+ queryParamBySqmParam =
11567 (IdentityHashMap <SqmParameter <?>, QueryParameterImplementor <?>>)
116- queryParamBySqmParam .clone ();
117- return new DomainParameterXref ( sqmParamsByQueryParam , clone , parameterResolutions );
68+ that .queryParamBySqmParam .clone ();
69+ parameterResolutions = that .parameterResolutions ;
70+ }
71+
72+ private DomainParameterXref (
73+ SqmStatement .ParameterResolutions resolutions ,
74+ Set <SqmParameter <?>> parameters ) {
75+ parameterResolutions = resolutions ;
76+ final int sqmParamCount = parameters .size ();
77+ sqmParamsByQueryParam = new LinkedHashMap <>( sqmParamCount );
78+ queryParamBySqmParam = new IdentityHashMap <>( sqmParamCount );
79+
80+ for ( var parameter : parameters ) {
81+ if ( parameter instanceof JpaCriteriaParameter ) {
82+ // see discussion on `SqmJpaCriteriaParameterWrapper#accept`
83+ throw new UnsupportedOperationException (
84+ "Unexpected JpaCriteriaParameter (criteria parameters should be represented as SqmJpaCriteriaParameterWrapper references in this collection)"
85+ );
86+ }
87+
88+ final var queryParameter = fromSqm ( parameter );
89+ sqmParamsByQueryParam .computeIfAbsent ( queryParameter , impl -> new ArrayList <>() )
90+ .add ( parameter );
91+ queryParamBySqmParam .put ( parameter , queryParameter );
92+ }
93+ }
94+
95+ private static @ NonNull QueryParameterImplementor <?> fromSqm (SqmParameter <?> sqmParameter ) {
96+ if ( sqmParameter .getName () != null ) {
97+ return QueryParameterNamedImpl .fromSqm ( sqmParameter );
98+ }
99+ else if ( sqmParameter .getPosition () != null ) {
100+ return QueryParameterPositionalImpl .fromSqm ( sqmParameter );
101+ }
102+ else if ( sqmParameter instanceof SqmJpaCriteriaParameterWrapper <?> criteriaParameter ) {
103+ if ( sqmParameter .allowMultiValuedBinding () ) {
104+ final var expressible = sqmParameter .getExpressible ();
105+ if ( expressible != null && expressible .getSqmType () instanceof BasicCollectionType ) {
106+ // The wrapper parameter was inferred to be of a basic
107+ // collection type, so we disallow multivalued bindings,
108+ // because binding a list of collections isn't useful
109+ criteriaParameter .getJpaCriteriaParameter ().disallowMultiValuedBinding ();
110+ }
111+ }
112+ return QueryParameterIdentifiedImpl .fromSqm ( criteriaParameter );
113+ }
114+ else {
115+ throw new UnsupportedOperationException ( "Unexpected SqmParameter type: " + sqmParameter );
116+ }
117+ }
118+
119+ public DomainParameterXref copy () {
120+ return new DomainParameterXref ( this );
118121 }
119122
120123 /**
121124 * Does this xref contain any parameters?
122125 */
123126 public boolean hasParameters () {
124- return sqmParamsByQueryParam != null && ! sqmParamsByQueryParam .isEmpty ();
127+ return sqmParamsByQueryParam != null
128+ && ! sqmParamsByQueryParam .isEmpty ();
125129 }
126130
127131 /**
@@ -141,13 +145,6 @@ public int getSqmParameterCount() {
141145 return queryParamBySqmParam .size ();
142146 }
143147
144- // public int getNumberOfSqmParameters(QueryParameterImplementor<?> queryParameter) {
145- // final List<SqmParameter<?>> sqmParameters = sqmParamsByQueryParam.get( queryParameter );
146- // return sqmParameters == null
147- // ? 0 // this should maybe be an exception instead
148- // : sqmParameters.size();
149- // }
150-
151148 public SqmStatement .ParameterResolutions getParameterResolutions () {
152149 return parameterResolutions ;
153150 }
@@ -157,12 +154,9 @@ public List<SqmParameter<?>> getSqmParameters(QueryParameterImplementor<?> query
157154 }
158155
159156 public QueryParameterImplementor <?> getQueryParameter (SqmParameter <?> sqmParameter ) {
160- if ( sqmParameter instanceof QueryParameterImplementor <?> parameterImplementor ) {
161- return parameterImplementor ;
162- }
163- else {
164- return queryParamBySqmParam .get ( sqmParameter );
165- }
157+ return sqmParameter instanceof QueryParameterImplementor <?> parameterImplementor
158+ ? parameterImplementor
159+ : queryParamBySqmParam .get ( sqmParameter );
166160 }
167161
168162 public void addExpansion (
@@ -182,15 +176,15 @@ public List<SqmParameter<?>> getExpansions(SqmParameter<?> sqmParameter) {
182176 return emptyList ();
183177 }
184178 else {
185- final List < SqmParameter <?>> sqmParameters = expansions .get ( sqmParameter );
179+ final var sqmParameters = expansions .get ( sqmParameter );
186180 return sqmParameters == null ? emptyList () : sqmParameters ;
187181 }
188182 }
189183
190184 public void clearExpansions () {
191185 if ( expansions != null ) {
192- for ( List < SqmParameter <?>> expansionList : expansions .values () ) {
193- for ( SqmParameter <?> expansion : expansionList ) {
186+ for ( var expansionList : expansions .values () ) {
187+ for ( var expansion : expansionList ) {
194188 queryParamBySqmParam .remove ( expansion );
195189 }
196190 }
0 commit comments