• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Dagger Authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dagger.producers.internal;
18 
19 import static com.google.common.util.concurrent.Futures.transform;
20 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
21 
22 import com.google.common.base.Function;
23 import com.google.common.collect.ImmutableMap;
24 import com.google.common.collect.Iterables;
25 import com.google.common.collect.Maps;
26 import com.google.common.util.concurrent.Futures;
27 import com.google.common.util.concurrent.ListenableFuture;
28 import dagger.producers.Produced;
29 import dagger.producers.Producer;
30 import java.util.List;
31 import java.util.Map;
32 import javax.inject.Provider;
33 
34 /**
35  * A {@link Producer} implementation used to implement {@link Map} bindings. This producer returns a
36  * {@code Map<K, Produced<V>>} which is populated by calls to the delegate {@link Producer#get}
37  * methods.
38  */
39 public final class MapOfProducedProducer<K, V> extends AbstractMapProducer<K, V, Produced<V>> {
MapOfProducedProducer(ImmutableMap<K, Producer<V>> contributingMap)40   private MapOfProducedProducer(ImmutableMap<K, Producer<V>> contributingMap) {
41     super(contributingMap);
42   }
43 
44   @Override
compute()45   public ListenableFuture<Map<K, Produced<V>>> compute() {
46     return Futures.transform(
47         Futures.allAsList(
48             Iterables.transform(
49                 contributingMap().entrySet(), MapOfProducedProducer.<K, V>entryUnwrapper())),
50         new Function<List<Map.Entry<K, Produced<V>>>, Map<K, Produced<V>>>() {
51           @Override
52           public Map<K, Produced<V>> apply(List<Map.Entry<K, Produced<V>>> entries) {
53             return ImmutableMap.copyOf(entries);
54           }
55         },
56         directExecutor());
57   }
58 
59   private static final Function<
60           Map.Entry<Object, Producer<Object>>,
61           ListenableFuture<Map.Entry<Object, Produced<Object>>>>
62       ENTRY_UNWRAPPER =
63           new Function<
64               Map.Entry<Object, Producer<Object>>,
65               ListenableFuture<Map.Entry<Object, Produced<Object>>>>() {
66             @Override
67             public ListenableFuture<Map.Entry<Object, Produced<Object>>> apply(
68                 final Map.Entry<Object, Producer<Object>> entry) {
69               return transform(
70                   Producers.createFutureProduced(entry.getValue().get()),
71                   new Function<Produced<Object>, Map.Entry<Object, Produced<Object>>>() {
72                     @Override
73                     public Map.Entry<Object, Produced<Object>> apply(Produced<Object> value) {
74                       return Maps.immutableEntry(entry.getKey(), value);
75                     }
76                   },
77                   directExecutor());
78             }
79           };
80 
81   @SuppressWarnings({"unchecked", "rawtypes"}) // bivariate implementation
82   private static <K, V>
83       Function<Map.Entry<K, Producer<V>>, ListenableFuture<Map.Entry<K, Produced<V>>>>
84           entryUnwrapper() {
85     return (Function) ENTRY_UNWRAPPER;
86   }
87 
88   /** Returns a new {@link Builder}. */
89   public static <K, V> Builder<K, V> builder(int size) {
90     return new Builder<>(size);
91   }
92 
93   /** A builder for {@link MapOfProducedProducer}. */
94   public static final class Builder<K, V> extends AbstractMapProducer.Builder<K, V, Produced<V>> {
95     private Builder(int size) {
96       super(size);
97     }
98 
99     @Override
100     public Builder<K, V> put(K key, Producer<V> producerOfValue) {
101       super.put(key, producerOfValue);
102       return this;
103     }
104 
105     @Override
106     public Builder<K, V> put(K key, Provider<V> providerOfValue) {
107       super.put(key, providerOfValue);
108       return this;
109     }
110 
111     @Override
112     public Builder<K, V> putAll(Producer<Map<K, Produced<V>>> mapOfProducedProducer) {
113       super.putAll(mapOfProducedProducer);
114       return this;
115     }
116 
117     /** Returns a new {@link MapOfProducedProducer}. */
118     public MapOfProducedProducer<K, V> build() {
119       return new MapOfProducedProducer<>(mapBuilder.build());
120     }
121   }
122 }
123