1/**
2 * Copyright (C) 2008 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
17package com.google.inject.spi;
18
19import static com.google.common.base.Preconditions.checkNotNull;
20
21import com.google.common.base.Objects;
22import com.google.common.collect.ImmutableSet;
23import com.google.common.collect.Lists;
24import com.google.inject.Key;
25import com.google.inject.internal.MoreTypes;
26
27import java.util.List;
28import java.util.Set;
29
30/**
31 * A variable that can be resolved by an injector.
32 *
33 * <p>Use {@link #get} to build a freestanding dependency, or {@link InjectionPoint} to build one
34 * that's attached to a constructor, method or field.
35 *
36 * @author crazybob@google.com (Bob Lee)
37 * @author jessewilson@google.com (Jesse Wilson)
38 * @since 2.0
39 */
40public final class Dependency<T> {
41  private final InjectionPoint injectionPoint;
42  private final Key<T> key;
43  private final boolean nullable;
44  private final int parameterIndex;
45
46  Dependency(InjectionPoint injectionPoint, Key<T> key, boolean nullable, int parameterIndex) {
47    this.injectionPoint = injectionPoint;
48    this.key = checkNotNull(key, "key");
49    this.nullable = nullable;
50    this.parameterIndex = parameterIndex;
51  }
52
53  /**
54   * Returns a new dependency that is not attached to an injection point. The returned dependency is
55   * nullable.
56   */
57  public static <T> Dependency<T> get(Key<T> key) {
58    return new Dependency<T>(null, MoreTypes.canonicalizeKey(key), true, -1);
59  }
60
61  /**
62   * Returns the dependencies from the given injection points.
63   */
64  public static Set<Dependency<?>> forInjectionPoints(Set<InjectionPoint> injectionPoints) {
65    List<Dependency<?>> dependencies = Lists.newArrayList();
66    for (InjectionPoint injectionPoint : injectionPoints) {
67      dependencies.addAll(injectionPoint.getDependencies());
68    }
69    return ImmutableSet.copyOf(dependencies);
70  }
71
72  /**
73   * Returns the key to the binding that satisfies this dependency.
74   */
75  public Key<T> getKey() {
76    return this.key;
77  }
78
79  /**
80   * Returns true if null is a legal value for this dependency.
81   */
82  public boolean isNullable() {
83    return nullable;
84  }
85
86  /**
87   * Returns the injection point to which this dependency belongs, or null if this dependency isn't
88   * attached to a particular injection point.
89   */
90  public InjectionPoint getInjectionPoint() {
91    return injectionPoint;
92  }
93
94  /**
95   * Returns the index of this dependency in the injection point's parameter list, or {@code -1} if
96   * this dependency does not belong to a parameter list. Only method and constuctor dependencies
97   * are elements in a parameter list.
98   */
99  public int getParameterIndex() {
100    return parameterIndex;
101  }
102
103  @Override public int hashCode() {
104    return Objects.hashCode(injectionPoint, parameterIndex, key);
105  }
106
107  @Override public boolean equals(Object o) {
108    if (o instanceof Dependency) {
109      Dependency dependency = (Dependency) o;
110      return Objects.equal(injectionPoint, dependency.injectionPoint)
111          && Objects.equal(parameterIndex, dependency.parameterIndex)
112          && Objects.equal(key, dependency.key);
113    } else {
114      return false;
115    }
116  }
117
118  @Override public String toString() {
119    StringBuilder builder = new StringBuilder();
120    builder.append(key);
121    if (injectionPoint != null) {
122      builder.append("@").append(injectionPoint);
123      if (parameterIndex != -1) {
124        builder.append("[").append(parameterIndex).append("]");
125      }
126    }
127    return builder.toString();
128  }
129}
130