Skip to content

Commit

Permalink
Big change - changing BinderImpl to use commands/
Browse files Browse the repository at this point in the history
git-svn-id: https://google-guice.googlecode.com/svn/trunk@420 d779f126-a31b-0410-b53b-1d3aecad763e
  • Loading branch information
limpbizkit committed Mar 8, 2008
1 parent 947540b commit 3d58d6b
Show file tree
Hide file tree
Showing 54 changed files with 2,045 additions and 943 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.google.inject.commands;

import static com.google.inject.internal.Objects.nonNull;

import java.util.Arrays;
import static java.util.Collections.unmodifiableList;
import java.util.List;
Expand All @@ -26,14 +28,20 @@
* @author [email protected] (Jesse Wilson)
*/
public final class AddMessageErrorCommand implements Command {
private final Object source;
private final String message;
private final List<Object> arguments;

AddMessageErrorCommand(String message, Object[] arguments) {
this.message = message;
AddMessageErrorCommand(Object source, String message, Object[] arguments) {
this.source = nonNull(source, "source");
this.message = nonNull(message, "message");
this.arguments = unmodifiableList(Arrays.asList(arguments.clone()));
}

public Object getSource() {
return source;
}

public <T> T acceptVisitor(Visitor<T> visitor) {
return visitor.visitAddMessageError(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,24 @@

package com.google.inject.commands;

import static com.google.inject.internal.Objects.nonNull;

/**
* Immutable snapshot of a request to add a throwable message.
*
* @author [email protected] (Jesse Wilson)
*/
public final class AddThrowableErrorCommand implements Command {
private final Object source;
private final Throwable throwable;

AddThrowableErrorCommand(Throwable throwable) {
this.throwable = throwable;
AddThrowableErrorCommand(Object source, Throwable throwable) {
this.source = nonNull(source, "source");
this.throwable = nonNull(throwable, "throwable");
}

public Object getSource() {
return source;
}

public <T> T acceptVisitor(Visitor<T> visitor) {
Expand Down
149 changes: 110 additions & 39 deletions extensions/commands/src/com/google/inject/commands/BindCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@

package com.google.inject.commands;

import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.Scope;
import com.google.inject.TypeLiteral;
import com.google.inject.*;
import com.google.inject.spi.SourceProviders;
import com.google.inject.binder.AnnotatedBindingBuilder;
import com.google.inject.binder.ConstantBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
Expand All @@ -34,14 +32,44 @@
* @author [email protected] (Jesse Wilson)
*/
public final class BindCommand<T> implements Command {

static {
SourceProviders.skip(BindCommand.BindingBuilder.class);
}

private static final BindTarget<Object> EMPTY_BIND_TARGET = new AbstractTarget<Object>() {
public ScopedBindingBuilder execute(LinkedBindingBuilder<Object> linkedBindingBuilder) {
return linkedBindingBuilder;
}
public <V> V acceptVisitor(Visitor<Object, V> visitor) {
return visitor.visitUntargetted();
}
};

private static final BindScoping EMPTY_SCOPING = new AbstractScoping() {
public void execute(ScopedBindingBuilder scopedBindingBuilder) {
// do nothing
}
public <V> V acceptVisitor(Visitor<V> visitor) {
return visitor.visitNoScoping();
}
};

private final Object source;
private Key<T> key;
private BindTarget<T> bindTarget;
private BindScoping bindScoping;
@SuppressWarnings({"unchecked"})
private BindTarget<T> bindTarget = (BindTarget<T>) EMPTY_BIND_TARGET;
private BindScoping bindScoping = EMPTY_SCOPING;

BindCommand(Key<T> key) {
BindCommand(Object source, Key<T> key) {
this.source = nonNull(source, "source");
this.key = nonNull(key, "key");
}

public Object getSource() {
return source;
}

public <V> V acceptVisitor(Visitor<V> visitor) {
return visitor.visitBind(this);
}
Expand All @@ -60,52 +88,57 @@ public BindScoping getScoping() {

@Override public String toString() {
return "bind " + key
+ (bindTarget == null ? "" : (" to " + bindTarget))
+ (bindScoping == null ? "" : (" in " + bindScoping));
+ (bindTarget == EMPTY_BIND_TARGET ? "" : (" to " + bindTarget))
+ (bindScoping == EMPTY_SCOPING ? "" : (" in " + bindScoping));
}

private static abstract class AbstractTarget<T> implements BindTarget<T> {
public void execute(ConstantBindingBuilder builder) {
throw new UnsupportedOperationException();
}
public T get(T defaultValue) {
return defaultValue;
public T get() {
return null;
}
public Key<? extends Provider<? extends T>> getProviderKey(
Key<Provider<? extends T>> defaultValue) {
return defaultValue;
public Key<? extends Provider<? extends T>> getProviderKey() {
return null;
}
public Provider<? extends T> getProvider(Provider<? extends T> defaultValue) {
return defaultValue;
public Provider<? extends T> getProvider() {
return null;
}
public Key<? extends T> getKey(Key<? extends T> defaultValue) {
return defaultValue;
public Key<? extends T> getKey() {
return null;
}
}

private static abstract class AbstractScoping implements BindScoping {
public boolean isEagerSingleton() {
return false;
}
public Scope getScope(Scope defaultValue) {
return defaultValue;
public Scope getScope() {
return null;
}
public Class<? extends Annotation> getScopeAnnotation(
Class<? extends Annotation> defaultValue) {
return defaultValue;
public Class<? extends Annotation> getScopeAnnotation() {
return null;
}
}

BindingBuilder bindingBuilder() {
return new BindingBuilder();
BindingBuilder bindingBuilder(Binder binder) {
return new BindingBuilder(binder);
}

/**
* Package-private write access to the internal state of this command.
*/
class BindingBuilder implements AnnotatedBindingBuilder<T> {
private final Binder binder;

BindingBuilder(Binder binder) {
this.binder = binder;
}

public LinkedBindingBuilder<T> annotatedWith(
Class<? extends Annotation> annotationType) {
nonNull(annotationType, "annotationType");
assertNotAnnotated();
key = Key.get(key.getTypeLiteral(), annotationType);
return this;
Expand Down Expand Up @@ -134,9 +167,12 @@ public ScopedBindingBuilder to(final Key<? extends T> targetKey) {
public ScopedBindingBuilder execute(LinkedBindingBuilder<T> linkedBindingBuilder) {
return linkedBindingBuilder.to(targetKey);
}
@Override public Key<? extends T> getKey(Key<? extends T> defaultValue) {
@Override public Key<? extends T> getKey() {
return targetKey;
}
public <V> V acceptVisitor(Visitor<T, V> visitor) {
return visitor.visitToKey(targetKey);
}
@Override public String toString() {
return String.valueOf(targetKey);
}
Expand All @@ -145,16 +181,23 @@ public ScopedBindingBuilder execute(LinkedBindingBuilder<T> linkedBindingBuilder
}

public void toInstance(final T instance) {
nonNull(instance, "instance"); // might someday want to tolerate null here
// might someday want to tolerate null here, probably by setting up a
// Provider<null> rather than trying to distinguish between null and
// not set
nonNull(instance, "instance");

assertNoTarget();
bindTarget = new AbstractTarget<T>() {
public ScopedBindingBuilder execute(LinkedBindingBuilder<T> linkedBindingBuilder) {
linkedBindingBuilder.toInstance(instance);
return null;
}
@Override public T get(T defaultValue) {
@Override public T get() {
return instance;
}
public <V> V acceptVisitor(Visitor<T, V> visitor) {
return visitor.visitToInstance(instance);
}
@Override public String toString() {
return "instance " + instance;
}
Expand All @@ -168,9 +211,12 @@ public ScopedBindingBuilder toProvider(final Provider<? extends T> provider) {
public ScopedBindingBuilder execute(LinkedBindingBuilder<T> linkedBindingBuilder) {
return linkedBindingBuilder.toProvider(provider);
}
@Override public Provider<? extends T> getProvider(Provider<? extends T> defaultValue) {
@Override public Provider<? extends T> getProvider() {
return provider;
}
public <V> V acceptVisitor(Visitor<T, V> visitor) {
return visitor.visitToProvider(provider);
}
@Override public String toString() {
return "provider " + provider;
}
Expand All @@ -191,10 +237,12 @@ public ScopedBindingBuilder toProvider(
public ScopedBindingBuilder execute(LinkedBindingBuilder<T> linkedBindingBuilder) {
return linkedBindingBuilder.toProvider(providerKey);
}
@Override public Key<? extends Provider<? extends T>> getProviderKey(
Key<Provider<? extends T>> defaultValue) {
@Override public Key<? extends Provider<? extends T>> getProviderKey() {
return providerKey;
}
public <V> V acceptVisitor(Visitor<T, V> visitor) {
return visitor.visitToProviderKey(providerKey);
}
@Override public String toString() {
return "provider " + providerKey;
}
Expand All @@ -210,10 +258,12 @@ public void in(final Class<? extends Annotation> scopeAnnotation) {
public void execute(ScopedBindingBuilder scopedBindingBuilder) {
scopedBindingBuilder.in(scopeAnnotation);
}
@Override public Class<? extends Annotation> getScopeAnnotation(
Class<? extends Annotation> defaultValue) {
@Override public Class<? extends Annotation> getScopeAnnotation() {
return scopeAnnotation;
}
public <V> V acceptVisitor(Visitor<V> visitor) {
return visitor.visitScopeAnnotation(scopeAnnotation);
}
@Override public String toString() {
return scopeAnnotation.getName();
}
Expand All @@ -224,12 +274,16 @@ public void in(final Scope scope) {
nonNull(scope, "scope");
assertNoScope();
bindScoping = new AbstractScoping() {

public void execute(ScopedBindingBuilder scopedBindingBuilder) {
scopedBindingBuilder.in(scope);
}
@Override public Scope getScope(Scope defaultValue) {
@Override public Scope getScope() {
return scope;
}
public <V> V acceptVisitor(Visitor<V> visitor) {
return visitor.visitScope(scope);
}
@Override public String toString() {
return String.valueOf(scope);
}
Expand All @@ -245,27 +299,44 @@ public void execute(ScopedBindingBuilder scopedBindingBuilder) {
@Override public boolean isEagerSingleton() {
return true;
}
public <V> V acceptVisitor(Visitor<V> visitor) {
return visitor.visitEagerSingleton();
}
@Override public String toString() {
return "eager singleton";
}
};
}

static final String IMPLEMENTATION_ALREADY_SET
= "Implementation is set more than once.";
static final String SINGLE_INSTANCE_AND_SCOPE = "Setting the scope is not"
+ " permitted when binding to a single instance.";
static final String SCOPE_ALREADY_SET = "Scope is set more than once.";
static final String ANNOTATION_ALREADY_SPECIFIED = "More than one annotation"
+ " is specified for this binding.";

private void assertNoTarget() {
if (bindTarget != null) {
throw new IllegalStateException("Already targetted to " + bindTarget);
if (bindTarget != EMPTY_BIND_TARGET) {
binder.addError(IMPLEMENTATION_ALREADY_SET);
}
}

private void assertNotAnnotated() {
if (BindCommand.this.key.getAnnotationType() != null) {
throw new IllegalStateException("Already annotated with " + key.getAnnotationType());
binder.addError(ANNOTATION_ALREADY_SPECIFIED);
}
}

private void assertNoScope() {
if (bindScoping != null) {
throw new IllegalStateException("Already scoped by " + bindScoping);
// Scoping isn't allowed when we have only one instance.
if (bindTarget.get() != null) {
binder.addError(SINGLE_INSTANCE_AND_SCOPE);
return;
}

if (bindScoping != EMPTY_SCOPING) {
binder.addError(SCOPE_ALREADY_SET);
}
}
}
Expand Down
Loading

0 comments on commit 3d58d6b

Please sign in to comment.