Elements.java revision 5ea4ab2bca518a3ac24dc5c0713326e8699d3fad
1477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit/**
2477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * Copyright (C) 2008 Google Inc.
3477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit *
4477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * Licensed under the Apache License, Version 2.0 (the "License");
5477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * you may not use this file except in compliance with the License.
6477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * You may obtain a copy of the License at
7477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit *
8477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * http://www.apache.org/licenses/LICENSE-2.0
9477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit *
10477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * Unless required by applicable law or agreed to in writing, software
11477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * distributed under the License is distributed on an "AS IS" BASIS,
12477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * See the License for the specific language governing permissions and
14477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * limitations under the License.
15477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit */
16477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
17477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitpackage com.google.inject.spi;
18477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
19477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport static com.google.common.base.Preconditions.checkArgument;
20477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport static com.google.common.base.Preconditions.checkState;
21b3a8f0bda3259af41e639f1872c42377989704d9limpbizkitimport com.google.common.collect.ImmutableList;
22477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.common.collect.Lists;
23477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.common.collect.Sets;
24477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.AbstractModule;
25477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Binder;
26477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Key;
27477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Module;
28477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Provider;
29477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Scope;
30477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Stage;
31477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.TypeLiteral;
32477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.binder.AnnotatedBindingBuilder;
33477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.binder.AnnotatedConstantBindingBuilder;
345ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkitimport com.google.inject.binder.AnnotatedElementBuilder;
355ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkitimport com.google.inject.binder.PrivateBinder;
3672d11dd102eeebf081aa5363469d28b25f9b1384limpbizkitimport com.google.inject.internal.Errors;
37477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.internal.ModuleBinding;
3886cb3bb7d9b662398dc2b71433a9f6c6a6392b5climpbizkitimport com.google.inject.internal.ProviderMethodsModule;
39477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.internal.SourceProvider;
40477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.matcher.Matcher;
41477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.lang.annotation.Annotation;
42477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.lang.reflect.Method;
43477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.Arrays;
445ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkitimport java.util.Collection;
45477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.Collections;
46477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.List;
47477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.Set;
48477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport org.aopalliance.intercept.MethodInterceptor;
49477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
50477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit/**
5100ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit * Exposes elements of a module so they can be inspected, validated or {@link ModuleWriter
5200ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit * rewritten}.
53477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit *
54477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * @author jessewilson@google.com (Jesse Wilson)
55c489adf4671b41765698d167e13960d998190c5elimpbizkit * @since 2.0
56477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit */
57477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitpublic final class Elements {
58afa4b5dd2056a8427657186d1804313c3f34fbfelimpbizkit  private static final BindingTargetVisitor<Object, Object> GET_INSTANCE_VISITOR
59afa4b5dd2056a8427657186d1804313c3f34fbfelimpbizkit      = new DefaultBindingTargetVisitor<Object, Object>() {
60b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit    @Override public Object visitInstance(Object instance, Set<InjectionPoint> injectionPoints) {
61477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return instance;
62477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
63477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
64d1fe130a70a1b881d7b27079954b0e9140ab324climpbizkit    @Override protected Object visitOther() {
65477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      throw new IllegalArgumentException();
66477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
67477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  };
68477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
69477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
70477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
71477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
72477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Module... modules) {
73477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return getElements(Stage.DEVELOPMENT, Arrays.asList(modules));
74477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
75477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
76477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
77477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
78477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
79477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Stage stage, Module... modules) {
80477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return getElements(stage, Arrays.asList(modules));
81477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
82477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
83477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
84477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
85477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
86477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Iterable<? extends Module> modules) {
87477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return getElements(Stage.DEVELOPMENT, modules);
88477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
89477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
90477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
91477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
92477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
93477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Stage stage, Iterable<? extends Module> modules) {
94477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    RecordingBinder binder = new RecordingBinder(stage);
95477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    for (Module module : modules) {
96477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      binder.install(module);
97477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
98477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return Collections.unmodifiableList(binder.elements);
99477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
100477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
101477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  @SuppressWarnings("unchecked")
1027e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit  static <T> BindingTargetVisitor<T, T> getInstanceVisitor() {
103afa4b5dd2056a8427657186d1804313c3f34fbfelimpbizkit    return (BindingTargetVisitor<T, T>) GET_INSTANCE_VISITOR;
104477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
105477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
1065ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit  private static class RecordingBinder implements Binder, PrivateBinder {
107477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final Stage stage;
108477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final Set<Module> modules;
109477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final List<Element> elements;
110477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final Object source;
111477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final SourceProvider sourceProvider;
1125ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    private final PrivateEnvironment privateEnvironment;
113477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
114477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private RecordingBinder(Stage stage) {
115477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.stage = stage;
116477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.modules = Sets.newHashSet();
117477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.elements = Lists.newArrayList();
118477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.source = null;
119477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.sourceProvider = new SourceProvider()
120477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          .plusSkippedClasses(Elements.class, RecordingBinder.class, AbstractModule.class);
1215ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.privateEnvironment = null;
122477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
123477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
1245ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    /** Creates a recording binder that's backed by {@code backingBinder}. */
125477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private RecordingBinder(RecordingBinder parent, Object source, SourceProvider sourceProvider) {
126477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      checkArgument(source == null ^ sourceProvider == null);
127477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
128477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.stage = parent.stage;
129477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.modules = parent.modules;
130477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.elements = parent.elements;
131477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.source = source;
132477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.sourceProvider = sourceProvider;
1335ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.privateEnvironment = parent.privateEnvironment;
1345ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
1355ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
1365ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    /** Creates a private recording binder. */
1375ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    private RecordingBinder(RecordingBinder parent, PrivateEnvironment privateEnvironment) {
1385ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.stage = parent.stage;
1395ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.modules = Sets.newHashSet();
1405ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.elements = privateEnvironment.elementsMutable;
1415ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.source = parent.source;
1425ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.sourceProvider = parent.sourceProvider;
1435ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.privateEnvironment = privateEnvironment;
144477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
145477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
146477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void bindInterceptor(
147477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        Matcher<? super Class<?>> classMatcher,
148477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        Matcher<? super Method> methodMatcher,
149477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        MethodInterceptor... interceptors) {
15000ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit      elements.add(new InterceptorBinding(getSource(), classMatcher, methodMatcher, interceptors));
151477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
152477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
153477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void bindScope(Class<? extends Annotation> annotationType, Scope scope) {
15400ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit      elements.add(new ScopeBinding(getSource(), annotationType, scope));
155477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
156477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
157477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void requestInjection(Object... instances) {
158b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      for (Object instance : instances) {
159b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit        elements.add(new InjectionRequest(getSource(), instance));
160b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      }
161477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
162477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
163477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void requestStaticInjection(Class<?>... types) {
164b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      for (Class<?> type : types) {
165b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit        elements.add(new StaticInjectionRequest(getSource(), type));
166b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      }
167477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
168477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
169477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void install(Module module) {
170477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      if (modules.add(module)) {
171477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        try {
172477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          module.configure(this);
173477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        } catch (RuntimeException e) {
17472d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          Collection<Message> messages = Errors.getMessagesFromThrowable(e);
17572d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          if (!messages.isEmpty()) {
17672d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit            elements.addAll(messages);
17772d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          } else {
17872d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit            addError(e);
17972d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          }
180477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        }
18186cb3bb7d9b662398dc2b71433a9f6c6a6392b5climpbizkit        install(ProviderMethodsModule.forModule(module));
182477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      }
183477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
184477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
185477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public Stage currentStage() {
186477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return stage;
187477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
188477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
189477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void addError(String message, Object... arguments) {
190477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      elements.add(new Message(getSource(), String.format(message, arguments)));
191477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
192477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
193477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void addError(Throwable t) {
194b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      String message = "An exception was caught and reported. Message: " + t.getMessage();
195b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      elements.add(new Message(ImmutableList.of(getSource()), message, t));
196477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
197477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
198477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void addError(Message message) {
199477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      elements.add(message);
200477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
201477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
202d1fe130a70a1b881d7b27079954b0e9140ab324climpbizkit    public <T> AnnotatedBindingBuilder<T> bind(Key<T> key) {
203477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      ModuleBinding<T> moduleBindingCommand = new ModuleBinding<T>(getSource(), key);
204477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      elements.add(moduleBindingCommand);
205d1fe130a70a1b881d7b27079954b0e9140ab324climpbizkit      return moduleBindingCommand.regularBuilder(RecordingBinder.this);
206477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
207477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
208477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
209477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return bind(Key.get(typeLiteral));
210477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
211477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
212477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> AnnotatedBindingBuilder<T> bind(Class<T> type) {
213477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return bind(Key.get(type));
214477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
215477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
216477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public AnnotatedConstantBindingBuilder bindConstant() {
217d1fe130a70a1b881d7b27079954b0e9140ab324climpbizkit      ModuleBinding<Object> moduleBindingCommand = new ModuleBinding<Object>(getSource());
218d1fe130a70a1b881d7b27079954b0e9140ab324climpbizkit      elements.add(moduleBindingCommand);
219d1fe130a70a1b881d7b27079954b0e9140ab324climpbizkit      return moduleBindingCommand.constantBuilder(RecordingBinder.this);
220477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
221477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
222477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> Provider<T> getProvider(final Key<T> key) {
22300ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit      final ProviderLookup<T> command = new ProviderLookup<T>(getSource(), key);
224477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      elements.add(command);
225477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return new Provider<T>() {
226477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        public T get() {
227477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          Provider<T> delegate = command.getDelegate();
228477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          checkState(delegate != null,
229477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit              "This provider cannot be used until the Injector has been created.");
230477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          return delegate.get();
231477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        }
232477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
233477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        @Override public String toString() {
234477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          return "Provider<" + key.getTypeLiteral() + ">";
235477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        }
236477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      };
237477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
238477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
239477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> Provider<T> getProvider(Class<T> type) {
240477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return getProvider(Key.get(type));
241477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
242477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
243477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
244477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        TypeConverter converter) {
24500ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit      elements.add(new TypeConverterBinding(getSource(), typeMatcher, converter));
246477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
247477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
2485ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public RecordingBinder withSource(final Object source) {
249477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return new RecordingBinder(this, source, null);
250477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
251477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
2525ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public RecordingBinder skipSources(Class... classesToSkip) {
253477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      // if a source is specified explicitly, we don't need to skip sources
254477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      if (source != null) {
255477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        return this;
256477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      }
257477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
258477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      SourceProvider newSourceProvider = sourceProvider.plusSkippedClasses(classesToSkip);
259477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return new RecordingBinder(this, null, newSourceProvider);
260477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
261477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
2625ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public PrivateBinder newPrivateBinder() {
2635ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      PrivateEnvironment privateEnvironment = new PrivateEnvironment(getSource());
2645ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      elements.add(privateEnvironment);
2655ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      return new RecordingBinder(this, privateEnvironment);
2665ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
2675ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
2685ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public void expose(Key<?> type) {
2695ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      exposeInternal(type);
2705ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
2715ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
2725ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public AnnotatedElementBuilder expose(Class<?> type) {
2735ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      return exposeInternal(Key.get(type));
2745ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
2755ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
2765ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public AnnotatedElementBuilder expose(TypeLiteral<?> type) {
2775ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      return exposeInternal(Key.get(type));
2785ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
2795ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
2805ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    private AnnotatedElementBuilder exposeInternal(Key<?> key) {
2815ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      if (privateEnvironment == null) {
2825ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit        throw new UnsupportedOperationException("expose() only supported on PrivateBinder. "
2835ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit            + "Avoid using 'instanceof PrivateBinder', it's unsafe.");
2845ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      }
2855ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
2865ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      Exposure exposure = new Exposure(getSource(), privateEnvironment, key);
2875ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      elements.add(exposure);
2885ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      return exposure.annotatedElementBuilder(this);
2895ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
2905ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
291477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    protected Object getSource() {
292477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return sourceProvider != null
293477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          ? sourceProvider.get()
294477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          : source;
295477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
296477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
297477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    @Override public String toString() {
298477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return "Binder";
299477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
300477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
301477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit}
302