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 }