Skip to content

Commit 190c906

Browse files
committed
Add qualifier support to firebase components.
Details: go/firebase-component-qualifiers
1 parent 42542ba commit 190c906

File tree

14 files changed

+488
-106
lines changed

14 files changed

+488
-106
lines changed

firebase-common/firebase-common.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ android {
6262
}
6363

6464
dependencies {
65-
// TODO(vkryachko): have sdks depend on components directly once components are released.
65+
implementation project(':firebase-annotations')
6666
implementation project(':firebase-components')
6767
implementation 'com.google.android.gms:play-services-basement:17.0.0'
6868
implementation "com.google.android.gms:play-services-tasks:17.0.0"

firebase-components/src/main/java/com/google/firebase/components/AbstractComponentContainer.java

Lines changed: 0 additions & 34 deletions
This file was deleted.

firebase-components/src/main/java/com/google/firebase/components/Component.java

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ public final class Component<T> {
7676
int SET = 1;
7777
}
7878

79-
private final Set<Class<? super T>> providedInterfaces;
79+
private final Set<Qualified<? super T>> providedInterfaces;
8080
private final Set<Dependency> dependencies;
8181
private final @Instantiation int instantiation;
8282
private final @ComponentType int type;
8383
private final ComponentFactory<T> factory;
8484
private final Set<Class<?>> publishedEvents;
8585

8686
private Component(
87-
Set<Class<? super T>> providedInterfaces,
87+
Set<Qualified<? super T>> providedInterfaces,
8888
Set<Dependency> dependencies,
8989
@Instantiation int instantiation,
9090
@ComponentType int type,
@@ -103,7 +103,7 @@ private Component(
103103
*
104104
* <p>Note: T conforms to all of these interfaces.
105105
*/
106-
public Set<Class<? super T>> getProvidedInterfaces() {
106+
public Set<Qualified<? super T>> getProvidedInterfaces() {
107107
return providedInterfaces;
108108
}
109109

@@ -180,6 +180,18 @@ public static <T> Component.Builder<T> builder(
180180
return new Builder<>(anInterface, additionalInterfaces);
181181
}
182182

183+
/** Returns a Component<T> builder. */
184+
public static <T> Component.Builder<T> builder(Qualified<T> anInterface) {
185+
return new Builder<>(anInterface);
186+
}
187+
188+
/** Returns a Component<T> builder. */
189+
@SafeVarargs
190+
public static <T> Component.Builder<T> builder(
191+
Qualified<T> anInterface, Qualified<? super T>... additionalInterfaces) {
192+
return new Builder<>(anInterface, additionalInterfaces);
193+
}
194+
183195
/**
184196
* Wraps a value in a {@link Component} with no dependencies.
185197
*
@@ -197,6 +209,13 @@ public static <T> Component<T> of(
197209
return builder(anInterface, additionalInterfaces).factory((args) -> value).build();
198210
}
199211

212+
/** Wraps a value in a {@link Component} with no dependencies. */
213+
@SafeVarargs
214+
public static <T> Component<T> of(
215+
T value, Qualified<T> anInterface, Qualified<? super T>... additionalInterfaces) {
216+
return builder(anInterface, additionalInterfaces).factory((args) -> value).build();
217+
}
218+
200219
/**
201220
* Provides a builder for a {@link Set}-multibinding {@link Component}.
202221
*
@@ -207,6 +226,16 @@ public static <T> Component.Builder<T> intoSetBuilder(Class<T> anInterface) {
207226
return builder(anInterface).intoSet();
208227
}
209228

229+
/**
230+
* Provides a builder for a {@link Set}-multibinding {@link Component}.
231+
*
232+
* <p>Such components can be requested by dependents via {@link ComponentContainer#setOf(Class)} *
233+
* or {@link ComponentContainer#setOfProvider(Class)}.
234+
*/
235+
public static <T> Component.Builder<T> intoSetBuilder(Qualified<T> anInterface) {
236+
return builder(anInterface).intoSet();
237+
}
238+
210239
/**
211240
* Wraps a value in a {@link Set}-multibinding {@link Component} with no dependencies. *
212241
*
@@ -217,21 +246,41 @@ public static <T> Component<T> intoSet(T value, Class<T> anInterface) {
217246
return intoSetBuilder(anInterface).factory(c -> value).build();
218247
}
219248

249+
/**
250+
* Wraps a value in a {@link Set}-multibinding {@link Component} with no dependencies. *
251+
*
252+
* <p>Such components can be requested by dependents via {@link ComponentContainer#setOf(Class)} *
253+
* or {@link ComponentContainer#setOfProvider(Class)}.
254+
*/
255+
public static <T> Component<T> intoSet(T value, Qualified<T> anInterface) {
256+
return intoSetBuilder(anInterface).factory(c -> value).build();
257+
}
258+
220259
/** FirebaseComponent builder. */
221260
public static class Builder<T> {
222-
private final Set<Class<? super T>> providedInterfaces = new HashSet<>();
261+
private final Set<Qualified<? super T>> providedInterfaces = new HashSet<>();
223262
private final Set<Dependency> dependencies = new HashSet<>();
224263
private @Instantiation int instantiation = Instantiation.LAZY;
225264
private @ComponentType int type = ComponentType.VALUE;
226265
private ComponentFactory<T> factory;
227-
private Set<Class<?>> publishedEvents = new HashSet<>();
266+
private final Set<Class<?>> publishedEvents = new HashSet<>();
228267

229268
@SafeVarargs
230269
private Builder(Class<T> anInterface, Class<? super T>... additionalInterfaces) {
231270
Preconditions.checkNotNull(anInterface, "Null interface");
232-
providedInterfaces.add(anInterface);
271+
providedInterfaces.add(Qualified.unqualified(anInterface));
233272
for (Class<? super T> iface : additionalInterfaces) {
234273
Preconditions.checkNotNull(iface, "Null interface");
274+
providedInterfaces.add(Qualified.unqualified(iface));
275+
}
276+
}
277+
278+
@SafeVarargs
279+
private Builder(Qualified<T> anInterface, Qualified<? super T>... additionalInterfaces) {
280+
Preconditions.checkNotNull(anInterface, "Null interface");
281+
providedInterfaces.add(anInterface);
282+
for (Qualified<? super T> iface : additionalInterfaces) {
283+
Preconditions.checkNotNull(iface, "Null interface");
235284
}
236285
Collections.addAll(providedInterfaces, additionalInterfaces);
237286
}
@@ -267,7 +316,7 @@ private Builder<T> setInstantiation(@Instantiation int instantiation) {
267316
return this;
268317
}
269318

270-
private void validateInterface(Class<?> anInterface) {
319+
private void validateInterface(Qualified<?> anInterface) {
271320
Preconditions.checkArgument(
272321
!providedInterfaces.contains(anInterface),
273322
"Components are not allowed to depend on interfaces they themselves provide.");

firebase-components/src/main/java/com/google/firebase/components/ComponentContainer.java

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,41 @@
2020

2121
/** Provides a means to retrieve instances of requested classes/interfaces. */
2222
public interface ComponentContainer {
23-
<T> T get(Class<T> anInterface);
23+
default <T> T get(Class<T> anInterface) {
24+
return get(Qualified.unqualified(anInterface));
25+
}
2426

25-
<T> Provider<T> getProvider(Class<T> anInterface);
27+
default <T> Provider<T> getProvider(Class<T> anInterface) {
28+
return getProvider(Qualified.unqualified(anInterface));
29+
}
2630

27-
<T> Deferred<T> getDeferred(Class<T> anInterface);
31+
default <T> Deferred<T> getDeferred(Class<T> anInterface) {
32+
return getDeferred(Qualified.unqualified(anInterface));
33+
}
2834

29-
<T> Set<T> setOf(Class<T> anInterface);
35+
default <T> Set<T> setOf(Class<T> anInterface) {
36+
return setOf(Qualified.unqualified(anInterface));
37+
}
3038

31-
<T> Provider<Set<T>> setOfProvider(Class<T> anInterface);
39+
default <T> Provider<Set<T>> setOfProvider(Class<T> anInterface) {
40+
return setOfProvider(Qualified.unqualified(anInterface));
41+
}
42+
43+
default <T> T get(Qualified<T> anInterface) {
44+
Provider<T> provider = getProvider(anInterface);
45+
if (provider == null) {
46+
return null;
47+
}
48+
return provider.get();
49+
}
50+
51+
<T> Provider<T> getProvider(Qualified<T> anInterface);
52+
53+
<T> Deferred<T> getDeferred(Qualified<T> anInterface);
54+
55+
default <T> Set<T> setOf(Qualified<T> anInterface) {
56+
return setOfProvider(anInterface).get();
57+
}
58+
59+
<T> Provider<Set<T>> setOfProvider(Qualified<T> anInterface);
3260
}

firebase-components/src/main/java/com/google/firebase/components/ComponentRuntime.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@
4242
* <p>Does {@link Component} dependency resolution and provides access to resolved {@link
4343
* Component}s via {@link #get(Class)} method.
4444
*/
45-
public class ComponentRuntime extends AbstractComponentContainer implements ComponentLoader {
45+
public class ComponentRuntime implements ComponentContainer, ComponentLoader {
4646
private static final Provider<Set<Object>> EMPTY_PROVIDER = Collections::emptySet;
4747
private final Map<Component<?>, Provider<?>> components = new HashMap<>();
48-
private final Map<Class<?>, Provider<?>> lazyInstanceMap = new HashMap<>();
49-
private final Map<Class<?>, LazySet<?>> lazySetMap = new HashMap<>();
48+
private final Map<Qualified<?>, Provider<?>> lazyInstanceMap = new HashMap<>();
49+
private final Map<Qualified<?>, LazySet<?>> lazySetMap = new HashMap<>();
5050
private final List<Provider<ComponentRegistrar>> unprocessedRegistrarProviders;
5151
private final EventBus eventBus;
5252
private final AtomicReference<Boolean> eagerComponentsInitializedWith = new AtomicReference<>();
@@ -176,7 +176,7 @@ private List<Runnable> processInstanceComponents(List<Component<?>> componentsTo
176176
}
177177

178178
Provider<?> provider = components.get(component);
179-
for (Class<?> anInterface : component.getProvidedInterfaces()) {
179+
for (Qualified<?> anInterface : component.getProvidedInterfaces()) {
180180
if (!lazyInstanceMap.containsKey(anInterface)) {
181181
lazyInstanceMap.put(anInterface, provider);
182182
} else {
@@ -195,7 +195,7 @@ private List<Runnable> processInstanceComponents(List<Component<?>> componentsTo
195195
/** Populates lazySetMap to make set components available for consumption via set dependencies. */
196196
private List<Runnable> processSetComponents() {
197197
ArrayList<Runnable> runnables = new ArrayList<>();
198-
Map<Class<?>, Set<Provider<?>>> setIndex = new HashMap<>();
198+
Map<Qualified<?>, Set<Provider<?>>> setIndex = new HashMap<>();
199199
for (Map.Entry<Component<?>, Provider<?>> entry : components.entrySet()) {
200200
Component<?> component = entry.getKey();
201201

@@ -206,15 +206,15 @@ private List<Runnable> processSetComponents() {
206206

207207
Provider<?> provider = entry.getValue();
208208

209-
for (Class<?> anInterface : component.getProvidedInterfaces()) {
209+
for (Qualified<?> anInterface : component.getProvidedInterfaces()) {
210210
if (!setIndex.containsKey(anInterface)) {
211211
setIndex.put(anInterface, new HashSet<>());
212212
}
213213
setIndex.get(anInterface).add(provider);
214214
}
215215
}
216216

217-
for (Map.Entry<Class<?>, Set<Provider<?>>> entry : setIndex.entrySet()) {
217+
for (Map.Entry<Qualified<?>, Set<Provider<?>>> entry : setIndex.entrySet()) {
218218
if (!lazySetMap.containsKey(entry.getKey())) {
219219
lazySetMap.put(entry.getKey(), LazySet.fromCollection(entry.getValue()));
220220
} else {
@@ -229,13 +229,13 @@ private List<Runnable> processSetComponents() {
229229

230230
@Override
231231
@SuppressWarnings("unchecked")
232-
public synchronized <T> Provider<T> getProvider(Class<T> anInterface) {
232+
public <T> Provider<T> getProvider(Qualified<T> anInterface) {
233233
Preconditions.checkNotNull(anInterface, "Null interface requested.");
234234
return (Provider<T>) lazyInstanceMap.get(anInterface);
235235
}
236236

237237
@Override
238-
public <T> Deferred<T> getDeferred(Class<T> anInterface) {
238+
public <T> Deferred<T> getDeferred(Qualified<T> anInterface) {
239239
Provider<T> provider = getProvider(anInterface);
240240
if (provider == null) {
241241
return OptionalProvider.empty();
@@ -248,7 +248,7 @@ public <T> Deferred<T> getDeferred(Class<T> anInterface) {
248248

249249
@Override
250250
@SuppressWarnings("unchecked")
251-
public synchronized <T> Provider<Set<T>> setOfProvider(Class<T> anInterface) {
251+
public <T> Provider<Set<T>> setOfProvider(Qualified<T> anInterface) {
252252
LazySet<?> provider = lazySetMap.get(anInterface);
253253
if (provider != null) {
254254
return (Provider<Set<T>>) (Provider<?>) provider;

firebase-components/src/main/java/com/google/firebase/components/CycleDetector.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
/** Cycle detector for the {@link Component} dependency graph. */
2525
class CycleDetector {
2626
private static class Dep {
27-
private final Class<?> anInterface;
27+
private final Qualified<?> anInterface;
2828
private final boolean set;
2929

30-
private Dep(Class<?> anInterface, boolean set) {
30+
private Dep(Qualified<?> anInterface, boolean set) {
3131
this.anInterface = anInterface;
3232
this.set = set;
3333
}
@@ -135,7 +135,7 @@ private static Set<ComponentNode> toGraph(List<Component<?>> components) {
135135
Map<Dep, Set<ComponentNode>> componentIndex = new HashMap<>(components.size());
136136
for (Component<?> component : components) {
137137
ComponentNode node = new ComponentNode(component);
138-
for (Class<?> anInterface : component.getProvidedInterfaces()) {
138+
for (Qualified<?> anInterface : component.getProvidedInterfaces()) {
139139
Dep cmp = new Dep(anInterface, !component.isValue());
140140
if (!componentIndex.containsKey(cmp)) {
141141
componentIndex.put(cmp, new HashSet<>());

0 commit comments

Comments
 (0)