15d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin/*
25d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Copyright (C) 2014 Google Inc.
35d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
45d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
55d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * you may not use this file except in compliance with the License.
65d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * You may obtain a copy of the License at
75d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
85d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
95d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
105d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Unless required by applicable law or agreed to in writing, software
115d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
125d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * See the License for the specific language governing permissions and
145d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * limitations under the License.
155d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */
165d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinpackage dagger.producers;
175d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
185d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.base.Objects;
195d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport dagger.internal.Beta;
205d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport java.util.concurrent.ExecutionException;
215d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.annotation.Nullable;
225d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
235d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static com.google.common.base.Preconditions.checkNotNull;
245d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
255d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin/**
265d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * An interface that represents the result of a {@linkplain Producer production} of type {@code T},
275d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * or an exception that was thrown during that production. For any type {@code T} that can be
285d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * injected, you can also inject {@code Produced<T>}, which enables handling of any exceptions that
295d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * were thrown during the production of {@code T}.
305d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
315d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * <p>For example: <pre><code>
325d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *   {@literal @}Produces Html getResponse(
335d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *       UserInfo criticalInfo, {@literal Produced<ExtraInfo>} noncriticalInfo) {
345d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *     try {
355d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *       return new Html(criticalInfo, noncriticalInfo.get());
365d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *     } catch (ExecutionException e) {
375d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *       logger.warning(e, "Noncritical info");
385d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *       return new Html(criticalInfo);
395d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *     }
405d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *   }
415d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * </code></pre>
425d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
435d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * @author Jesse Beder
445d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */
455d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin@Beta
465d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinpublic abstract class Produced<T> {
475d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  /**
485d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * Returns the result of a production.
495d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   *
505d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * @throws ExecutionException if the production threw an exception
515d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   */
525d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public abstract T get() throws ExecutionException;
535d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
545d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  /**
555d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * Two {@code Produced} objects compare equal if both are successful with equal values, or both
565d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * are failed with equal exceptions.
575d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   */
585d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  @Override
595d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public abstract boolean equals(Object o);
605d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
615d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  /** Returns an appropriate hash code to match {@link #equals). */
625d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  @Override
635d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public abstract int hashCode();
645d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
655d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  /** Returns a successful {@code Produced}, whose {@link #get} will return the given value. */
665d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public static <T> Produced<T> successful(@Nullable T value) {
6787182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    return new Successful<T>(value);
685d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
695d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
705d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  /**
715d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * Returns a failed {@code Produced}, whose {@link #get} will throw an
725d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   * {@code ExecutionException} with the given cause.
735d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin   */
745d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public static <T> Produced<T> failed(Throwable throwable) {
7587182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    return new Failed<T>(checkNotNull(throwable));
765d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
775d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
785d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  private static final class Successful<T> extends Produced<T> {
795d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    @Nullable private final T value;
805d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
815d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    private Successful(@Nullable T value) {
825d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      this.value = value;
835d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
845d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
855d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    @Override public T get() {
865d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      return value;
875d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
885d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
895d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    @Override public boolean equals(Object o) {
905d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      if (o == this) {
915d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        return true;
925d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      } else if (o instanceof Successful) {
9387182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin        Successful<?> that = (Successful<?>) o;
945d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        return Objects.equal(this.value, that.value);
955d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      } else {
965d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        return false;
975d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      }
985d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
995d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1005d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    @Override public int hashCode() {
1015d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      return value == null ? 0 : value.hashCode();
1025d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
1035d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
1045d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1055d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  private static final class Failed<T> extends Produced<T> {
1065d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    private final Throwable throwable;
1075d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1085d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    private Failed(Throwable throwable) {
1095d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      this.throwable = checkNotNull(throwable);
1105d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
1115d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1125d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    @Override public T get() throws ExecutionException {
1135d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      throw new ExecutionException(throwable);
1145d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
1155d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1165d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    @Override public boolean equals(Object o) {
1175d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      if (o == this) {
1185d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        return true;
1195d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      } else if (o instanceof Failed) {
12087182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin        Failed<?> that = (Failed<?>) o;
1215d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        return this.throwable.equals(that.throwable);
1225d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      } else {
1235d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        return false;
1245d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      }
1255d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
1265d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1275d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    @Override public int hashCode() {
1285d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      return throwable.hashCode();
1295d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
1305d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
1315d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1325d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  private Produced() {}
1335d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin}
134