001package io.dinject;
002
003import java.util.List;
004
005/**
006 * Provides a global system wide BeanContext that contains all the bean contexts in the classpath.
007 * <p>
008 * This will automatically get all the bean contexts and wire them all as necessary. It will use
009 * a shutdown hook to fire any <code>@PreDestroy</code> methods on beans.
010 * </p>
011 *
012 * <h3>Example: get a bean</h3>
013 * <pre>{@code
014 *
015 *   CoffeeMaker coffeeMaker = SystemContext.getBean(CoffeeMaker.class);
016 *   coffeeMaker.brew();
017 *
018 * }</pre>
019 *
020 * <h3>Example: get all the beans implementing an interface</h3>
021 * <pre>{@code
022 *
023 *   // e.g. register all WebRoutes for a web framework
024 *
025 *   List<WebRoute> routes = SystemContext.getBeans(WebRoute.class);
026 *
027 *   // register all the routes ...
028 *
029 * }</pre>
030 *
031 * <h3>Example: get all the beans that have an annotation</h3>
032 * <pre>{@code
033 *
034 *   // e.g. register all controllers with web a framework
035 *   // .. where Controller is an annotation on the beans
036 *
037 *   List<Object> controllers = SystemContext.getBeansWithAnnotation(Controller.class);
038 *
039 *   // register all the controllers ...
040 *
041 * }</pre>
042 */
043public class SystemContext {
044
045  private static final BeanContext rootContext = init();
046
047  private static BeanContext init() {
048    return new BeanContextBuilder().build();
049  }
050
051  private SystemContext() {
052    // hide
053  }
054
055  /**
056   * Return the underlying BeanContext.
057   */
058  public static BeanContext context() {
059    return rootContext;
060  }
061
062  /**
063   * Return a single bean given the type.
064   *
065   * <pre>{@code
066   *
067   *   CoffeeMaker coffeeMaker = SystemContext.getBean(CoffeeMaker.class);
068   *   coffeeMaker.brew();
069   *
070   * }</pre>
071   *
072   * @param type an interface or bean type
073   */
074  public static <T> T getBean(Class<T> type) {
075    return rootContext.getBean(type);
076  }
077
078  /**
079   * Return a single bean given the type and name.
080   *
081   * <pre>{@code
082   *
083   *   Heater heater = SystemContext.getBean(Heater.class, "electric");
084   *   heater.heat();
085   *
086   * }</pre>
087   *
088   * @param type an interface or bean type
089   * @param name the name qualifier of a specific bean
090   */
091  public static <T> T getBean(Class<T> type, String name) {
092    return rootContext.getBean(type, name);
093  }
094
095  /**
096   * Return the list of beans that have an annotation.
097   *
098   * <pre>{@code
099   *
100   *   // e.g. register all controllers with web a framework
101   *   // .. where Controller is an annotation on the beans
102   *
103   *   List<Object> controllers = SystemContext.getBeansWithAnnotation(Controller.class);
104   *
105   * }</pre>
106   *
107   * @param annotation An annotation class.
108   */
109  public static List<Object> getBeansWithAnnotation(Class<?> annotation) {
110    return rootContext.getBeansWithAnnotation(annotation);
111  }
112
113  /**
114   * Return the list of beans that implement the interface.
115   *
116   * <pre>{@code
117   *
118   *   // e.g. register all web routes with web a framework
119   *
120   *   List<WebRoute> routes = SystemContext.getBeans(WebRoute.class);
121   *
122   * }</pre>
123   *
124   * @param interfaceType An interface class.
125   */
126  public static <T> List<T> getBeans(Class<T> interfaceType) {
127    return rootContext.getBeans(interfaceType);
128  }
129
130  /**
131   * Return the list of beans that implement the interface ordering based on <code>@Priority</code>.
132   *
133   * <pre>{@code
134   *
135   *   // e.g. register all web routes with web a framework
136   *
137   *   List<WebRoute> routes = SystemContext.getBeansByPriority(WebRoute.class);
138   *
139   * }</pre>
140   *
141   * @param interfaceType An interface class.
142   */
143  public static <T> List<T> getBeansByPriority(Class<T> interfaceType) {
144    return rootContext.getBeansByPriority(interfaceType);
145  }
146
147}