1 /* 2 * Copyright (C) 2014 Google, Inc. 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 package dagger.producers.internal; 17 18 import com.google.common.base.Function; 19 import com.google.common.collect.ImmutableSet; 20 import com.google.common.util.concurrent.FutureFallback; 21 import com.google.common.util.concurrent.Futures; 22 import com.google.common.util.concurrent.ListenableFuture; 23 import dagger.producers.Produced; 24 import dagger.producers.Producer; 25 import dagger.producers.monitoring.ProducerMonitor; 26 import java.util.Set; 27 import javax.inject.Provider; 28 29 import static com.google.common.base.Preconditions.checkNotNull; 30 31 /** 32 * Utility methods for use in generated producer code. 33 * 34 * @author Jesse Beder 35 * @since 2.0 36 */ 37 public final class Producers { 38 /** 39 * Returns a future of {@link Produced} that represents the completion (either success or failure) 40 * of the given future. If the input future succeeds, then the resulting future also succeeds with 41 * a successful {@code Produced}; if the input future fails, then the resulting future succeeds 42 * with a failing {@code Produced}. 43 * 44 * <p>Cancelling the resulting future will propagate the cancellation to the input future; but 45 * cancelling the input future will trigger the resulting future to succeed with a failing 46 * {@code Produced}. 47 */ 48 // TODO(user): Document what happens with an InterruptedException after you figure out how to 49 // trigger one in a test. createFutureProduced(ListenableFuture<T> future)50 public static <T> ListenableFuture<Produced<T>> createFutureProduced(ListenableFuture<T> future) { 51 // TODO(dpb): Switch to Futures.catchAsync once guava_jdk5 gets to v19. 52 return Futures.withFallback( 53 Futures.transform( 54 future, 55 new Function<T, Produced<T>>() { 56 @Override 57 public Produced<T> apply(final T value) { 58 return Produced.successful(value); 59 } 60 }), 61 Producers.<T>futureFallbackForProduced()); 62 63 } 64 65 private static final FutureFallback<Produced<Object>> FUTURE_FALLBACK_FOR_PRODUCED = 66 new FutureFallback<Produced<Object>>() { 67 @Override public ListenableFuture<Produced<Object>> create(final Throwable t) { 68 Produced<Object> produced = Produced.failed(t); 69 return Futures.immediateFuture(produced); 70 } 71 }; 72 73 @SuppressWarnings({"unchecked", "rawtypes"}) // bivariant implementation 74 private static <T> FutureFallback<Produced<T>> futureFallbackForProduced() { 75 return (FutureFallback) FUTURE_FALLBACK_FOR_PRODUCED; 76 } 77 78 /** 79 * Returns a future of a {@code Set} that contains a single element: the result of the input 80 * future. 81 */ 82 public static <T> ListenableFuture<Set<T>> createFutureSingletonSet(ListenableFuture<T> future) { 83 return Futures.transform(future, new Function<T, Set<T>>() { 84 @Override public Set<T> apply(T value) { 85 return ImmutableSet.of(value); 86 } 87 }); 88 } 89 90 /** 91 * Returns a producer that immediately executes the binding logic for the given provider every 92 * time it is called. 93 */ 94 public static <T> Producer<T> producerFromProvider(final Provider<T> provider) { 95 checkNotNull(provider); 96 return new AbstractProducer<T>() { 97 @Override 98 protected ListenableFuture<T> compute(ProducerMonitor unusedMonitor) { 99 return Futures.immediateFuture(provider.get()); 100 } 101 }; 102 } 103 104 /** Returns a producer that succeeds with the given value. */ 105 public static <T> Producer<T> immediateProducer(final T value) { 106 return new Producer<T>() { 107 @Override 108 public ListenableFuture<T> get() { 109 return Futures.immediateFuture(value); 110 } 111 }; 112 } 113 114 /** Returns a producer that fails with the given exception. */ 115 public static <T> Producer<T> immediateFailedProducer(final Throwable throwable) { 116 return new Producer<T>() { 117 @Override 118 public ListenableFuture<T> get() { 119 return Futures.immediateFailedFuture(throwable); 120 } 121 }; 122 } 123 124 private Producers() {} 125 } 126