1/**
2 * Copyright (C) 2008 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.internal;
18
19import com.google.common.collect.ImmutableSet;
20import com.google.inject.Binder;
21import com.google.inject.Key;
22import com.google.inject.binder.AnnotatedConstantBindingBuilder;
23import com.google.inject.binder.ConstantBindingBuilder;
24import com.google.inject.spi.Element;
25import com.google.inject.spi.InjectionPoint;
26
27import java.lang.annotation.Annotation;
28import java.util.List;
29
30/**
31 * Bind a constant.
32 *
33 * @author jessewilson@google.com (Jesse Wilson)
34 */
35public final class ConstantBindingBuilderImpl<T>
36    extends AbstractBindingBuilder<T>
37    implements AnnotatedConstantBindingBuilder, ConstantBindingBuilder {
38
39  @SuppressWarnings("unchecked") // constant bindings start out with T unknown
40  public ConstantBindingBuilderImpl(Binder binder, List<Element> elements, Object source) {
41    super(binder, elements, source, (Key<T>) NULL_KEY);
42  }
43
44  public ConstantBindingBuilder annotatedWith(Class<? extends Annotation> annotationType) {
45    annotatedWithInternal(annotationType);
46    return this;
47  }
48
49  public ConstantBindingBuilder annotatedWith(Annotation annotation) {
50    annotatedWithInternal(annotation);
51    return this;
52  }
53
54  public void to(final String value) {
55    toConstant(String.class, value);
56  }
57
58  public void to(final int value) {
59    toConstant(Integer.class, value);
60  }
61
62  public void to(final long value) {
63    toConstant(Long.class, value);
64  }
65
66  public void to(final boolean value) {
67    toConstant(Boolean.class, value);
68  }
69
70  public void to(final double value) {
71    toConstant(Double.class, value);
72  }
73
74  public void to(final float value) {
75    toConstant(Float.class, value);
76  }
77
78  public void to(final short value) {
79    toConstant(Short.class, value);
80  }
81
82  public void to(final char value) {
83    toConstant(Character.class, value);
84  }
85
86  public void to(final byte value) {
87    toConstant(Byte.class, value);
88  }
89
90  public void to(final Class<?> value) {
91    toConstant(Class.class, value);
92  }
93
94  public <E extends Enum<E>> void to(final E value) {
95    toConstant(value.getDeclaringClass(), value);
96  }
97
98  private void toConstant(Class<?> type, Object instance) {
99    // this type will define T, so these assignments are safe
100    @SuppressWarnings("unchecked")
101    Class<T> typeAsClassT = (Class<T>) type;
102    @SuppressWarnings("unchecked")
103    T instanceAsT = (T) instance;
104
105    if (keyTypeIsSet()) {
106      binder.addError(CONSTANT_VALUE_ALREADY_SET);
107      return;
108    }
109
110    BindingImpl<T> base = getBinding();
111    Key<T> key;
112    if (base.getKey().getAnnotation() != null) {
113      key = Key.get(typeAsClassT, base.getKey().getAnnotation());
114    } else if (base.getKey().getAnnotationType() != null) {
115      key = Key.get(typeAsClassT, base.getKey().getAnnotationType());
116    } else {
117      key = Key.get(typeAsClassT);
118    }
119
120    if (instanceAsT == null) {
121      binder.addError(BINDING_TO_NULL);
122    }
123
124    setBinding(new InstanceBindingImpl<T>(
125        base.getSource(), key, base.getScoping(), ImmutableSet.<InjectionPoint>of(), instanceAsT));
126  }
127
128  @Override public String toString() {
129    return "ConstantBindingBuilder";
130  }
131}