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.MoreExecutors.directExecutor; 20 21 import com.google.common.base.Function; 22 import com.google.common.collect.ImmutableMap; 23 import com.google.common.collect.Maps; 24 import com.google.common.util.concurrent.Futures; 25 import com.google.common.util.concurrent.ListenableFuture; 26 import dagger.producers.Producer; 27 import java.util.ArrayList; 28 import java.util.List; 29 import java.util.Map; 30 import java.util.Map.Entry; 31 import javax.inject.Provider; 32 33 /** 34 * A {@link Producer} implementation used to implement {@link Map} bindings. This producer returns a 35 * {@code Map<K, V>} which is populated by calls to the delegate {@link Producer#get} methods. 36 */ 37 public final class MapProducer<K, V> extends AbstractMapProducer<K, V, V> { MapProducer(ImmutableMap<K, Producer<V>> contributingMap)38 private MapProducer(ImmutableMap<K, Producer<V>> contributingMap) { 39 super(contributingMap); 40 } 41 42 /** Returns a new {@link Builder}. */ builder(int size)43 public static <K, V> Builder<K, V> builder(int size) { 44 return new Builder<>(size); 45 } 46 47 /** A builder for {@link MapProducer} */ 48 public static final class Builder<K, V> extends AbstractMapProducer.Builder<K, V, V> { Builder(int size)49 private Builder(int size) { 50 super(size); 51 } 52 53 @Override put(K key, Producer<V> producerOfValue)54 public Builder<K, V> put(K key, Producer<V> producerOfValue) { 55 super.put(key, producerOfValue); 56 return this; 57 } 58 59 @Override put(K key, Provider<V> providerOfValue)60 public Builder<K, V> put(K key, Provider<V> providerOfValue) { 61 super.put(key, providerOfValue); 62 return this; 63 } 64 65 @Override putAll(Producer<Map<K, V>> mapProducer)66 public Builder<K, V> putAll(Producer<Map<K, V>> mapProducer) { 67 super.putAll(mapProducer); 68 return this; 69 } 70 71 /** Returns a new {@link MapProducer}. */ build()72 public MapProducer<K, V> build() { 73 return new MapProducer<>(mapBuilder.build()); 74 } 75 } 76 77 @Override compute()78 protected ListenableFuture<Map<K, V>> compute() { 79 final List<ListenableFuture<Map.Entry<K, V>>> listOfEntries = new ArrayList<>(); 80 for (final Entry<K, Producer<V>> entry : contributingMap().entrySet()) { 81 listOfEntries.add( 82 Futures.transform( 83 entry.getValue().get(), 84 new Function<V, Entry<K, V>>() { 85 @Override 86 public Entry<K, V> apply(V computedValue) { 87 return Maps.immutableEntry(entry.getKey(), computedValue); 88 } 89 }, 90 directExecutor())); 91 } 92 93 return Futures.transform( 94 Futures.allAsList(listOfEntries), 95 new Function<List<Map.Entry<K, V>>, Map<K, V>>() { 96 @Override 97 public Map<K, V> apply(List<Map.Entry<K, V>> entries) { 98 return ImmutableMap.copyOf(entries); 99 } 100 }, 101 directExecutor()); 102 } 103 } 104