001package io.avaje.inject.spi;
002
003import java.lang.reflect.Type;
004import java.util.List;
005import java.util.Map;
006import java.util.Optional;
007import java.util.Set;
008import java.util.function.Consumer;
009import java.util.function.Function;
010
011import io.avaje.inject.BeanScope;
012import jakarta.inject.Provider;
013
014/**
015 * Mutable builder object used when building a bean scope.
016 */
017public interface Builder {
018
019  /**
020   * Create the root level Builder.
021   *
022   * @param profiles       Explicit profiles used
023   * @param suppliedBeans  The list of beans (typically test doubles) supplied when building the context.
024   * @param enrichBeans    The list of classes we want to have with mockito spy enhancement
025   * @param parent         The parent BeanScope
026   * @param parentOverride When false do not add beans that already exist on the parent
027   */
028  @SuppressWarnings("rawtypes")
029  static Builder newBuilder(Set<String> profiles, ConfigPropertyPlugin plugin, List<SuppliedBean> suppliedBeans, List<EnrichBean> enrichBeans, BeanScope parent, boolean parentOverride) {
030    if (suppliedBeans.isEmpty() && enrichBeans.isEmpty()) {
031      // simple case, no mocks or spies
032      return new DBuilder(profiles, plugin, parent, parentOverride);
033    }
034    return new DBuilderExtn(profiles, plugin, parent, parentOverride, suppliedBeans, enrichBeans);
035  }
036
037  /**
038   * Return true if the bean should be created and registered with the context.
039   * <p>
040   * Returning false means there has been a supplied bean already registered and
041   * that we should skip the creation and registration for this bean.
042   *
043   * @param name  The qualifier name
044   * @param types The types that the bean implements and provides
045   */
046  boolean isBeanAbsent(String name, Type... types);
047
048  /**
049   * Return true if the bean should be created and registered with the context.
050   * <p>
051   * Returning false means there has been a supplied bean already registered and
052   * that we should skip the creation and registration for this bean.
053   *
054   * @param types The types that the bean implements and provides
055   */
056  default boolean isBeanAbsent(Type... types) {
057    return isBeanAbsent(null, types);
058  }
059
060  /**
061   * Register the next bean as having Primary priority.
062   * Highest priority, wired over any other matching beans.
063   */
064  Builder asPrimary();
065
066  /**
067   * Register the next bean as having Secondary priority.
068   * Lowest priority, wired when no other matching beans are available.
069   */
070  Builder asSecondary();
071
072  /**
073   * Register the next bean as having the given priority. Wired only if no other higher priority
074   * matching beans are available.
075   */
076  Builder asPriority(int priority);
077
078  /**
079   * Register the next bean as having Prototype scope.
080   */
081  Builder asPrototype();
082
083  /**
084   * Register the provider into the context.
085   */
086  <T> void registerProvider(Provider<T> provider);
087
088  /**
089   * Register the lazy provider into the context.
090   */
091  default <T> void registerLazy(Provider<T> provider, Function<Provider<T>, T> proxyClassConstructor) {
092    register(proxyClassConstructor.apply(new OnceProvider<>(provider)));
093  }
094
095  /**
096   * Register the bean instance into the context.
097   *
098   * @param bean The bean instance that has been created.
099   */
100  <T> T register(T bean);
101
102  /**
103   * Register the externally provided bean.
104   *
105   * @param type The type of the provided bean.
106   * @param bean The bean instance
107   */
108  <T> void withBean(Class<T> type, T bean);
109
110  /**
111   * Add lifecycle PostConstruct method.
112   */
113  void addPostConstruct(Runnable runnable);
114
115  /**
116   * Add lifecycle PostConstruct method.
117   */
118  void addPostConstruct(Consumer<BeanScope> consumer);
119
120  /**
121   * Add lifecycle PreDestroy method.
122   */
123  void addPreDestroy(AutoCloseable closeable);
124
125  /**
126   * Add lifecycle PreDestroy method with a given priority.
127   */
128  void addPreDestroy(AutoCloseable closeable, int priority);
129
130  /**
131   * Check if the instance is AutoCloseable and if so register it with PreDestroy.
132   *
133   * @param maybeAutoCloseable An instance that might be AutoCloseable
134   */
135  void addAutoClosable(Object maybeAutoCloseable);
136
137  /**
138   * Add field and method injection.
139   */
140  void addInjector(Consumer<Builder> injector);
141
142  /**
143   * Get a dependency.
144   */
145  <T> T get(Class<T> cls);
146
147  /**
148   * Get a named dependency.
149   */
150  <T> T get(Class<T> cls, String name);
151
152  /**
153   * Get a dependency for the generic type.
154   */
155  <T> T get(Type cls);
156
157  /**
158   * Get a named dependency for the generic type.
159   */
160  <T> T get(Type cls, String name);
161
162  /**
163   * Get an optional dependency.
164   */
165  <T> Optional<T> getOptional(Class<T> cls);
166
167  /**
168   * Get an optional named dependency.
169   */
170  <T> Optional<T> getOptional(Class<T> cls, String name);
171
172  /**
173   * Get an optional dependency for the generic type.
174   */
175  <T> Optional<T> getOptional(Type cls);
176
177  /**
178   * Get an optional named dependency for the generic type.
179   */
180  <T> Optional<T> getOptional(Type cls, String name);
181
182  /**
183   * Get an optional dependency potentially returning null.
184   */
185  <T> T getNullable(Class<T> cls);
186
187  /**
188   * Get an optional named dependency potentially returning null.
189   */
190  <T> T getNullable(Class<T> cls, String name);
191
192  /**
193   * Get an optional dependency potentially returning null for the generic type.
194   */
195  <T> T getNullable(Type cls);
196
197  /**
198   * Get an optional named dependency potentially returning null for the generic type.
199   */
200  <T> T getNullable(Type cls, String name);
201
202  /**
203   * Return Provider of T given the type.
204   */
205  <T> Provider<T> getProvider(Class<T> cls);
206
207  /**
208   * Return Provider of T given the type and name.
209   */
210  <T> Provider<T> getProvider(Class<T> cls, String name);
211
212  /**
213   * Return Provider of T given the generic type.
214   */
215  <T> Provider<T> getProvider(Type cls);
216
217  /**
218   * Return Provider of T given the generic type and name.
219   */
220  <T> Provider<T> getProvider(Type cls, String name);
221
222  /**
223   * Return Provider for a generic interface type.
224   *
225   * @param cls  The usual implementation class
226   * @param type The generic interface type
227   */
228  <T> Provider<T> getProviderFor(Class<?> cls, Type type);
229
230  /**
231   * Get a list of dependencies for the type.
232   */
233  <T> List<T> list(Class<T> type);
234
235  /**
236   * Get a list of dependencies for the generic type.
237   */
238  <T> List<T> list(Type type);
239
240  /**
241   * Get a list of dependencies for the type and name.
242   */
243  <T> List<T> list(Type type, String name);
244
245  /**
246   * Get a set of dependencies for the type.
247   */
248  <T> Set<T> set(Class<T> type);
249
250  /**
251   * Get a set of dependencies for the generic type.
252   */
253  <T> Set<T> set(Type type);
254
255  /**
256   * Get a set of dependencies for the type and name.
257   */
258  <T> Set<T> set(Type type, String name);
259
260  /**
261   * Return a map of dependencies for the type keyed by qualifier name.
262   */
263  <T> Map<String, T> map(Class<T> type);
264
265  /**
266   * Return a map of dependencies for the generic type keyed by qualifier name.
267   */
268  <T> Map<String, T> map(Type type);
269
270  /**
271   * Return true if the builder contains the given type.
272   */
273  boolean contains(Type type);
274
275  /**
276   * Return true if the builder contains the given type.
277   */
278  boolean contains(String type);
279
280  /**
281   * Return true if the builder contains a bean with the given name.
282   */
283  boolean containsQualifier(String name);
284
285  /**
286   * Return true if the builder contains the given profile
287   */
288  boolean containsProfiles(List<String> type);
289
290  /**
291   * Return true if the builder contains all of the given profile
292   */
293  boolean containsAllProfiles(List<String> type);
294
295  /**
296   * Return the plugin for required properties.
297   */
298  ConfigPropertyPlugin property();
299
300  /**
301   * Build and return the bean scope.
302   */
303  BeanScope build(boolean withShutdownHook, long start);
304
305  /**
306   * Set the current module being wired.
307   */
308  void currentModule(Class<? extends AvajeModule> currentModule);
309
310  /**
311   * Set the custom scopes defined by the module being wired.
312   */
313  void currentScopes(String[] scopes);
314}