001package io.avaje.inject.spi;
002
003import io.avaje.inject.BeanContext;
004import io.avaje.inject.BeanEntry;
005
006import java.util.List;
007import java.util.Optional;
008import java.util.Set;
009import java.util.function.Consumer;
010
011/**
012 * Mutable builder object used when building a bean context.
013 */
014public interface Builder {
015
016  /**
017   * Create the root level Builder.
018   *
019   * @param suppliedBeans The list of beans (typically test doubles) supplied when building the context.
020   * @param enrichBeans   The list of classes we want to have with mockito spy enhancement
021   */
022  @SuppressWarnings("rawtypes")
023  static Builder newRootBuilder(List<SuppliedBean> suppliedBeans, List<EnrichBean> enrichBeans) {
024    if (suppliedBeans.isEmpty() && enrichBeans.isEmpty()) {
025      // simple case, no mocks or spies
026      return new DBuilder();
027    }
028    return new DBuilderExtn(suppliedBeans, enrichBeans);
029  }
030
031  /**
032   * Create a Builder for the named context (module).
033   *
034   * @param name      the name of the module / bean context
035   * @param provides  the module features this module provides
036   * @param dependsOn the names of modules this module is depends on.
037   */
038  static Builder newBuilder(String name, String[] provides, String[] dependsOn) {
039    return new DBuilder(name, provides, dependsOn);
040  }
041
042  /**
043   * Return the name of the (module) context this builder is creating.
044   */
045  String getName();
046
047  /**
048   * Return the names of module features that this module provides.
049   */
050  String[] getProvides();
051
052  /**
053   * Return the names of modules that this module depends on.
054   */
055  String[] getDependsOn();
056
057  /**
058   * Set a parent builder that can provide cross-module dependencies.
059   */
060  void setParent(Builder parent);
061
062  /**
063   * Return true if the bean should be created and registered with the context.
064   * <p/>
065   * Returning false means there has been a (test double) bean already registered and
066   * that we should skip the creation and registration for this bean.
067   *
068   * @param addForType   The interface that the bean implements and provides
069   * @param injectTarget The actual bean type we are looking to create and register
070   */
071  boolean isAddBeanFor(Class<?> addForType, Class<?> injectTarget);
072
073  /**
074   * Return true if the bean should be created and registered with the context.
075   * <p/>
076   * Returning false means there has been a (test double) bean already registered and
077   * that we should skip the creation and registration for this bean.
078   *
079   * @param injectTarget The actual bean type we are looking to create and register
080   */
081  boolean isAddBeanFor(Class<?> injectTarget);
082
083  /**
084   * Register the bean instance into the context.
085   * <p>
086   * Beans are added in an appropriate order to satisfy dependencies.
087   * </p>
088   *
089   * @param bean  The bean instance that has been created.
090   * @param name  The (optional) name of the instance.
091   * @param types Interfaces and class level annotations this bean provides or associates to.
092   */
093  <T> T register(T bean, String name, Class<?>... types);
094
095  /**
096   * Register the bean as a Primary bean.
097   */
098  <T> T registerPrimary(T bean, String name, Class<?>... types);
099
100  /**
101   * Register the bean as a secondary bean.
102   */
103  <T> T registerSecondary(T bean, String name, Class<?>... types);
104
105  /**
106   * Add a lifecycle bean.
107   */
108  void addLifecycle(BeanLifecycle bean);
109
110  /**
111   * Add field and method injection.
112   */
113  void addInjector(Consumer<Builder> injector);
114
115  /**
116   * Add a child context.
117   */
118  void addChild(BeanContextFactory factory);
119
120  /**
121   * Get an optional dependency.
122   */
123  <T> Optional<T> getOptional(Class<T> cls);
124
125  /**
126   * Get an optional named dependency.
127   */
128  <T> Optional<T> getOptional(Class<T> cls, String name);
129
130  /**
131   * Get a dependency.
132   */
133  <T> T get(Class<T> cls);
134
135  /**
136   * Get a named dependency.
137   */
138  <T> T get(Class<T> cls, String name);
139
140  /**
141   * Get a list of dependencies for the interface type .
142   */
143  <T> List<T> getList(Class<T> interfaceType);
144
145  /**
146   * Get a set of dependencies for the interface type .
147   */
148  <T> Set<T> getSet(Class<T> interfaceType);
149
150  /**
151   * Get a candidate dependency allowing it to be null.
152   */
153  <T> BeanEntry<T> candidate(Class<T> cls, String name);
154
155  /**
156   * Return a potentially enriched bean for registration into the context.
157   * Typically for use with mockito spy.
158   *
159   * @param bean  The bean with dependencies injected
160   * @param types The types this bean registers for
161   * @return Either the bean or the enriched bean to register into the context.
162   */
163  <T> T enrich(T bean, Class<?>[] types);
164
165  /**
166   * Build and return the bean context.
167   */
168  BeanContext build();
169}