15d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin/*
25d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Copyright (C) 2015 Google, Inc.
35d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
45d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
55d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * you may not use this file except in compliance with the License.
65d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * You may obtain a copy of the License at
75d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
85d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
95d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
105d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Unless required by applicable law or agreed to in writing, software
115d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
125d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * See the License for the specific language governing permissions and
145d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * limitations under the License.
155d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */
165d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinpackage dagger.producers.internal;
175d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
185d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.base.Function;
195d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.collect.ImmutableSet;
205d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.util.concurrent.Futures;
215d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.util.concurrent.ListenableFuture;
225d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport dagger.producers.Producer;
2387182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffinimport dagger.producers.monitoring.ProducerMonitor;
245d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport java.util.ArrayList;
255d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport java.util.List;
265d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport java.util.Set;
275d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
285d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin/**
295d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * A {@link Producer} implementation used to implement {@link Set} bindings. This producer returns
305d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * a future {@link Set} whose elements are populated by subsequent calls to the delegate
315d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * {@link Producer#get} methods.
325d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
335d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * @author Jesse Beder
345d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * @since 2.0
355d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */
365d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinpublic final class SetProducer<T> extends AbstractProducer<Set<T>> {
375d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  /**
385d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * Returns a new producer that creates {@link Set} futures from the union of the given
395d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * {@link Producer} instances.
405d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   */
4187182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin  @SafeVarargs
4287182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin  public static <T> Producer<Set<T>> create(Producer<Set<T>>... producers) {
435d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    return new SetProducer<T>(ImmutableSet.copyOf(producers));
445d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
455d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
465d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  private final Set<Producer<Set<T>>> contributingProducers;
475d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
485d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  private SetProducer(Set<Producer<Set<T>>> contributingProducers) {
495d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    super();
505d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    this.contributingProducers = contributingProducers;
515d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
525d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
535d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  /**
545d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * Returns a future {@link Set} whose iteration order is that of the elements given by each of the
555d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * producers, which are invoked in the order given at creation.
565d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   *
575d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * <p>If any of the delegate sets, or any elements therein, are null, then this future will fail
585d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * with a NullPointerException.
595d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   *
605d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * <p>Canceling this future will attempt to cancel all of the component futures, and if any of the
615d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * delegate futures fails or is canceled, this one is, too.
625d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   *
635d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * @throws NullPointerException if any of the delegate producers return null
645d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   */
655d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  @Override
6687182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin  public ListenableFuture<Set<T>> compute(ProducerMonitor unusedMonitor) {
675d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    List<ListenableFuture<Set<T>>> futureSets =
685d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        new ArrayList<ListenableFuture<Set<T>>>(contributingProducers.size());
695d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    for (Producer<Set<T>> producer : contributingProducers) {
705d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      ListenableFuture<Set<T>> futureSet = producer.get();
715d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      if (futureSet == null) {
725d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        throw new NullPointerException(producer + " returned null");
735d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      }
745d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      futureSets.add(futureSet);
755d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
765d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    return Futures.transform(Futures.allAsList(futureSets), new Function<List<Set<T>>, Set<T>>() {
775d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      @Override public Set<T> apply(List<Set<T>> sets) {
785d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        ImmutableSet.Builder<T> builder = ImmutableSet.builder();
795d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        for (Set<T> set : sets) {
805d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          builder.addAll(set);
815d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        }
825d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        return builder.build();
835d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      }
845d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    });
855d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
865d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin}
87