All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dagger.producers.internal.SetOfProducedProducer Maven / Gradle / Ivy

There is a newer version: 2.52
Show newest version
/*
 * Copyright (C) 2015 The Dagger Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package dagger.producers.internal;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static dagger.internal.DaggerCollections.hasDuplicates;
import static dagger.internal.DaggerCollections.presizedList;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import dagger.producers.Produced;
import dagger.producers.Producer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;

/**
 * A {@link Producer} implementation used to implement {@link Set} bindings. This producer returns a
 * future {@code Set>} whose elements are populated by subsequent calls to the delegate
 * {@link Producer#get} methods.
 */
public final class SetOfProducedProducer extends AbstractProducer>> {
  public static  Producer> empty() {
    return SetProducer.empty();
  }

  /**
   * Constructs a new {@link Builder} for a {@link SetProducer} with {@code individualProducerSize}
   * individual {@code Producer} and {@code collectionProducerSize} {@code
   * Producer>} instances.
   */
  public static  Builder builder(int individualProducerSize, int collectionProducerSize) {
    return new Builder(individualProducerSize, collectionProducerSize);
  }

  /**
   * A builder to accumulate {@code Producer} and {@code Producer>} instances.
   * These are only intended to be single-use and from within generated code. Do NOT add
   * producers after calling {@link #build()}.
   */
  public static final class Builder {
    private final List> individualProducers;
    private final List>> collectionProducers;

    private Builder(int individualProducerSize, int collectionProducerSize) {
      individualProducers = presizedList(individualProducerSize);
      collectionProducers = presizedList(collectionProducerSize);
    }

    @SuppressWarnings("unchecked")
    public Builder addProducer(Producer individualProducer) {
      assert individualProducer != null : "Codegen error? Null producer";
      individualProducers.add((Producer) individualProducer);
      return this;
    }

    @SuppressWarnings("unchecked")
    public Builder addCollectionProducer(
        Producer> multipleProducer) {
      assert multipleProducer != null : "Codegen error? Null producer";
      collectionProducers.add((Producer>) multipleProducer);
      return this;
    }

    public SetOfProducedProducer build() {
      assert !hasDuplicates(individualProducers)
          : "Codegen error?  Duplicates in the producer list";
      assert !hasDuplicates(collectionProducers)
          : "Codegen error?  Duplicates in the producer list";

      return new SetOfProducedProducer(individualProducers, collectionProducers);
    }
  }

  private final List> individualProducers;
  private final List>> collectionProducers;

  private SetOfProducedProducer(
      List> individualProducers, List>> collectionProducers) {
    this.individualProducers = individualProducers;
    this.collectionProducers = collectionProducers;
  }

  /**
   * Returns a future {@link Set} of {@link Produced} elements given by each of the producers.
   *
   * 

If any of the delegate collections, or any elements therein, are null, then that * corresponding {@code Produced} element will fail with a NullPointerException. * *

Canceling this future will attempt to cancel all of the component futures; but if any of the * delegate futures fail or are canceled, this future succeeds, with the appropriate failed {@link * Produced}. * * @throws NullPointerException if any of the delegate producers return null */ @Override public ListenableFuture>> compute() { List>>> futureProducedCollections = new ArrayList>>>( individualProducers.size() + collectionProducers.size()); for (Producer producer : individualProducers) { // TODO(ronshapiro): Don't require individual productions to be added to a collection just to // be materialized into futureProducedCollections. futureProducedCollections.add( Producers.createFutureProduced( Producers.createFutureSingletonSet(checkNotNull(producer.get())))); } for (Producer> producer : collectionProducers) { futureProducedCollections.add(Producers.createFutureProduced(checkNotNull(producer.get()))); } return Futures.transform( Futures.allAsList(futureProducedCollections), new Function>>, Set>>() { @Override public Set> apply( List>> producedCollections) { ImmutableSet.Builder> builder = ImmutableSet.builder(); for (Produced> producedCollection : producedCollections) { try { Collection collection = producedCollection.get(); if (collection == null) { // TODO(beder): This is a vague exception. Can we somehow point to the failing // producer? See the similar comment in the component writer about null // provisions. builder.add( Produced.failed( new NullPointerException( "Cannot contribute a null collection into a producer set binding when" + " it's injected as Set>."))); } else { for (T value : collection) { if (value == null) { builder.add( Produced.failed( new NullPointerException( "Cannot contribute a null element into a producer set binding" + " when it's injected as Set>."))); } else { builder.add(Produced.successful(value)); } } } } catch (ExecutionException e) { builder.add(Produced.failed(e.getCause())); } } return builder.build(); } }, directExecutor()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy