View Javadoc
1   package com.atlassian.sal.api.component;
2   
3   import java.util.Collection;
4   import java.util.Optional;
5   
6   /**
7    * Unified interface to access components via their interface.  Calling {@link #getComponent(Class)} will work the
8    * same in any application, regardless of underlying dependency injection system used.
9    *
10   * @since 2.0
11   */
12  public abstract class ComponentLocator {
13      private static ComponentLocator componentLocator;
14  
15      /**
16       * Sets the component locator to use.  Should only be called once.
17       *
18       * @param loc The implementation to use
19       */
20      public static void setComponentLocator(ComponentLocator loc) {
21          ComponentLocator.componentLocator = loc;
22      }
23  
24      /**
25       * @return True if intialized with a locator subclass
26       */
27      public static boolean isInitialized() {
28          return ComponentLocator.componentLocator != null;
29      }
30  
31      /**
32       * Gets a component by its interface.  Applications that don't support interface-based components will need to
33       * convert the interface name into a String
34       *
35       * @param iface The interface to find an implementation for
36       * @return The implementation
37       */
38      public static <T> T getComponent(Class<T> iface) {
39          return componentLocator.getComponentInternal(iface);
40      }
41  
42      /**
43       * Get a component by it's interface safely. If there is any issue with fetching the interface then this
44       * method will return Optional.empty().
45       *
46       * @param iface The interface to find an implementation for
47       * @return The implementation
48       */
49      public static <T> Optional<T> getComponentSafely(Class<T> iface) {
50          if (componentLocator == null) {
51              return Optional.empty();
52          }
53          try {
54              return Optional.ofNullable(componentLocator.getComponentInternal(iface));
55          } catch (RuntimeException ignore) {
56              // Don't care what goes wrong, this method just returns and empty vessel.
57              return Optional.empty();
58          }
59      }
60  
61      /**
62       * Gets a component by its interface and its Id.
63       *
64       * @param iface        The interface to find an implementation for
65       * @param componentKey id of the component
66       * @return The implementation
67       */
68      public static <T> T getComponent(Class<T> iface, String componentKey) {
69          return componentLocator.getComponentInternal(iface, componentKey);
70      }
71  
72      /**
73       * Gets the requested component, to be overridden for each application
74       *
75       * @param iface The interface to lookup
76       * @return The implementation
77       */
78      protected abstract <T> T getComponentInternal(Class<T> iface);
79  
80      /**
81       * Gets the requested component, to be overridden for each application
82       *
83       * @param iface        The interface to lookup
84       * @param componentKey key of the component
85       * @return The implementation
86       */
87      protected abstract <T> T getComponentInternal(Class<T> iface, String componentKey);
88  
89      /**
90       * Gets a components by interface.  Applications that don't support interface-based components will need to
91       * covert the interface name into a String
92       *
93       * @param iface The interface to find an implementation for
94       * @return The implementation
95       */
96      public static <T> Collection<T> getComponents(Class<T> iface) {
97          return componentLocator.getComponentsInternal(iface);
98      }
99  
100     protected abstract <T> Collection<T> getComponentsInternal(Class<T> iface);
101 
102     /**
103      * Converts the interface name into a String key
104      *
105      * @param iface The interface to convert
106      * @return The String key to use to find the implementation
107      */
108     protected String convertClassToName(Class iface) {
109         return Character.toLowerCase(iface.getSimpleName().charAt(0)) + iface.getSimpleName()
110                 .substring(1);
111     }
112 
113 }