blob: 5f6c3e7469d46392e4ae4c5e5c39e38a51e8ecb3 [file] [log] [blame]
/**
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.inject.visitable;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.binder.AnnotatedConstantBindingBuilder;
import com.google.inject.binder.ConstantBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.binder.ScopedBindingBuilder;
import com.google.inject.internal.Objects;
import java.lang.annotation.Annotation;
/**
* Immutable snapshot of a request to bind a constant.
*
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class BindConstantCommand implements Command {
private BindingAnnotation bindingAnnotation;
private ConstantTarget<?> target;
BindConstantCommand() {
// hide public constructor
}
public <T> T acceptVisitor(BinderVisitor<T> visitor) {
return visitor.visitConstantBinding(this);
}
public Target<?> getTarget() {
return target;
}
public <T> Key<T> getKey() {
return bindingAnnotation.getKey();
}
/**
* Target API for bindConstant().
*/
private static abstract class ConstantTarget<T> implements Target<T> {
/**
* Returns the type of constant, such as {@code int.class} or
* {@code Enum.class}.
*/
abstract Class getType();
public boolean hasInstance() {
return true;
}
public ScopedBindingBuilder execute(LinkedBindingBuilder linkedBindingBuilder) {
throw new UnsupportedOperationException();
}
public Provider<? extends T> getProvider(Provider<? extends T> defaultValue) {
return defaultValue;
}
public Key<? extends Provider<? extends T>> getProviderKey(Key<Provider<? extends T>> defaultValue) {
return defaultValue;
}
public Key<? extends T> getKey(Key<? extends T> defaultValue) {
return defaultValue;
}
}
/**
* Internal annotation API.
*/
private abstract class BindingAnnotation {
abstract ConstantBindingBuilder execute(AnnotatedConstantBindingBuilder builder);
abstract <T> Key<T> getKey();
}
BindingBuilder bindingBuilder() {
return new BindingBuilder();
}
/**
* Package-private write access to the internal state of this command.
*/
class BindingBuilder
implements AnnotatedConstantBindingBuilder, ConstantBindingBuilder {
private void assertNoBindingAnnotation() {
if (target != null) {
throw new IllegalStateException("Already annotated with " + bindingAnnotation);
}
}
private void assertNoTarget() {
if (target != null) {
throw new IllegalStateException("Already targetted to " + target);
}
}
public ConstantBindingBuilder annotatedWith(final Class<? extends Annotation> annotationType) {
assertNoBindingAnnotation();
bindingAnnotation = new BindingAnnotation() {
public ConstantBindingBuilder execute(AnnotatedConstantBindingBuilder builder) {
return builder.annotatedWith(annotationType);
}
public <T> Key<T> getKey() {
return Key.get((Class<T>) target.getType(), annotationType);
}
};
return this;
}
public ConstantBindingBuilder annotatedWith(final Annotation annotation) {
assertNoBindingAnnotation();
bindingAnnotation = new BindingAnnotation() {
public ConstantBindingBuilder execute(AnnotatedConstantBindingBuilder builder) {
return builder.annotatedWith(annotation);
}
public <T> Key<T> getKey() {
return Key.get((Class<T>) target.getType(), annotation);
}
};
return this;
}
public void to(final String value) {
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
public Object get(Object defaultValue) {
return value;
}
public Class getType() {
return String.class;
}
@Override public String toString() {
return value;
}
};
}
public void to(final int value) {
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
public Object get(Object defaultValue) {
return value;
}
public Class getType() {
return Integer.class;
}
@Override public String toString() {
return String.valueOf(value);
}
};
}
public void to(final long value) {
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
public Object get(Object defaultValue) {
return value;
}
public Class getType() {
return Long.class;
}
@Override public String toString() {
return String.valueOf(value);
}
};
}
public void to(final boolean value) {
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
public Object get(Object defaultValue) {
return value;
}
public Class getType() {
return Boolean.class;
}
@Override public String toString() {
return String.valueOf(value);
}
};
}
public void to(final double value) {
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
public Object get(Object defaultValue) {
return value;
}
public Class getType() {
return Double.class;
}
@Override public String toString() {
return String.valueOf(value);
}
};
}
public void to(final float value) {
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
public Object get(Object defaultValue) {
return value;
}
public Class getType() {
return Float.class;
}
@Override public String toString() {
return String.valueOf(value);
}
};
}
public void to(final short value) {
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
public Object get(Object defaultValue) {
return value;
}
public Class getType() {
return Short.class;
}
@Override public String toString() {
return String.valueOf(value);
}
};
}
public void to(final char value) {
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
public Object get(Object defaultValue) {
return value;
}
public Class getType() {
return Character.class;
}
@Override public String toString() {
return String.valueOf(value);
}
};
}
public void to(final Class<?> value) {
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
public Object get(Object defaultValue) {
return value;
}
public Class getType() {
return Class.class;
}
@Override public String toString() {
return String.valueOf(value);
}
};
}
public <E extends Enum<E>> void to(final E value) {
Objects.nonNull(value, "value");
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
public Object get(Object defaultValue) {
return value;
}
public Class getType() {
return value.getDeclaringClass();
}
@Override public String toString() {
return String.valueOf(value);
}
};
}
}
}