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; 17 18 import com.google.common.base.Objects; 19 import dagger.internal.Beta; 20 import java.util.concurrent.ExecutionException; 21 import javax.annotation.Nullable; 22 23 import 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 46 public abstract class Produced<T> { 47 /** 48 * Returns the result of a production. 49 * 50 * @throws ExecutionException if the production threw an exception 51 */ get()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 equals(Object o)59 public abstract boolean equals(Object o); 60 61 /** Returns an appropriate hash code to match {@link #equals). */ 62 @Override hashCode()63 public abstract int hashCode(); 64 65 /** Returns a successful {@code Produced}, whose {@link #get} will return the given value. */ successful(@ullable T value)66 public static <T> Produced<T> successful(@Nullable T value) { 67 return new Successful<T>(value); 68 } 69 70 /** 71 * Returns a failed {@code Produced}, whose {@link #get} will throw an 72 * {@code ExecutionException} with the given cause. 73 */ failed(Throwable throwable)74 public static <T> Produced<T> failed(Throwable throwable) { 75 return new Failed<T>(checkNotNull(throwable)); 76 } 77 78 private static final class Successful<T> extends Produced<T> { 79 @Nullable private final T value; 80 Successful(@ullable T value)81 private Successful(@Nullable T value) { 82 this.value = value; 83 } 84 get()85 @Override public T get() { 86 return value; 87 } 88 equals(Object o)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 hashCode()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 Failed(Throwable throwable)108 private Failed(Throwable throwable) { 109 this.throwable = checkNotNull(throwable); 110 } 111 get()112 @Override public T get() throws ExecutionException { 113 throw new ExecutionException(throwable); 114 } 115 equals(Object o)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 hashCode()127 @Override public int hashCode() { 128 return throwable.hashCode(); 129 } 130 } 131 Produced()132 private Produced() {} 133 } 134