Skip to content

Commit 6f05a97

Browse files
committed
Add qualifier support to firebase components.
Details: go/firebase-component-qualifiers
1 parent ffca832 commit 6f05a97

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:18.1.0'
6868
implementation "com.google.android.gms:play-services-tasks:18.0.1"

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
@@ -80,7 +80,7 @@ public final class Component<T> {
8080
}
8181

8282
private final String name;
83-
private final Set<Class<? super T>> providedInterfaces;
83+
private final Set<Qualified<? super T>> providedInterfaces;
8484
private final Set<Dependency> dependencies;
8585
private final @Instantiation int instantiation;
8686
private final @ComponentType int type;
@@ -89,7 +89,7 @@ public final class Component<T> {
8989

9090
private Component(
9191
@Nullable String name,
92-
Set<Class<? super T>> providedInterfaces,
92+
Set<Qualified<? super T>> providedInterfaces,
9393
Set<Dependency> dependencies,
9494
@Instantiation int instantiation,
9595
@ComponentType int type,
@@ -119,7 +119,7 @@ public String getName() {
119119
*
120120
* <p>Note: T conforms to all of these interfaces.
121121
*/
122-
public Set<Class<? super T>> getProvidedInterfaces() {
122+
public Set<Qualified<? super T>> getProvidedInterfaces() {
123123
return providedInterfaces;
124124
}
125125

@@ -202,6 +202,18 @@ public static <T> Component.Builder<T> builder(
202202
return new Builder<>(anInterface, additionalInterfaces);
203203
}
204204

205+
/** Returns a Component<T> builder. */
206+
public static <T> Component.Builder<T> builder(Qualified<T> anInterface) {
207+
return new Builder<>(anInterface);
208+
}
209+
210+
/** Returns a Component<T> builder. */
211+
@SafeVarargs
212+
public static <T> Component.Builder<T> builder(
213+
Qualified<T> anInterface, Qualified<? super T>... additionalInterfaces) {
214+
return new Builder<>(anInterface, additionalInterfaces);
215+
}
216+
205217
/**
206218
* Wraps a value in a {@link Component} with no dependencies.
207219
*
@@ -219,6 +231,13 @@ public static <T> Component<T> of(
219231
return builder(anInterface, additionalInterfaces).factory((args) -> value).build();
220232
}
221233

234+
/** Wraps a value in a {@link Component} with no dependencies. */
235+
@SafeVarargs
236+
public static <T> Component<T> of(
237+
T value, Qualified<T> anInterface, Qualified<? super T>... additionalInterfaces) {
238+
return builder(anInterface, additionalInterfaces).factory((args) -> value).build();
239+
}
240+
222241
/**
223242
* Provides a builder for a {@link Set}-multibinding {@link Component}.
224243
*
@@ -229,6 +248,16 @@ public static <T> Component.Builder<T> intoSetBuilder(Class<T> anInterface) {
229248
return builder(anInterface).intoSet();
230249
}
231250

251+
/**
252+
* Provides a builder for a {@link Set}-multibinding {@link Component}.
253+
*
254+
* <p>Such components can be requested by dependents via {@link ComponentContainer#setOf(Class)} *
255+
* or {@link ComponentContainer#setOfProvider(Class)}.
256+
*/
257+
public static <T> Component.Builder<T> intoSetBuilder(Qualified<T> anInterface) {
258+
return builder(anInterface).intoSet();
259+
}
260+
232261
/**
233262
* Wraps a value in a {@link Set}-multibinding {@link Component} with no dependencies. *
234263
*
@@ -239,22 +268,42 @@ public static <T> Component<T> intoSet(T value, Class<T> anInterface) {
239268
return intoSetBuilder(anInterface).factory(c -> value).build();
240269
}
241270

271+
/**
272+
* Wraps a value in a {@link Set}-multibinding {@link Component} with no dependencies. *
273+
*
274+
* <p>Such components can be requested by dependents via {@link ComponentContainer#setOf(Class)} *
275+
* or {@link ComponentContainer#setOfProvider(Class)}.
276+
*/
277+
public static <T> Component<T> intoSet(T value, Qualified<T> anInterface) {
278+
return intoSetBuilder(anInterface).factory(c -> value).build();
279+
}
280+
242281
/** FirebaseComponent builder. */
243282
public static class Builder<T> {
244283
private String name = null;
245-
private final Set<Class<? super T>> providedInterfaces = new HashSet<>();
284+
private final Set<Qualified<? super T>> providedInterfaces = new HashSet<>();
246285
private final Set<Dependency> dependencies = new HashSet<>();
247286
private @Instantiation int instantiation = Instantiation.LAZY;
248287
private @ComponentType int type = ComponentType.VALUE;
249288
private ComponentFactory<T> factory;
250-
private Set<Class<?>> publishedEvents = new HashSet<>();
289+
private final Set<Class<?>> publishedEvents = new HashSet<>();
251290

252291
@SafeVarargs
253292
private Builder(Class<T> anInterface, Class<? super T>... additionalInterfaces) {
254293
Preconditions.checkNotNull(anInterface, "Null interface");
255-
providedInterfaces.add(anInterface);
294+
providedInterfaces.add(Qualified.unqualified(anInterface));
256295
for (Class<? super T> iface : additionalInterfaces) {
257296
Preconditions.checkNotNull(iface, "Null interface");
297+
providedInterfaces.add(Qualified.unqualified(iface));
298+
}
299+
}
300+
301+
@SafeVarargs
302+
private Builder(Qualified<T> anInterface, Qualified<? super T>... additionalInterfaces) {
303+
Preconditions.checkNotNull(anInterface, "Null interface");
304+
providedInterfaces.add(anInterface);
305+
for (Qualified<? super T> iface : additionalInterfaces) {
306+
Preconditions.checkNotNull(iface, "Null interface");
258307
}
259308
Collections.addAll(providedInterfaces, additionalInterfaces);
260309
}
@@ -301,7 +350,7 @@ private Builder<T> setInstantiation(@Instantiation int instantiation) {
301350
return this;
302351
}
303352

304-
private void validateInterface(Class<?> anInterface) {
353+
private void validateInterface(Qualified<?> anInterface) {
305354
Preconditions.checkArgument(
306355
!providedInterfaces.contains(anInterface),
307356
"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
@@ -43,11 +43,11 @@
4343
* <p>Does {@link Component} dependency resolution and provides access to resolved {@link
4444
* Component}s via {@link #get(Class)} method.
4545
*/
46-
public class ComponentRuntime extends AbstractComponentContainer implements ComponentLoader {
46+
public class ComponentRuntime implements ComponentContainer, ComponentLoader {
4747
private static final Provider<Set<Object>> EMPTY_PROVIDER = Collections::emptySet;
4848
private final Map<Component<?>, Provider<?>> components = new HashMap<>();
49-
private final Map<Class<?>, Provider<?>> lazyInstanceMap = new HashMap<>();
50-
private final Map<Class<?>, LazySet<?>> lazySetMap = new HashMap<>();
49+
private final Map<Qualified<?>, Provider<?>> lazyInstanceMap = new HashMap<>();
50+
private final Map<Qualified<?>, LazySet<?>> lazySetMap = new HashMap<>();
5151
private final List<Provider<ComponentRegistrar>> unprocessedRegistrarProviders;
5252
private final EventBus eventBus;
5353
private final AtomicReference<Boolean> eagerComponentsInitializedWith = new AtomicReference<>();
@@ -184,7 +184,7 @@ private List<Runnable> processInstanceComponents(List<Component<?>> componentsTo
184184
}
185185

186186
Provider<?> provider = components.get(component);
187-
for (Class<?> anInterface : component.getProvidedInterfaces()) {
187+
for (Qualified<?> anInterface : component.getProvidedInterfaces()) {
188188
if (!lazyInstanceMap.containsKey(anInterface)) {
189189
lazyInstanceMap.put(anInterface, provider);
190190
} else {
@@ -203,7 +203,7 @@ private List<Runnable> processInstanceComponents(List<Component<?>> componentsTo
203203
/** Populates lazySetMap to make set components available for consumption via set dependencies. */
204204
private List<Runnable> processSetComponents() {
205205
ArrayList<Runnable> runnables = new ArrayList<>();
206-
Map<Class<?>, Set<Provider<?>>> setIndex = new HashMap<>();
206+
Map<Qualified<?>, Set<Provider<?>>> setIndex = new HashMap<>();
207207
for (Map.Entry<Component<?>, Provider<?>> entry : components.entrySet()) {
208208
Component<?> component = entry.getKey();
209209

@@ -214,15 +214,15 @@ private List<Runnable> processSetComponents() {
214214

215215
Provider<?> provider = entry.getValue();
216216

217-
for (Class<?> anInterface : component.getProvidedInterfaces()) {
217+
for (Qualified<?> anInterface : component.getProvidedInterfaces()) {
218218
if (!setIndex.containsKey(anInterface)) {
219219
setIndex.put(anInterface, new HashSet<>());
220220
}
221221
setIndex.get(anInterface).add(provider);
222222
}
223223
}
224224

225-
for (Map.Entry<Class<?>, Set<Provider<?>>> entry : setIndex.entrySet()) {
225+
for (Map.Entry<Qualified<?>, Set<Provider<?>>> entry : setIndex.entrySet()) {
226226
if (!lazySetMap.containsKey(entry.getKey())) {
227227
lazySetMap.put(entry.getKey(), LazySet.fromCollection(entry.getValue()));
228228
} else {
@@ -240,13 +240,13 @@ private List<Runnable> processSetComponents() {
240240

241241
@Override
242242
@SuppressWarnings("unchecked")
243-
public synchronized <T> Provider<T> getProvider(Class<T> anInterface) {
243+
public synchronized <T> Provider<T> getProvider(Qualified<T> anInterface) {
244244
Preconditions.checkNotNull(anInterface, "Null interface requested.");
245245
return (Provider<T>) lazyInstanceMap.get(anInterface);
246246
}
247247

248248
@Override
249-
public <T> Deferred<T> getDeferred(Class<T> anInterface) {
249+
public <T> Deferred<T> getDeferred(Qualified<T> anInterface) {
250250
Provider<T> provider = getProvider(anInterface);
251251
if (provider == null) {
252252
return OptionalProvider.empty();
@@ -259,7 +259,7 @@ public <T> Deferred<T> getDeferred(Class<T> anInterface) {
259259

260260
@Override
261261
@SuppressWarnings("unchecked")
262-
public synchronized <T> Provider<Set<T>> setOfProvider(Class<T> anInterface) {
262+
public synchronized <T> Provider<Set<T>> setOfProvider(Qualified<T> anInterface) {
263263
LazySet<?> provider = lazySetMap.get(anInterface);
264264
if (provider != null) {
265265
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)