Elements.java revision bf0d876bb767f45c5cfbed3929e2cf6acd7d061a
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;
2676c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkitimport com.google.inject.Binding;
27477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Key;
28477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Module;
29bf0d876bb767f45c5cfbed3929e2cf6acd7d061alimpbizkitimport com.google.inject.PrivateBinder;
30fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkitimport com.google.inject.PrivateModule;
31477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Provider;
32477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Scope;
33477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Stage;
34477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.TypeLiteral;
35477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.binder.AnnotatedBindingBuilder;
36477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.binder.AnnotatedConstantBindingBuilder;
375ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkitimport com.google.inject.binder.AnnotatedElementBuilder;
3876c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkitimport com.google.inject.internal.AbstractBindingBuilder;
3976c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkitimport com.google.inject.internal.BindingBuilder;
4076c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkitimport com.google.inject.internal.ConstantBindingBuilderImpl;
4172d11dd102eeebf081aa5363469d28b25f9b1384limpbizkitimport com.google.inject.internal.Errors;
42c3f928404a91cf837d809dcc465ba43442bc1198limpbizkitimport com.google.inject.internal.PrivateElementsImpl;
4386cb3bb7d9b662398dc2b71433a9f6c6a6392b5climpbizkitimport com.google.inject.internal.ProviderMethodsModule;
44477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.internal.SourceProvider;
45477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.matcher.Matcher;
46477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.lang.annotation.Annotation;
47477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.lang.reflect.Method;
48477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.Arrays;
495ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkitimport java.util.Collection;
50477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.Collections;
51477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.List;
52477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.Set;
53477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport org.aopalliance.intercept.MethodInterceptor;
54477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
55477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit/**
5600ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit * Exposes elements of a module so they can be inspected, validated or {@link ModuleWriter
5700ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit * rewritten}.
58477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit *
59477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * @author jessewilson@google.com (Jesse Wilson)
60c489adf4671b41765698d167e13960d998190c5elimpbizkit * @since 2.0
61477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit */
62477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitpublic final class Elements {
63afa4b5dd2056a8427657186d1804313c3f34fbfelimpbizkit  private static final BindingTargetVisitor<Object, Object> GET_INSTANCE_VISITOR
64afa4b5dd2056a8427657186d1804313c3f34fbfelimpbizkit      = new DefaultBindingTargetVisitor<Object, Object>() {
658996e8059681c083744df50c7ad9e007eda1f648limpbizkit    @Override public Object visitInstance(InstanceBinding<?> binding) {
6676c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkit      return binding.getInstance();
67477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
68477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
698996e8059681c083744df50c7ad9e007eda1f648limpbizkit    @Override protected Object visitOther(Binding<?> binding) {
70477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      throw new IllegalArgumentException();
71477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
72477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  };
73477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
74477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
75477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
76477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
77477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Module... modules) {
78477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return getElements(Stage.DEVELOPMENT, Arrays.asList(modules));
79477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
80477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
81477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
82477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
83477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
84477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Stage stage, Module... modules) {
85477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return getElements(stage, Arrays.asList(modules));
86477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
87477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
88477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
89477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
90477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
91477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Iterable<? extends Module> modules) {
92477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return getElements(Stage.DEVELOPMENT, modules);
93477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
94477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
95477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
96477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
97477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
98477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Stage stage, Iterable<? extends Module> modules) {
99477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    RecordingBinder binder = new RecordingBinder(stage);
100477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    for (Module module : modules) {
101477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      binder.install(module);
102477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
103477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return Collections.unmodifiableList(binder.elements);
104477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
105477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
106477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  @SuppressWarnings("unchecked")
1077e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit  static <T> BindingTargetVisitor<T, T> getInstanceVisitor() {
108afa4b5dd2056a8427657186d1804313c3f34fbfelimpbizkit    return (BindingTargetVisitor<T, T>) GET_INSTANCE_VISITOR;
109477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
110477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
1115ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit  private static class RecordingBinder implements Binder, PrivateBinder {
112477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final Stage stage;
113477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final Set<Module> modules;
114477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final List<Element> elements;
115477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final Object source;
116477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final SourceProvider sourceProvider;
117fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit
118fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit    /** The binder where exposed bindings will be created */
119fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit    private final RecordingBinder parent;
120c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit    private final PrivateElementsImpl privateElements;
121477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
122477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private RecordingBinder(Stage stage) {
123477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.stage = stage;
124477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.modules = Sets.newHashSet();
125477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.elements = Lists.newArrayList();
126477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.source = null;
12776c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkit      this.sourceProvider = new SourceProvider().plusSkippedClasses(
12876c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkit          Elements.class, RecordingBinder.class, AbstractModule.class,
12976c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkit          ConstantBindingBuilderImpl.class, AbstractBindingBuilder.class, BindingBuilder.class);
130fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.parent = null;
131c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      this.privateElements = null;
132477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
133477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
134fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit    /** Creates a recording binder that's backed by {@code prototype}. */
135fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit    private RecordingBinder(
136fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit        RecordingBinder prototype, Object source, SourceProvider sourceProvider) {
137477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      checkArgument(source == null ^ sourceProvider == null);
138477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
139fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.stage = prototype.stage;
140fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.modules = prototype.modules;
141fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.elements = prototype.elements;
142477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.source = source;
143477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.sourceProvider = sourceProvider;
144fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.parent = prototype.parent;
145c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      this.privateElements = prototype.privateElements;
1465ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
1475ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
1485ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    /** Creates a private recording binder. */
149c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit    private RecordingBinder(RecordingBinder parent, PrivateElementsImpl privateElements) {
1505ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.stage = parent.stage;
1515ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.modules = Sets.newHashSet();
152c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      this.elements = privateElements.getElementsMutable();
1535ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.source = parent.source;
1545ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.sourceProvider = parent.sourceProvider;
155fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.parent = parent;
156c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      this.privateElements = privateElements;
157477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
158477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
159bf0d876bb767f45c5cfbed3929e2cf6acd7d061alimpbizkit    /*if[AOP]*/
160477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void bindInterceptor(
161477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        Matcher<? super Class<?>> classMatcher,
162477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        Matcher<? super Method> methodMatcher,
163477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        MethodInterceptor... interceptors) {
16400ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit      elements.add(new InterceptorBinding(getSource(), classMatcher, methodMatcher, interceptors));
165477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
166bf0d876bb767f45c5cfbed3929e2cf6acd7d061alimpbizkit    /*end[AOP]*/
167477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
168477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void bindScope(Class<? extends Annotation> annotationType, Scope scope) {
16900ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit      elements.add(new ScopeBinding(getSource(), annotationType, scope));
170477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
171477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
172477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void requestInjection(Object... instances) {
173b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      for (Object instance : instances) {
174b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit        elements.add(new InjectionRequest(getSource(), instance));
175b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      }
176477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
177477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
178477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void requestStaticInjection(Class<?>... types) {
179b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      for (Class<?> type : types) {
180b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit        elements.add(new StaticInjectionRequest(getSource(), type));
181b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      }
182477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
183477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
184477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void install(Module module) {
185477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      if (modules.add(module)) {
186fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit        Binder binder = this;
187fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit        if (module instanceof PrivateModule) {
188fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit          binder = binder.newPrivateBinder();
189fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit        }
190fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit
191477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        try {
192fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit          module.configure(binder);
193477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        } catch (RuntimeException e) {
19472d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          Collection<Message> messages = Errors.getMessagesFromThrowable(e);
19572d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          if (!messages.isEmpty()) {
19672d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit            elements.addAll(messages);
19772d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          } else {
19872d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit            addError(e);
19972d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          }
200477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        }
201fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit        binder.install(ProviderMethodsModule.forModule(module));
202477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      }
203477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
204477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
205477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public Stage currentStage() {
206477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return stage;
207477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
208477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
209477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void addError(String message, Object... arguments) {
210b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit      elements.add(new Message(getSource(), Errors.format(message, arguments)));
211477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
212477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
213477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void addError(Throwable t) {
214b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      String message = "An exception was caught and reported. Message: " + t.getMessage();
215b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      elements.add(new Message(ImmutableList.of(getSource()), message, t));
216477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
217477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
218477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void addError(Message message) {
219477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      elements.add(message);
220477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
221477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
222d1fe130a70a1b881d7b27079954b0e9140ab324climpbizkit    public <T> AnnotatedBindingBuilder<T> bind(Key<T> key) {
22376c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkit      return new BindingBuilder<T>(this, elements, getSource(), key);
224477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
225477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
226477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
227477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return bind(Key.get(typeLiteral));
228477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
229477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
230477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> AnnotatedBindingBuilder<T> bind(Class<T> type) {
231477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return bind(Key.get(type));
232477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
233477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
234477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public AnnotatedConstantBindingBuilder bindConstant() {
23576c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkit      return new ConstantBindingBuilderImpl<Void>(this, elements, getSource());
236477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
237477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
238477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> Provider<T> getProvider(final Key<T> key) {
23900ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit      final ProviderLookup<T> command = new ProviderLookup<T>(getSource(), key);
240477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      elements.add(command);
241477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return new Provider<T>() {
242477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        public T get() {
243477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          Provider<T> delegate = command.getDelegate();
244477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          checkState(delegate != null,
245477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit              "This provider cannot be used until the Injector has been created.");
246477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          return delegate.get();
247477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        }
248477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
249477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        @Override public String toString() {
250477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          return "Provider<" + key.getTypeLiteral() + ">";
251477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        }
252477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      };
253477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
254477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
255477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> Provider<T> getProvider(Class<T> type) {
256477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return getProvider(Key.get(type));
257477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
258477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
259477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
260477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        TypeConverter converter) {
26100ca9f749aa80383ee7d85ad25e1535a79fe5718limpbizkit      elements.add(new TypeConverterBinding(getSource(), typeMatcher, converter));
262477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
263477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
2645ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public RecordingBinder withSource(final Object source) {
265477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return new RecordingBinder(this, source, null);
266477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
267477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
2685ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public RecordingBinder skipSources(Class... classesToSkip) {
269477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      // if a source is specified explicitly, we don't need to skip sources
270477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      if (source != null) {
271477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        return this;
272477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      }
273477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
274477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      SourceProvider newSourceProvider = sourceProvider.plusSkippedClasses(classesToSkip);
275477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return new RecordingBinder(this, null, newSourceProvider);
276477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
277477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
2785ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public PrivateBinder newPrivateBinder() {
279c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      PrivateElementsImpl privateElements = new PrivateElementsImpl(getSource());
280c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      elements.add(privateElements);
281c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      return new RecordingBinder(this, privateElements);
2825ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
2835ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
2844994bf6a8e9986ca9013a908c340f019084be30flimpbizkit    public void expose(Key<?> key) {
2854994bf6a8e9986ca9013a908c340f019084be30flimpbizkit      exposeInternal(key);
2865ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
2875ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
2885ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public AnnotatedElementBuilder expose(Class<?> type) {
2895ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      return exposeInternal(Key.get(type));
2905ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
2915ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
2925ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public AnnotatedElementBuilder expose(TypeLiteral<?> type) {
2935ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      return exposeInternal(Key.get(type));
2945ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
2955ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
296fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit    private <T> AnnotatedElementBuilder exposeInternal(Key<T> key) {
297c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      if (privateElements == null) {
298b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit        addError("Cannot expose %s on a standard binder. "
299b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit            + "Exposed bindings are only applicable to private binders.", key);
300b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit        return new AnnotatedElementBuilder() {
301b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit          public void annotatedWith(Class<? extends Annotation> annotationType) {}
302b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit          public void annotatedWith(Annotation annotation) {}
303b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit        };
3045ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      }
3055ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
30676c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkit      BindingBuilder<T> exposeBinding = new BindingBuilder<T>(
30776c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkit          this, parent.elements, getSource(), key);
308fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit
309c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      BindingBuilder.ExposureBuilder<T> builder = exposeBinding.usingKeyFrom(privateElements);
310c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      privateElements.addExposureBuilder(builder);
311fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      return builder;
3125ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
3135ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
314477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    protected Object getSource() {
315477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return sourceProvider != null
316477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          ? sourceProvider.get()
317477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit          : source;
318477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
319477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
320477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    @Override public String toString() {
321477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return "Binder";
322477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
323477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
324477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit}
325