blob: fa6954e551deef1a306c5a9d1818620533ebc62f [file] [log] [blame]
limpbizkit03b81a62009-03-18 05:34:39 +00001/*
2 * Copyright (C) 2007 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
19import com.google.inject.internal.BindingImpl;
20import com.google.inject.internal.Errors;
21import com.google.inject.internal.ErrorsException;
limpbizkita843a952009-04-08 22:24:55 +000022import com.google.inject.internal.ImmutableSet;
limpbizkit03b81a62009-03-18 05:34:39 +000023import com.google.inject.internal.InternalContext;
24import com.google.inject.internal.InternalFactory;
25import static com.google.inject.internal.Preconditions.checkState;
26import com.google.inject.internal.Scoping;
27import com.google.inject.internal.ToStringBuilder;
28import com.google.inject.spi.BindingTargetVisitor;
29import com.google.inject.spi.ConstructorBinding;
30import com.google.inject.spi.Dependency;
limpbizkita843a952009-04-08 22:24:55 +000031import com.google.inject.spi.InjectionPoint;
32import java.lang.reflect.Method;
33import java.util.List;
34import java.util.Map;
limpbizkit03b81a62009-03-18 05:34:39 +000035import java.util.Set;
36
37class ConstructorBindingImpl<T> extends BindingImpl<T> implements ConstructorBinding<T> {
38
39 private final Factory<T> factory;
limpbizkit03b81a62009-03-18 05:34:39 +000040
41 private ConstructorBindingImpl(Injector injector, Key<T> key, Object source,
42 InternalFactory<? extends T> scopedFactory, Scoping scoping, Factory<T> factory) {
43 super(injector, key, source, scopedFactory, scoping);
44 this.factory = factory;
45 }
46
47 static <T> ConstructorBindingImpl<T> create(
48 InjectorImpl injector, Key<T> key, Object source, Scoping scoping) {
49 Factory<T> factoryFactory = new Factory<T>();
50 InternalFactory<? extends T> scopedFactory
51 = Scopes.scope(key, injector, factoryFactory, scoping);
52 return new ConstructorBindingImpl<T>(
53 injector, key, source, scopedFactory, scoping, factoryFactory);
54 }
55
limpbizkit03b81a62009-03-18 05:34:39 +000056 public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
limpbizkit7cef5b02009-03-29 21:16:51 +000057 factory.constructorInjector = injector.constructors.get(getKey().getTypeLiteral(), errors);
limpbizkit03b81a62009-03-18 05:34:39 +000058 }
59
60 public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
limpbizkita843a952009-04-08 22:24:55 +000061 checkState(factory.constructorInjector != null, "not initialized");
limpbizkit03b81a62009-03-18 05:34:39 +000062 return visitor.visit(this);
63 }
64
limpbizkita843a952009-04-08 22:24:55 +000065 public InjectionPoint getConstructor() {
66 checkState(factory.constructorInjector != null, "Binding is not ready");
67 return factory.constructorInjector.getConstructionProxy().getInjectionPoint();
limpbizkit03b81a62009-03-18 05:34:39 +000068 }
69
limpbizkita843a952009-04-08 22:24:55 +000070 public Set<InjectionPoint> getInjectableMembers() {
71 checkState(factory.constructorInjector != null, "Binding is not ready");
72 return factory.constructorInjector.getInjectableMembers();
73 }
74
limpbizkiteb405132009-04-14 00:50:25 +000075 /*if[AOP]*/
76 public Map<Method, List<org.aopalliance.intercept.MethodInterceptor>> getMethodInterceptors() {
limpbizkita843a952009-04-08 22:24:55 +000077 checkState(factory.constructorInjector != null, "Binding is not ready");
limpbizkiteb405132009-04-14 00:50:25 +000078 return factory.constructorInjector.getConstructionProxy().getMethodInterceptors();
limpbizkit03b81a62009-03-18 05:34:39 +000079 }
limpbizkiteb405132009-04-14 00:50:25 +000080 /*end[AOP]*/
limpbizkit03b81a62009-03-18 05:34:39 +000081
82 public Set<Dependency<?>> getDependencies() {
limpbizkita843a952009-04-08 22:24:55 +000083 return Dependency.forInjectionPoints(new ImmutableSet.Builder<InjectionPoint>()
84 .add(getConstructor())
85 .addAll(getInjectableMembers())
86 .build());
limpbizkit03b81a62009-03-18 05:34:39 +000087 }
88
89 public void applyTo(Binder binder) {
90 throw new UnsupportedOperationException("This element represents a synthetic binding.");
91 }
92
93 @Override public String toString() {
94 return new ToStringBuilder(ConstructorBinding.class)
95 .add("key", getKey())
96 .add("source", getSource())
97 .add("scope", getScoping())
98 .toString();
99 }
100
101 private static class Factory<T> implements InternalFactory<T> {
102 private ConstructorInjector<T> constructorInjector;
103
104 @SuppressWarnings("unchecked")
105 public T get(Errors errors, InternalContext context, Dependency<?> dependency)
106 throws ErrorsException {
107 checkState(constructorInjector != null, "Constructor not ready");
108
109 // This may not actually be safe because it could return a super type of T (if that's all the
110 // client needs), but it should be OK in practice thanks to the wonders of erasure.
111 return (T) constructorInjector.construct(errors, context, dependency.getKey().getRawType());
112 }
113 }
114}