1515 */
1616package org .springframework .data .repository .aot .generate ;
1717
18+ import java .util .function .Consumer ;
19+ import java .util .function .Function ;
20+
21+ import org .jspecify .annotations .Nullable ;
22+
23+ import org .springframework .beans .factory .config .BeanReference ;
1824import org .springframework .core .ResolvableType ;
1925import org .springframework .javapoet .CodeBlock ;
26+ import org .springframework .util .Assert ;
2027
2128/**
2229 * Builder for AOT Repository Constructors.
@@ -65,7 +72,31 @@ default void addParameter(String parameterName, Class<?> type, boolean bindToFie
6572 * @param type parameter type.
6673 * @param bindToField whether to create a field for the parameter and assign its value to the field.
6774 */
68- void addParameter (String parameterName , ResolvableType type , boolean bindToField );
75+ default void addParameter (String parameterName , ResolvableType type , boolean bindToField ) {
76+ addParameter (parameterName , type , c -> c .bindToField (bindToField ));
77+ }
78+
79+ /**
80+ * Add constructor parameter.
81+ *
82+ * @param parameterName name of the parameter.
83+ * @param type parameter type.
84+ * @param parameterCustomizer customizer for the parameter.
85+ */
86+ default void addParameter (String parameterName , Class <?> type ,
87+ Consumer <ConstructorParameterCustomizer > parameterCustomizer ) {
88+ addParameter (parameterName , ResolvableType .forClass (type ), parameterCustomizer );
89+ }
90+
91+ /**
92+ * Add constructor parameter.
93+ *
94+ * @param parameterName name of the parameter.
95+ * @param type parameter type.
96+ * @param parameterCustomizer customizer for the parameter.
97+ */
98+ void addParameter (String parameterName , ResolvableType type ,
99+ Consumer <ConstructorParameterCustomizer > parameterCustomizer );
69100
70101 /**
71102 * Add constructor body customizer. The customizer is invoked after adding constructor arguments and before assigning
@@ -89,4 +120,147 @@ interface ConstructorCustomizer {
89120
90121 }
91122
123+ /**
124+ * Customizer for a AOT repository constructor parameter.
125+ */
126+ interface ConstructorParameterCustomizer {
127+
128+ /**
129+ * Bind the constructor parameter to a field of the same type using the original parameter name.
130+ *
131+ * @return {@code this} for method chaining.
132+ */
133+ default ConstructorParameterCustomizer bindToField () {
134+ return bindToField (true );
135+ }
136+
137+ /**
138+ * Bind the constructor parameter to a field of the same type using the original parameter name.
139+ *
140+ * @return {@code this} for method chaining.
141+ */
142+ ConstructorParameterCustomizer bindToField (boolean bindToField );
143+
144+ /**
145+ * Use the given {@link BeanReference} to define the constructor parameter origin. Bean references can be by name,
146+ * by type or by type and name. Using a bean reference renders a lookup to a local variable using the parameter name
147+ * as guidance for the local variable name
148+ *
149+ * @see FragmentParameterContext#localVariable(String)
150+ */
151+ void origin (BeanReference reference );
152+
153+ /**
154+ * Use the given {@link BeanReference} to define the constructor parameter origin. Bean references can be by name,
155+ * by type or by type and name.
156+ */
157+ void origin (Function <FragmentParameterContext , ParameterOrigin > originFunction );
158+
159+ }
160+
161+ /**
162+ * Context to obtain a constructor parameter value when declaring the constructor parameter origin.
163+ */
164+ interface FragmentParameterContext {
165+
166+ /**
167+ * @return variable name of the {@link org.springframework.beans.factory.BeanFactory}.
168+ */
169+ String beanFactory ();
170+
171+ /**
172+ * @return parameter origin to obtain the {@link org.springframework.beans.factory.BeanFactory}.
173+ */
174+ default ParameterOrigin getBeanFactory () {
175+ return ParameterOrigin .ofReference (beanFactory ());
176+ }
177+
178+ /**
179+ * @return variable name of the
180+ * {@link org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.FragmentCreationContext}.
181+ */
182+ String fragmentCreationContext ();
183+
184+ /**
185+ * @return parameter origin to obtain the fragment creation context.
186+ */
187+ default ParameterOrigin getFragmentCreationContext () {
188+ return ParameterOrigin .ofReference (fragmentCreationContext ());
189+ }
190+
191+ /**
192+ * Obtain a naming-clash free variant for the given logical variable name within the local method context. Returns
193+ * the target variable name when called multiple times with the same {@code variableName}.
194+ *
195+ * @param variableName the logical variable name.
196+ * @return the variable name used in the generated code.
197+ */
198+ String localVariable (String variableName );
199+
200+ }
201+
202+ /**
203+ * Interface describing the origin of a constructor parameter. The parameter value can be obtained either from a
204+ * {@link #getReference() reference} variable, a {@link #getCodeBlock() code block} or a combination of both.
205+ *
206+ * @author Mark Paluch
207+ * @since 4.0
208+ */
209+ interface ParameterOrigin {
210+
211+ /**
212+ * Construct a {@link ParameterOrigin} from the given {@link CodeBlock} and reference name.
213+ *
214+ * @param reference the reference name to obtain the parameter value from.
215+ * @param codeBlock the code block that is required to set up the parameter value.
216+ * @return a {@link ParameterOrigin} from the given {@link CodeBlock} and reference name.
217+ */
218+ static ParameterOrigin of (String reference , CodeBlock codeBlock ) {
219+
220+ Assert .hasText (reference , "Parameter reference must not be empty" );
221+
222+ return new DefaultParameterOrigin (reference , codeBlock );
223+ }
224+
225+ /**
226+ * Construct a {@link ParameterOrigin} from the given {@link CodeBlock}.
227+ *
228+ * @param codeBlock the code block that produces the parameter value.
229+ * @return a {@link ParameterOrigin} from the given {@link CodeBlock}.
230+ */
231+ static ParameterOrigin of (CodeBlock codeBlock ) {
232+
233+ Assert .notNull (codeBlock , "CodeBlock reference must not be empty" );
234+
235+ return new DefaultParameterOrigin (null , codeBlock );
236+ }
237+
238+ /**
239+ * Construct a {@link ParameterOrigin} from the given reference name.
240+ *
241+ * @param reference the reference name of the variable to obtain the parameter value from.
242+ * @return a {@link ParameterOrigin} from the given reference name.
243+ */
244+ static ParameterOrigin ofReference (String reference ) {
245+
246+ Assert .hasText (reference , "Parameter reference must not be empty" );
247+
248+ return of (reference , CodeBlock .builder ().build ());
249+ }
250+
251+ /**
252+ * Obtain the reference name to obtain the parameter value from. Can be {@code null} if the parameter value is
253+ * solely obtained from the {@link #getCodeBlock() code block}.
254+ *
255+ * @return name of the reference or {@literal null} if absent.
256+ */
257+ @ Nullable
258+ String getReference ();
259+
260+ /**
261+ * Obtain the code block to obtain the parameter value from. Never {@literal null}, can be empty.
262+ */
263+ CodeBlock getCodeBlock ();
264+
265+ }
92266}
0 commit comments