crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 1 | /** |
| 2 | * Copyright (C) 2006 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 | |
| 17 | package com.google.inject; |
| 18 | |
crazyboblee | 07e4182 | 2006-11-21 01:27:08 +0000 | [diff] [blame] | 19 | import static com.google.inject.util.Objects.nonNull; |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 20 | import java.lang.reflect.Type; |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 21 | |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 22 | /** |
kevinb9n | a99dca7 | 2007-02-11 04:48:57 +0000 | [diff] [blame] | 23 | * Binding key consisting of a type and a name. Matches the type and name |
| 24 | * ({@link Inject#value()}) at a point of injection. |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 25 | * |
kevinb9n | a99dca7 | 2007-02-11 04:48:57 +0000 | [diff] [blame] | 26 | * <p>For example, {@code new Key<List<String>>("cities") {}} will match: |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 27 | * |
crazyboblee | 63b592b | 2007-01-25 02:45:24 +0000 | [diff] [blame] | 28 | * <pre> |
kevinb9n | a99dca7 | 2007-02-11 04:48:57 +0000 | [diff] [blame] | 29 | * {@literal @}Inject("cities") |
crazyboblee | 7c5b2c4 | 2007-01-20 02:05:20 +0000 | [diff] [blame] | 30 | * public void setList(List<String> cities) { |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 31 | * ... |
| 32 | * } |
crazyboblee | 63b592b | 2007-01-25 02:45:24 +0000 | [diff] [blame] | 33 | * </pre> |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 34 | * |
| 35 | * @author crazybob@google.com (Bob Lee) |
| 36 | */ |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 37 | public abstract class Key<T> { |
| 38 | |
| 39 | /** |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 40 | * Default binding name. |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 41 | */ |
| 42 | public static final String DEFAULT_NAME = "default"; |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 43 | |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 44 | final String name; |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 45 | final TypeLiteral<T> typeLiteral; |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 46 | final int hashCode; |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 47 | |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 48 | /** |
| 49 | * Constructs a new key. Derives the type from this class's type parameter. |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 50 | * |
| 51 | * <p>Clients create an empty anonymous subclass. Doing so embeds the type |
kevinb9n | a99dca7 | 2007-02-11 04:48:57 +0000 | [diff] [blame] | 52 | * parameter in the anonymous class's type hierarchy so we can reconstitute it |
| 53 | * at runtime despite erasure. |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 54 | * |
| 55 | * <p>Example usage for a binding of type {@code Foo} named "bar": |
| 56 | * {@code new Key<Foo>("bar") {}}. |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 57 | */ |
kevinb9n | a99dca7 | 2007-02-11 04:48:57 +0000 | [diff] [blame] | 58 | @SuppressWarnings("unchecked") |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 59 | protected Key(String name) { |
| 60 | this.name = nonNull(name, "name"); |
kevinb9n | a99dca7 | 2007-02-11 04:48:57 +0000 | [diff] [blame] | 61 | this.typeLiteral |
| 62 | = (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass()); |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 63 | this.hashCode = computeHashCode(); |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 64 | } |
| 65 | |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 66 | /** |
| 67 | * Convenience method. Delegates to {@link #Key(String)} with |
| 68 | * {@link #DEFAULT_NAME}. |
| 69 | */ |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 70 | protected Key() { |
| 71 | this(DEFAULT_NAME); |
| 72 | } |
| 73 | |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 74 | /** |
| 75 | * Unsafe. Constructs a key from a manually specified type. |
| 76 | */ |
kevinb9n | a99dca7 | 2007-02-11 04:48:57 +0000 | [diff] [blame] | 77 | @SuppressWarnings("unchecked") |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 78 | private Key(Type type, String name) { |
crazyboblee | 07e4182 | 2006-11-21 01:27:08 +0000 | [diff] [blame] | 79 | this.name = nonNull(name, "name"); |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 80 | this.typeLiteral = (TypeLiteral<T>) TypeLiteral.get(type); |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 81 | this.hashCode = computeHashCode(); |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 82 | } |
| 83 | |
kevinb9n | a99dca7 | 2007-02-11 04:48:57 +0000 | [diff] [blame] | 84 | /** Constructs a key from a manually specified type. */ |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 85 | private Key(TypeLiteral<T> typeLiteral, String name) { |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 86 | this.name = nonNull(name, "name"); |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 87 | this.typeLiteral = typeLiteral; |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 88 | this.hashCode = computeHashCode(); |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 89 | } |
| 90 | |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 91 | private int computeHashCode() { |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 92 | return typeLiteral.hashCode() * 31 + name.hashCode(); |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 93 | } |
| 94 | |
| 95 | /** |
crazyboblee | b944668 | 2006-12-11 07:16:41 +0000 | [diff] [blame] | 96 | * Returns {@code true} if this key has the default name. |
| 97 | */ |
| 98 | public boolean hasDefaultName() { |
| 99 | return DEFAULT_NAME.equals(this.name); |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * Returns a new key with the same type as this key and the given name, |
| 104 | */ |
crazyboblee | fc9337f | 2007-01-26 00:51:34 +0000 | [diff] [blame] | 105 | Key<T> named(String name) { |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 106 | return new SimpleKey<T>(this.typeLiteral, name); |
crazyboblee | b944668 | 2006-12-11 07:16:41 +0000 | [diff] [blame] | 107 | } |
| 108 | |
| 109 | /** |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 110 | * Gets the key type. |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 111 | */ |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 112 | public TypeLiteral<T> getType() { |
| 113 | return typeLiteral; |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 114 | } |
| 115 | |
| 116 | /** |
| 117 | * Gets the binding name. |
| 118 | */ |
kevinb9n | a99dca7 | 2007-02-11 04:48:57 +0000 | [diff] [blame] | 119 | public String getName() { |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 120 | return name; |
| 121 | } |
| 122 | |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 123 | public int hashCode() { |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 124 | return this.hashCode; |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 125 | } |
| 126 | |
crazyboblee | f1ba2b5 | 2007-01-29 21:19:53 +0000 | [diff] [blame] | 127 | Class<? super T> getRawType() { |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 128 | return typeLiteral.getRawType(); |
crazyboblee | d42a05b | 2006-12-07 01:00:33 +0000 | [diff] [blame] | 129 | } |
| 130 | |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 131 | public boolean equals(Object o) { |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 132 | if (o == this) { |
| 133 | return true; |
| 134 | } |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 135 | if (!(o instanceof Key<?>)) { |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 136 | return false; |
| 137 | } |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 138 | Key<?> other = (Key<?>) o; |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 139 | return name.equals(other.name) && typeLiteral.equals(other.typeLiteral); |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 140 | } |
| 141 | |
| 142 | public String toString() { |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 143 | return Key.class.getSimpleName() |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 144 | + "[type=" + typeLiteral + ", name='" + name + "']"; |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 145 | } |
| 146 | |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 147 | /** |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 148 | * Gets a key for a {@code Class}. Defaults name to {@link #DEFAULT_NAME}. |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 149 | */ |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 150 | public static <T> Key<T> get(Class<T> type) { |
crazyboblee | b944668 | 2006-12-11 07:16:41 +0000 | [diff] [blame] | 151 | return new SimpleKey<T>(type, DEFAULT_NAME); |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 152 | } |
| 153 | |
| 154 | /** |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 155 | * Gets a key for a {@code Class} and a name. |
crazyboblee | 6ab7e1f | 2006-12-02 00:20:36 +0000 | [diff] [blame] | 156 | */ |
crazyboblee | fc9337f | 2007-01-26 00:51:34 +0000 | [diff] [blame] | 157 | public static <T> Key<T> get(Class<T> type, String name) { |
crazyboblee | b944668 | 2006-12-11 07:16:41 +0000 | [diff] [blame] | 158 | return new SimpleKey<T>(type, name); |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 159 | } |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 160 | |
| 161 | /** |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 162 | * Gets a key for a type. Defaults name to {@link #DEFAULT_NAME}. |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 163 | */ |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 164 | public static Key<?> get(Type type) { |
crazyboblee | b944668 | 2006-12-11 07:16:41 +0000 | [diff] [blame] | 165 | return new SimpleKey<Object>(type, DEFAULT_NAME); |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 166 | } |
| 167 | |
| 168 | /** |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 169 | * Gets a key for a type and a name. |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 170 | */ |
crazyboblee | fc9337f | 2007-01-26 00:51:34 +0000 | [diff] [blame] | 171 | public static Key<?> get(Type type, String name) { |
crazyboblee | b944668 | 2006-12-11 07:16:41 +0000 | [diff] [blame] | 172 | return new SimpleKey<Object>(type, name); |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | /** |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 176 | * Gets a key for a type. Defaults name to {@link #DEFAULT_NAME}. |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 177 | */ |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 178 | public static <T> Key<T> get(TypeLiteral<T> typeLiteral) { |
| 179 | return new SimpleKey<T>(typeLiteral, DEFAULT_NAME); |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 180 | } |
| 181 | |
| 182 | /** |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 183 | * Gets key for a type and a name. |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 184 | */ |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 185 | public static <T> Key<T> get(TypeLiteral<T> typeLiteral, String name) { |
| 186 | return new SimpleKey<T>(typeLiteral, name); |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 187 | } |
| 188 | |
crazyboblee | b944668 | 2006-12-11 07:16:41 +0000 | [diff] [blame] | 189 | private static class SimpleKey<T> extends Key<T> { |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 190 | |
crazyboblee | b944668 | 2006-12-11 07:16:41 +0000 | [diff] [blame] | 191 | private SimpleKey(Type type, String name) { |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 192 | super(type, name); |
| 193 | } |
| 194 | |
crazyboblee | 0baa9fc | 2007-01-31 02:38:54 +0000 | [diff] [blame] | 195 | private SimpleKey(TypeLiteral<T> typeLiteral, String name) { |
| 196 | super(typeLiteral, name); |
crazyboblee | 41bc852 | 2006-12-08 07:06:55 +0000 | [diff] [blame] | 197 | } |
crazyboblee | ed8825f | 2006-12-06 01:28:10 +0000 | [diff] [blame] | 198 | } |
crazyboblee | 66b415a | 2006-08-25 02:01:19 +0000 | [diff] [blame] | 199 | } |