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