blob: 01225daf0b96f25e88a937135c8a4640a2fceb0d [file] [log] [blame]
crazyboblee66b415a2006-08-25 02:01:19 +00001/**
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
17package com.google.inject;
18
crazyboblee07e41822006-11-21 01:27:08 +000019import static com.google.inject.util.Objects.nonNull;
crazyboblee9a3861b2007-02-20 03:37:31 +000020import com.google.inject.util.StackTraceElements;
kevinb9n225310e2007-02-20 04:12:01 +000021import com.google.inject.util.ToStringBuilder;
crazyboblee0f09fe32007-02-23 23:43:57 +000022import com.google.inject.util.Annotations;
crazyboblee4602a6f2007-02-15 02:45:18 +000023import java.lang.annotation.Annotation;
24import java.lang.reflect.Member;
crazyboblee6ab7e1f2006-12-02 00:20:36 +000025import java.lang.reflect.Type;
crazyboblee6ab7e1f2006-12-02 00:20:36 +000026
crazyboblee66b415a2006-08-25 02:01:19 +000027/**
crazyboblee4602a6f2007-02-15 02:45:18 +000028 * Binding key consisting of an injection type and an optional annotation.
29 * Matches the type and annotation at a point of injection.
crazyboblee41bc8522006-12-08 07:06:55 +000030 *
crazyboblee4602a6f2007-02-15 02:45:18 +000031 * <p>For example, {@code Key.get(Service.class, Transactional.class) {}} will
32 * match:
crazyboblee41bc8522006-12-08 07:06:55 +000033 *
crazyboblee63b592b2007-01-25 02:45:24 +000034 * <pre>
crazyboblee4602a6f2007-02-15 02:45:18 +000035 * {@literal @}Inject
crazyboblee278ee4d2007-02-15 19:23:13 +000036 * public void setService({@literal @}Transactional Service service) {
crazyboblee41bc8522006-12-08 07:06:55 +000037 * ...
38 * }
crazyboblee63b592b2007-01-25 02:45:24 +000039 * </pre>
crazyboblee66b415a2006-08-25 02:01:19 +000040 *
crazyboblee4602a6f2007-02-15 02:45:18 +000041 * <p>{@code Key} supports generic types via subclassing just like {@link
42 * TypeLiteral}.
43 *
crazyboblee66b415a2006-08-25 02:01:19 +000044 * @author crazybob@google.com (Bob Lee)
45 */
crazyboblee6ab7e1f2006-12-02 00:20:36 +000046public abstract class Key<T> {
47
crazyboblee4602a6f2007-02-15 02:45:18 +000048 final AnnotationStrategy annotationStrategy;
crazyboblee66b415a2006-08-25 02:01:19 +000049
crazyboblee0baa9fc2007-01-31 02:38:54 +000050 final TypeLiteral<T> typeLiteral;
crazyboblee41bc8522006-12-08 07:06:55 +000051 final int hashCode;
crazyboblee66b415a2006-08-25 02:01:19 +000052
crazybobleeed8825f2006-12-06 01:28:10 +000053 /**
54 * Constructs a new key. Derives the type from this class's type parameter.
crazyboblee41bc8522006-12-08 07:06:55 +000055 *
56 * <p>Clients create an empty anonymous subclass. Doing so embeds the type
kevinb9na99dca72007-02-11 04:48:57 +000057 * parameter in the anonymous class's type hierarchy so we can reconstitute it
58 * at runtime despite erasure.
crazybobleeed8825f2006-12-06 01:28:10 +000059 *
crazyboblee4602a6f2007-02-15 02:45:18 +000060 * <p>Example usage for a binding of type {@code Foo} annotated with
61 * {@code @Bar}:
62 *
63 * <p>{@code new Key<Foo>(Bar.class) {}}.
crazybobleeed8825f2006-12-06 01:28:10 +000064 */
kevinb9na99dca72007-02-11 04:48:57 +000065 @SuppressWarnings("unchecked")
crazyboblee4602a6f2007-02-15 02:45:18 +000066 protected Key(Class<? extends Annotation> annotationType) {
67 this.annotationStrategy = strategyFor(annotationType);
kevinb9na99dca72007-02-11 04:48:57 +000068 this.typeLiteral
69 = (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass());
crazyboblee41bc8522006-12-08 07:06:55 +000070 this.hashCode = computeHashCode();
crazyboblee6ab7e1f2006-12-02 00:20:36 +000071 }
72
crazybobleeed8825f2006-12-06 01:28:10 +000073 /**
crazyboblee4602a6f2007-02-15 02:45:18 +000074 * Constructs a new key. Derives the type from this class's type parameter.
75 *
76 * <p>Clients create an empty anonymous subclass. Doing so embeds the type
77 * parameter in the anonymous class's type hierarchy so we can reconstitute it
78 * at runtime despite erasure.
79 *
80 * <p>Example usage for a binding of type {@code Foo} annotated with
81 * {@code @Bar}:
82 *
83 * <p>{@code new Key<Foo>(new Bar()) {}}.
crazybobleeed8825f2006-12-06 01:28:10 +000084 */
crazyboblee4602a6f2007-02-15 02:45:18 +000085 @SuppressWarnings("unchecked")
86 protected Key(Annotation annotation) {
kevinb9n225310e2007-02-20 04:12:01 +000087 // no usages, not test-covered
crazyboblee4602a6f2007-02-15 02:45:18 +000088 this.annotationStrategy = strategyFor(annotation);
89 this.typeLiteral
90 = (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass());
91 this.hashCode = computeHashCode();
92 }
93
94 /**
95 * Constructs a new key. Derives the type from this class's type parameter.
96 *
97 * <p>Clients create an empty anonymous subclass. Doing so embeds the type
98 * parameter in the anonymous class's type hierarchy so we can reconstitute it
99 * at runtime despite erasure.
100 *
crazyboblee4602a6f2007-02-15 02:45:18 +0000101 * <p>Example usage for a binding of type {@code Foo}:
102 *
103 * <p>{@code new Key<Foo>() {}}.
104 */
105 @SuppressWarnings("unchecked")
crazyboblee6ab7e1f2006-12-02 00:20:36 +0000106 protected Key() {
crazyboblee4602a6f2007-02-15 02:45:18 +0000107 this.annotationStrategy = NULL_STRATEGY;
108 this.typeLiteral
109 = (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass());
110 this.hashCode = computeHashCode();
crazyboblee6ab7e1f2006-12-02 00:20:36 +0000111 }
112
crazyboblee41bc8522006-12-08 07:06:55 +0000113 /**
114 * Unsafe. Constructs a key from a manually specified type.
115 */
kevinb9na99dca72007-02-11 04:48:57 +0000116 @SuppressWarnings("unchecked")
crazyboblee4602a6f2007-02-15 02:45:18 +0000117 private Key(Type type, AnnotationStrategy annotationStrategy) {
118 this.annotationStrategy = annotationStrategy;
crazyboblee0baa9fc2007-01-31 02:38:54 +0000119 this.typeLiteral = (TypeLiteral<T>) TypeLiteral.get(type);
crazyboblee41bc8522006-12-08 07:06:55 +0000120 this.hashCode = computeHashCode();
crazyboblee6ab7e1f2006-12-02 00:20:36 +0000121 }
122
kevinb9na99dca72007-02-11 04:48:57 +0000123 /** Constructs a key from a manually specified type. */
crazyboblee4602a6f2007-02-15 02:45:18 +0000124 private Key(TypeLiteral<T> typeLiteral,
125 AnnotationStrategy annotationStrategy) {
126 this.annotationStrategy = annotationStrategy;
crazyboblee0baa9fc2007-01-31 02:38:54 +0000127 this.typeLiteral = typeLiteral;
crazyboblee41bc8522006-12-08 07:06:55 +0000128 this.hashCode = computeHashCode();
crazyboblee66b415a2006-08-25 02:01:19 +0000129 }
130
crazyboblee41bc8522006-12-08 07:06:55 +0000131 private int computeHashCode() {
crazyboblee4602a6f2007-02-15 02:45:18 +0000132 return typeLiteral.hashCode() * 31 + annotationStrategy.hashCode();
crazybobleeb9446682006-12-11 07:16:41 +0000133 }
134
135 /**
crazyboblee0baa9fc2007-01-31 02:38:54 +0000136 * Gets the key type.
crazybobleeed8825f2006-12-06 01:28:10 +0000137 */
crazybobleec3e88492007-02-25 22:36:58 +0000138 public TypeLiteral<T> getTypeLiteral() {
crazyboblee0baa9fc2007-01-31 02:38:54 +0000139 return typeLiteral;
crazybobleeed8825f2006-12-06 01:28:10 +0000140 }
141
142 /**
crazyboblee4602a6f2007-02-15 02:45:18 +0000143 * Gets the annotation type.
crazybobleeed8825f2006-12-06 01:28:10 +0000144 */
crazyboblee4602a6f2007-02-15 02:45:18 +0000145 public Class<? extends Annotation> getAnnotationType() {
146 return annotationStrategy.getAnnotationType();
147 }
148
crazybobleed7908e82007-02-16 01:04:53 +0000149 /**
150 * Gets the annotation.
151 */
152 public Annotation getAnnotation() {
153 return annotationStrategy.getAnnotation();
154 }
155
crazyboblee4602a6f2007-02-15 02:45:18 +0000156 boolean hasAnnotationType() {
157 return annotationStrategy.getAnnotationType() != null;
158 }
159
160 String getAnnotationName() {
161 Annotation annotation = annotationStrategy.getAnnotation();
162 if (annotation != null) {
163 return annotation.toString();
164 }
165
kevinb9n225310e2007-02-20 04:12:01 +0000166 // not test-covered
crazyboblee4602a6f2007-02-15 02:45:18 +0000167 return annotationStrategy.getAnnotationType().toString();
crazyboblee66b415a2006-08-25 02:01:19 +0000168 }
169
crazybobleeed8825f2006-12-06 01:28:10 +0000170 public int hashCode() {
crazyboblee41bc8522006-12-08 07:06:55 +0000171 return this.hashCode;
crazybobleeed8825f2006-12-06 01:28:10 +0000172 }
173
crazybobleef1ba2b52007-01-29 21:19:53 +0000174 Class<? super T> getRawType() {
crazyboblee0baa9fc2007-01-31 02:38:54 +0000175 return typeLiteral.getRawType();
crazybobleed42a05b2006-12-07 01:00:33 +0000176 }
177
crazyboblee66b415a2006-08-25 02:01:19 +0000178 public boolean equals(Object o) {
crazyboblee66b415a2006-08-25 02:01:19 +0000179 if (o == this) {
180 return true;
181 }
crazyboblee41bc8522006-12-08 07:06:55 +0000182 if (!(o instanceof Key<?>)) {
crazybobleeed8825f2006-12-06 01:28:10 +0000183 return false;
184 }
crazyboblee41bc8522006-12-08 07:06:55 +0000185 Key<?> other = (Key<?>) o;
crazyboblee4602a6f2007-02-15 02:45:18 +0000186 return annotationStrategy.equals(other.annotationStrategy)
187 && typeLiteral.equals(other.typeLiteral);
crazyboblee66b415a2006-08-25 02:01:19 +0000188 }
189
190 public String toString() {
crazyboblee4602a6f2007-02-15 02:45:18 +0000191 return new ToStringBuilder(Key.class)
192 .add("type", typeLiteral)
193 .add("annotation", annotationStrategy)
194 .toString();
crazyboblee66b415a2006-08-25 02:01:19 +0000195 }
196
crazyboblee6ab7e1f2006-12-02 00:20:36 +0000197 /**
crazyboblee4602a6f2007-02-15 02:45:18 +0000198 * Gets a key for an injection type and an annotation strategy.
199 */
200 static <T> Key<T> get(Class<T> type,
201 AnnotationStrategy annotationStrategy) {
202 return new SimpleKey<T>(type, annotationStrategy);
203 }
204
205 /**
206 * Gets a key for an injection type.
crazyboblee6ab7e1f2006-12-02 00:20:36 +0000207 */
crazyboblee41bc8522006-12-08 07:06:55 +0000208 public static <T> Key<T> get(Class<T> type) {
crazyboblee4602a6f2007-02-15 02:45:18 +0000209 return new SimpleKey<T>(type, NULL_STRATEGY);
crazyboblee6ab7e1f2006-12-02 00:20:36 +0000210 }
211
212 /**
crazyboblee4602a6f2007-02-15 02:45:18 +0000213 * Gets a key for an injection type and an annotation type.
214 */
215 public static <T> Key<T> get(Class<T> type,
216 Class<? extends Annotation> annotationType) {
217 return new SimpleKey<T>(type, strategyFor(annotationType));
218 }
219
220 /**
crazyboblee4602a6f2007-02-15 02:45:18 +0000221 * Gets a key for an injection type and an annotation.
222 */
223 public static <T> Key<T> get(Class<T> type, Annotation annotation) {
224 return new SimpleKey<T>(type, strategyFor(annotation));
225 }
226
227 /**
228 * Gets a key for an injection type.
crazybobleeed8825f2006-12-06 01:28:10 +0000229 */
crazyboblee41bc8522006-12-08 07:06:55 +0000230 public static Key<?> get(Type type) {
crazyboblee4602a6f2007-02-15 02:45:18 +0000231 return new SimpleKey<Object>(type, NULL_STRATEGY);
crazybobleeed8825f2006-12-06 01:28:10 +0000232 }
233
234 /**
crazyboblee4602a6f2007-02-15 02:45:18 +0000235 * Gets a key for an injection type and an annotation type.
236 */
237 public static Key<?> get(Type type,
238 Class<? extends Annotation> annotationType) {
239 return new SimpleKey<Object>(type, strategyFor(annotationType));
240 }
241
242 /**
243 * Gets a key for an injection type and an annotation.
244 */
245 public static Key<?> get(Type type, Annotation annotation) {
246 return new SimpleKey<Object>(type, strategyFor(annotation));
247 }
248
249 /**
crazyboblee4602a6f2007-02-15 02:45:18 +0000250 * Gets a key for an injection type.
crazyboblee41bc8522006-12-08 07:06:55 +0000251 */
crazyboblee0baa9fc2007-01-31 02:38:54 +0000252 public static <T> Key<T> get(TypeLiteral<T> typeLiteral) {
crazyboblee4602a6f2007-02-15 02:45:18 +0000253 return new SimpleKey<T>(typeLiteral, NULL_STRATEGY);
crazyboblee41bc8522006-12-08 07:06:55 +0000254 }
255
256 /**
crazyboblee4602a6f2007-02-15 02:45:18 +0000257 * Gets a key for an injection type and an annotation type.
258 */
259 public static <T> Key<T> get(TypeLiteral<T> typeLiteral,
260 Class<? extends Annotation> annotationType) {
261 return new SimpleKey<T>(typeLiteral, strategyFor(annotationType));
262 }
263
264 /**
265 * Gets a key for an injection type and an annotation.
266 */
267 public static <T> Key<T> get(TypeLiteral<T> typeLiteral,
268 Annotation annotation) {
269 return new SimpleKey<T>(typeLiteral, strategyFor(annotation));
270 }
271
272 /**
crazyboblee4602a6f2007-02-15 02:45:18 +0000273 * Gets a key for the given type, member and annotations.
274 */
275 static Key<?> get(Type type, Member member, Annotation[] annotations,
276 ErrorHandler errorHandler) {
277 Annotation found = null;
278 for (Annotation annotation : annotations) {
kevinb9nc0c12ea2007-02-20 04:46:01 +0000279 if (annotation.annotationType().getAnnotation(BindingAnnotation.class) != null) {
crazyboblee4602a6f2007-02-15 02:45:18 +0000280 if (found == null) {
281 found = annotation;
282 } else {
crazyboblee9a3861b2007-02-20 03:37:31 +0000283 errorHandler.handle(StackTraceElements.forMember(member),
284 ErrorMessages.DUPLICATE_ANNOTATIONS, found, annotation);
crazyboblee4602a6f2007-02-15 02:45:18 +0000285 }
286 }
287 }
288 Key<?> key = found == null ? Key.get(type) : Key.get(type, found);
289 return key;
290 }
291
292 /**
293 * Returns a new key of the specified type with the same annotation as this
294 * key.
295 */
crazybobleedb395b22007-02-18 05:09:15 +0000296 <T> Key<T> ofType(Class<T> type) {
crazyboblee4602a6f2007-02-15 02:45:18 +0000297 return new SimpleKey<T>(type, annotationStrategy);
298 }
299
300 /**
301 * Returns a new key of the specified type with the same annotation as this
302 * key.
303 */
crazybobleedb395b22007-02-18 05:09:15 +0000304 Key<?> ofType(Type type) {
crazyboblee4602a6f2007-02-15 02:45:18 +0000305 return new SimpleKey<Object>(type, annotationStrategy);
306 }
307
crazybobleec3e88492007-02-25 22:36:58 +0000308 /**
309 * Returns true if this key has annotation attributes.
310 * @return
311 */
312 boolean hasAttributes() {
313 return annotationStrategy.hasAttributes();
314 }
315
316 /**
317 * Returns this key without annotation attributes, i.e. with only the
318 * annotation type.
319 */
320 Key<T> withoutAttributes() {
321 return new SimpleKey<T>(typeLiteral, annotationStrategy.withoutAttributes());
322 }
323
crazybobleeb9446682006-12-11 07:16:41 +0000324 private static class SimpleKey<T> extends Key<T> {
crazyboblee41bc8522006-12-08 07:06:55 +0000325
crazyboblee4602a6f2007-02-15 02:45:18 +0000326 private SimpleKey(Type type, AnnotationStrategy annotationStrategy) {
327 super(type, annotationStrategy);
crazyboblee41bc8522006-12-08 07:06:55 +0000328 }
329
crazyboblee4602a6f2007-02-15 02:45:18 +0000330 private SimpleKey(TypeLiteral<T> typeLiteral,
331 AnnotationStrategy annotationStrategy) {
332 super(typeLiteral, annotationStrategy);
333 }
334 }
335
336 interface AnnotationStrategy {
337
338 Annotation getAnnotation();
339 Class<? extends Annotation> getAnnotationType();
crazybobleec3e88492007-02-25 22:36:58 +0000340 boolean hasAttributes();
341 AnnotationStrategy withoutAttributes();
crazyboblee4602a6f2007-02-15 02:45:18 +0000342 }
343
344 static final AnnotationStrategy NULL_STRATEGY = new AnnotationStrategy() {
345
crazybobleec3e88492007-02-25 22:36:58 +0000346 public boolean hasAttributes() {
347 return false;
348 }
349
350 public AnnotationStrategy withoutAttributes() {
351 throw new UnsupportedOperationException("Key already has no attributes.");
352 }
353
crazyboblee4602a6f2007-02-15 02:45:18 +0000354 public Annotation getAnnotation() {
355 return null;
356 }
357
358 public Class<? extends Annotation> getAnnotationType() {
359 return null;
360 }
361
362 public boolean equals(Object o) {
363 return o == NULL_STRATEGY;
364 }
365
366 public int hashCode() {
367 return 0;
368 }
369
370 public String toString() {
371 return "[none]";
372 }
373 };
374
375 /**
376 * Returns {@code true} if the given annotation type has no attributes.
377 */
378 static boolean isMarker(Class<? extends Annotation> annotationType) {
379 return annotationType.getDeclaredMethods().length == 0;
380 }
381
382 /**
383 * Gets the strategy for an annotation.
384 */
385 static AnnotationStrategy strategyFor(Annotation annotation) {
386 nonNull(annotation, "annotation");
crazyboblee0f09fe32007-02-23 23:43:57 +0000387 Class<? extends Annotation> annotationType = annotation.annotationType();
388 ensureRetainedAtRuntime(annotationType);
crazybobleec3e88492007-02-25 22:36:58 +0000389 ensureIsBindingAnnotation(annotationType);
390 return new AnnotationInstanceStrategy(annotation);
crazyboblee4602a6f2007-02-15 02:45:18 +0000391 }
392
393 /**
394 * Gets the strategy for an annotation type.
395 */
396 static AnnotationStrategy strategyFor(
397 Class<? extends Annotation> annotationType) {
398 nonNull(annotationType, "annotation type");
crazyboblee0f09fe32007-02-23 23:43:57 +0000399 ensureRetainedAtRuntime(annotationType);
crazybobleec3e88492007-02-25 22:36:58 +0000400 ensureIsBindingAnnotation(annotationType);
crazyboblee4602a6f2007-02-15 02:45:18 +0000401 return new AnnotationTypeStrategy(annotationType, null);
402 }
403
crazyboblee0f09fe32007-02-23 23:43:57 +0000404 private static void ensureRetainedAtRuntime(
405 Class<? extends Annotation> annotationType) {
406 if (!Annotations.isRetainedAtRuntime(annotationType)) {
407 throw new IllegalArgumentException(annotationType.getName()
408 + " is not retained at runtime."
409 + " Please annotate it with @Retention(RUNTIME).");
410 }
411 }
412
crazybobleec3e88492007-02-25 22:36:58 +0000413 private static void ensureIsBindingAnnotation(
414 Class<? extends Annotation> annotationType) {
415 if (!isBindingAnnotation(annotationType)) {
416 throw new IllegalArgumentException(annotationType.getName()
417 + " is not a binding annotation."
418 + " Please annotate it with @BindingAnnotation.");
419 }
420 }
421
kevinb9n225310e2007-02-20 04:12:01 +0000422 // this class not test-covered
crazyboblee4602a6f2007-02-15 02:45:18 +0000423 static class AnnotationInstanceStrategy implements AnnotationStrategy {
424
425 final Annotation annotation;
426
427 AnnotationInstanceStrategy(Annotation annotation) {
428 this.annotation = nonNull(annotation, "annotation");
429 }
430
crazybobleec3e88492007-02-25 22:36:58 +0000431 public boolean hasAttributes() {
432 return true;
433 }
434
435 public AnnotationStrategy withoutAttributes() {
436 return new AnnotationTypeStrategy(getAnnotationType(), annotation);
437 }
438
crazyboblee4602a6f2007-02-15 02:45:18 +0000439 public Annotation getAnnotation() {
440 return annotation;
441 }
442
443 public Class<? extends Annotation> getAnnotationType() {
444 return annotation.annotationType();
445 }
446
447 public boolean equals(Object o) {
448 if (!(o instanceof AnnotationInstanceStrategy)) {
449 return false;
450 }
451
452 AnnotationInstanceStrategy other = (AnnotationInstanceStrategy) o;
453 return annotation.equals(other.annotation);
454 }
455
456 public int hashCode() {
457 return annotation.hashCode();
458 }
459
460 public String toString() {
461 return annotation.toString();
462 }
463 }
464
465 static class AnnotationTypeStrategy implements AnnotationStrategy {
466
467 final Class<? extends Annotation> annotationType;
468
469 // Keep the instance around if we have it so the client can request it.
470 final Annotation annotation;
471
472 AnnotationTypeStrategy(Class<? extends Annotation> annotationType,
473 Annotation annotation) {
474 this.annotationType = nonNull(annotationType, "annotation type");
475 this.annotation = annotation;
476 }
477
crazybobleec3e88492007-02-25 22:36:58 +0000478 public boolean hasAttributes() {
479 return false;
480 }
481
482 public AnnotationStrategy withoutAttributes() {
483 throw new UnsupportedOperationException("Key already has no attributes.");
484 }
485
crazyboblee4602a6f2007-02-15 02:45:18 +0000486 public Annotation getAnnotation() {
487 return annotation;
488 }
489
490 public Class<? extends Annotation> getAnnotationType() {
491 return annotationType;
492 }
493
494 public boolean equals(Object o) {
495 if (!(o instanceof AnnotationTypeStrategy)) {
496 return false;
497 }
498
499 AnnotationTypeStrategy other = (AnnotationTypeStrategy) o;
500 return annotationType.equals(other.annotationType);
501 }
502
503 public int hashCode() {
504 return annotationType.hashCode();
505 }
506
507 public String toString() {
crazybobleed7908e82007-02-16 01:04:53 +0000508 return "@" + annotationType.getName();
crazyboblee41bc8522006-12-08 07:06:55 +0000509 }
crazybobleeed8825f2006-12-06 01:28:10 +0000510 }
crazybobleec3e88492007-02-25 22:36:58 +0000511
512 static boolean isBindingAnnotation(Annotation annotation) {
513 return isBindingAnnotation(annotation.annotationType());
514 }
515
516 static boolean isBindingAnnotation(
517 Class<? extends Annotation> annotationType) {
518 return annotationType.isAnnotationPresent(BindingAnnotation.class);
519 }
crazyboblee66b415a2006-08-25 02:01:19 +0000520}