1/**
2 * Copyright (C) 2015 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 com.google.inject.daggeradapter;
17
18import com.google.common.collect.ImmutableSet;
19import com.google.inject.Binder;
20import com.google.inject.Key;
21import com.google.inject.internal.UniqueAnnotations;
22import com.google.inject.multibindings.Multibinder;
23import com.google.inject.spi.InjectionPoint;
24import com.google.inject.spi.ModuleAnnotatedMethodScanner;
25
26import dagger.Provides;
27import dagger.Provides.Type;
28
29import java.lang.annotation.Annotation;
30import java.lang.reflect.Method;
31import java.util.Set;
32
33/**
34 * A scanner to process provider methods on Dagger modules.
35 *
36 * @author cgruber@google.com (Christian Gruber)
37 */
38final class DaggerMethodScanner extends ModuleAnnotatedMethodScanner {
39  static DaggerMethodScanner INSTANCE = new DaggerMethodScanner();
40
41  @Override public Set<? extends Class<? extends Annotation>> annotationClasses() {
42    return ImmutableSet.of(dagger.Provides.class);
43  }
44
45  @Override public <T> Key<T> prepareMethod(
46      Binder binder, Annotation rawAnnotation, Key<T> key, InjectionPoint injectionPoint) {
47    Method providesMethod = (Method) injectionPoint.getMember();
48    Provides annotation = (Provides) rawAnnotation;
49    switch (annotation.type()) {
50      case UNIQUE:
51        return key;
52      case MAP:
53        /* TODO(cgruber) implement map bindings */
54        binder.addError("Map bindings are not yet supported.");
55      case SET:
56        return processSetBinding(binder, key);
57      case SET_VALUES:
58        binder.addError(Type.SET_VALUES.name() + " contributions are not supported by Guice.",
59            providesMethod);
60        return key;
61      default:
62        binder.addError("Unknown @Provides type " + annotation.type() + ".", providesMethod);
63        return key;
64    }
65  }
66
67  private static <T> Key<T> processSetBinding(Binder binder, Key<T> key) {
68    Multibinder<T> setBinder = Multibinder.newSetBinder(binder, key.getTypeLiteral());
69    Key<T> newKey = Key.get(key.getTypeLiteral(), UniqueAnnotations.create());
70    setBinder.addBinding().to(newKey);
71    return newKey;
72  }
73
74  private DaggerMethodScanner() {}
75}