Produced.java revision 5d3207ac2713386ed61c6ca8f0356e8f093a62e1
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 */ 16package dagger.producers; 17 18import com.google.common.base.Objects; 19import dagger.internal.Beta; 20import java.util.concurrent.ExecutionException; 21import javax.annotation.Nullable; 22 23import static com.google.common.base.Preconditions.checkNotNull; 24 25/** 26 * An interface that represents the result of a {@linkplain Producer production} of type {@code T}, 27 * or an exception that was thrown during that production. For any type {@code T} that can be 28 * injected, you can also inject {@code Produced<T>}, which enables handling of any exceptions that 29 * were thrown during the production of {@code T}. 30 * 31 * <p>For example: <pre><code> 32 * {@literal @}Produces Html getResponse( 33 * UserInfo criticalInfo, {@literal Produced<ExtraInfo>} noncriticalInfo) { 34 * try { 35 * return new Html(criticalInfo, noncriticalInfo.get()); 36 * } catch (ExecutionException e) { 37 * logger.warning(e, "Noncritical info"); 38 * return new Html(criticalInfo); 39 * } 40 * } 41 * </code></pre> 42 * 43 * @author Jesse Beder 44 */ 45@Beta 46public abstract class Produced<T> { 47 /** 48 * Returns the result of a production. 49 * 50 * @throws ExecutionException if the production threw an exception 51 */ 52 public abstract T get() throws ExecutionException; 53 54 /** 55 * Two {@code Produced} objects compare equal if both are successful with equal values, or both 56 * are failed with equal exceptions. 57 */ 58 @Override 59 public abstract boolean equals(Object o); 60 61 /** Returns an appropriate hash code to match {@link #equals). */ 62 @Override 63 public abstract int hashCode(); 64 65 /** Returns a successful {@code Produced}, whose {@link #get} will return the given value. */ 66 public static <T> Produced<T> successful(@Nullable T value) { 67 return new Successful(value); 68 } 69 70 /** 71 * Returns a failed {@code Produced}, whose {@link #get} will throw an 72 * {@code ExecutionException} with the given cause. 73 */ 74 public static <T> Produced<T> failed(Throwable throwable) { 75 return new Failed(checkNotNull(throwable)); 76 } 77 78 private static final class Successful<T> extends Produced<T> { 79 @Nullable private final T value; 80 81 private Successful(@Nullable T value) { 82 this.value = value; 83 } 84 85 @Override public T get() { 86 return value; 87 } 88 89 @Override public boolean equals(Object o) { 90 if (o == this) { 91 return true; 92 } else if (o instanceof Successful) { 93 Successful that = (Successful) o; 94 return Objects.equal(this.value, that.value); 95 } else { 96 return false; 97 } 98 } 99 100 @Override public int hashCode() { 101 return value == null ? 0 : value.hashCode(); 102 } 103 } 104 105 private static final class Failed<T> extends Produced<T> { 106 private final Throwable throwable; 107 108 private Failed(Throwable throwable) { 109 this.throwable = checkNotNull(throwable); 110 } 111 112 @Override public T get() throws ExecutionException { 113 throw new ExecutionException(throwable); 114 } 115 116 @Override public boolean equals(Object o) { 117 if (o == this) { 118 return true; 119 } else if (o instanceof Failed) { 120 Failed that = (Failed) o; 121 return this.throwable.equals(that.throwable); 122 } else { 123 return false; 124 } 125 } 126 127 @Override public int hashCode() { 128 return throwable.hashCode(); 129 } 130 } 131 132 private Produced() {} 133} 134