Skip to content

Instantly share code, notes, and snippets.

@gissuebot
Created July 7, 2014 18:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gissuebot/13d674d53bc88f90f173 to your computer and use it in GitHub Desktop.
Save gissuebot/13d674d53bc88f90f173 to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 436, comment 13
Index: test/com/google/inject/TypeConversionTest.java
===================================================================
--- test/com/google/inject/TypeConversionTest.java (revision 1119)
+++ test/com/google/inject/TypeConversionTest.java (working copy)
@@ -19,7 +19,10 @@
import static com.google.inject.Asserts.assertContains;
import com.google.inject.internal.Iterables;
import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.ConvertedConstantBinding;
import com.google.inject.spi.TypeConverter;
+import com.google.inject.spi.TypeConverterBinding;
+
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.util.Date;
@@ -209,6 +212,14 @@
});
assertSame(result, injector.getInstance(DateHolder.class).date);
+
+ Binding<Date> binding = injector.getBinding(Key.get(Date.class, NumericValue.class));
+ assertTrue(binding instanceof ConvertedConstantBinding<?>);
+
+ TypeConverterBinding converterBinding = ((ConvertedConstantBinding<?>)binding).getTypeConverterBinding();
+ assertEquals("CustomConverter", converterBinding.getTypeConverter().toString());
+
+ assertTrue(injector.getTypeConverterBindings().contains(converterBinding));
}
public void testInvalidCustomValue() throws CreationException {
Index: src/com/google/inject/spi/Elements.java
===================================================================
--- src/com/google/inject/spi/Elements.java (revision 1119)
+++ src/com/google/inject/spi/Elements.java (working copy)
@@ -37,6 +37,8 @@
import com.google.inject.internal.Errors;
import com.google.inject.internal.ImmutableList;
import com.google.inject.internal.Lists;
+import com.google.inject.internal.TypeConverterBindingImpl;
+
import static com.google.inject.internal.Preconditions.checkArgument;
import com.google.inject.internal.PrivateElementsImpl;
import com.google.inject.internal.ProviderMethodsModule;
@@ -278,7 +280,7 @@
public void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
TypeConverter converter) {
- elements.add(new TypeConverterBinding(getSource(), typeMatcher, converter));
+ elements.add(new TypeConverterBindingImpl(getSource(), typeMatcher, converter));
}
public RecordingBinder withSource(final Object source) {
Index: src/com/google/inject/spi/ConvertedConstantBinding.java
===================================================================
--- src/com/google/inject/spi/ConvertedConstantBinding.java (revision 1119)
+++ src/com/google/inject/spi/ConvertedConstantBinding.java (working copy)
@@ -35,6 +35,11 @@
T getValue();
/**
+ * Returns the type converter binding used to convert the constant.
+ */
+ TypeConverterBinding getTypeConverterBinding();
+
+ /**
* Returns the key for the source binding. That binding can e retrieved from an injector using
* {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}.
*/
Index: src/com/google/inject/spi/TypeConverterBinding.java
===================================================================
--- src/com/google/inject/spi/TypeConverterBinding.java (revision 1119)
+++ src/com/google/inject/spi/TypeConverterBinding.java (working copy)
@@ -18,7 +18,6 @@
import com.google.inject.TypeLiteral;
import com.google.inject.Binder;
-import static com.google.inject.internal.Preconditions.checkNotNull;
import com.google.inject.matcher.Matcher;
/**
@@ -31,35 +30,15 @@
* @author jessewilson@google.com (Jesse Wilson)
* @since 2.0
*/
-public final class TypeConverterBinding implements Element {
- private final Object source;
- private final Matcher<? super TypeLiteral<?>> typeMatcher;
- private final TypeConverter typeConverter;
+public interface TypeConverterBinding extends Element {
- TypeConverterBinding(Object source, Matcher<? super TypeLiteral<?>> typeMatcher,
- TypeConverter typeConverter) {
- this.source = checkNotNull(source, "source");
- this.typeMatcher = checkNotNull(typeMatcher, "typeMatcher");
- this.typeConverter = checkNotNull(typeConverter, "typeConverter");
- }
+ Object getSource();
- public Object getSource() {
- return source;
- }
+ Matcher<? super TypeLiteral<?>> getTypeMatcher();
- public Matcher<? super TypeLiteral<?>> getTypeMatcher() {
- return typeMatcher;
- }
+ TypeConverter getTypeConverter();
- public TypeConverter getTypeConverter() {
- return typeConverter;
- }
+ <T> T acceptVisitor(ElementVisitor<T> visitor);
- public <T> T acceptVisitor(ElementVisitor<T> visitor) {
- return visitor.visit(this);
- }
-
- public void applyTo(Binder binder) {
- binder.withSource(getSource()).convertToTypes(typeMatcher, typeConverter);
- }
+ void applyTo(Binder binder);
}
Index: src/com/google/inject/internal/Errors.java
===================================================================
--- src/com/google/inject/internal/Errors.java (revision 1119)
+++ src/com/google/inject/internal/Errors.java (working copy)
@@ -28,6 +28,7 @@
import com.google.inject.spi.InjectionListener;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.Message;
+import com.google.inject.spi.TypeConverterBinding;
import com.google.inject.spi.TypeListenerBinding;
import java.io.PrintWriter;
import java.io.Serializable;
@@ -46,7 +47,7 @@
/**
* A collection of error messages. If this type is passed as a method parameter, the method is
- * considered to have executed succesfully only if new errors were not added to this collection.
+ * considered to have executed successfully only if new errors were not added to this collection.
*
* <p>Errors can be chained to provide additional context. To add context, call {@link #withSource}
* to create a new Errors instance that contains additional context. All messages added to the
@@ -126,30 +127,30 @@
}
public Errors converterReturnedNull(String stringValue, Object source,
- TypeLiteral<?> type, MatcherAndConverter matchingConverter) {
+ TypeLiteral<?> type, TypeConverterBinding typeConverterBinding) {
return addMessage("Received null converting '%s' (bound at %s) to %s%n"
+ " using %s.",
- stringValue, convert(source), type, matchingConverter);
+ stringValue, convert(source), type, typeConverterBinding);
}
public Errors conversionTypeError(String stringValue, Object source, TypeLiteral<?> type,
- MatcherAndConverter matchingConverter, Object converted) {
+ TypeConverterBinding typeConverterBinding, Object converted) {
return addMessage("Type mismatch converting '%s' (bound at %s) to %s%n"
+ " using %s.%n"
+ " Converter returned %s.",
- stringValue, convert(source), type, matchingConverter, converted);
+ stringValue, convert(source), type, typeConverterBinding, converted);
}
public Errors conversionError(String stringValue, Object source,
- TypeLiteral<?> type, MatcherAndConverter matchingConverter, RuntimeException cause) {
+ TypeLiteral<?> type, TypeConverterBinding typeConverterBinding, RuntimeException cause) {
return errorInUserCode(cause, "Error converting '%s' (bound at %s) to %s%n"
+ " using %s.%n"
+ " Reason: %s",
- stringValue, convert(source), type, matchingConverter, cause);
+ stringValue, convert(source), type, typeConverterBinding, cause);
}
public Errors ambiguousTypeConversion(String stringValue, Object source, TypeLiteral<?> type,
- MatcherAndConverter a, MatcherAndConverter b) {
+ TypeConverterBinding a, TypeConverterBinding b) {
return addMessage("Multiple converters can convert '%s' (bound at %s) to %s:%n"
+ " %s and%n"
+ " %s.%n"
Index: src/com/google/inject/internal/InjectorImpl.java
===================================================================
--- src/com/google/inject/internal/InjectorImpl.java (revision 1119)
+++ src/com/google/inject/internal/InjectorImpl.java (working copy)
@@ -36,6 +36,7 @@
import com.google.inject.spi.ProviderBinding;
import com.google.inject.spi.ProviderKeyBinding;
import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.TypeConverterBinding;
import com.google.inject.util.Providers;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
@@ -284,9 +285,9 @@
// Find a matching type converter.
TypeLiteral<T> type = key.getTypeLiteral();
- MatcherAndConverter matchingConverter = state.getConverter(stringValue, type, errors, source);
+ TypeConverterBinding typeConverterBinding = state.getConverter(stringValue, type, errors, source);
- if (matchingConverter == null) {
+ if (typeConverterBinding == null) {
// No converter can handle the given type.
return null;
}
@@ -294,23 +295,24 @@
// Try to convert the string. A failed conversion results in an error.
try {
@SuppressWarnings("unchecked") // This cast is safe because we double check below.
- T converted = (T) matchingConverter.getTypeConverter().convert(stringValue, type);
+ T converted = (T) typeConverterBinding.getTypeConverter().convert(stringValue, type);
if (converted == null) {
- throw errors.converterReturnedNull(stringValue, source, type, matchingConverter)
+ throw errors.converterReturnedNull(stringValue, source, type, typeConverterBinding)
.toException();
}
if (!type.getRawType().isInstance(converted)) {
- throw errors.conversionTypeError(stringValue, source, type, matchingConverter, converted)
+ throw errors.conversionTypeError(stringValue, source, type, typeConverterBinding, converted)
.toException();
}
- return new ConvertedConstantBindingImpl<T>(this, key, converted, stringBinding);
+ return new ConvertedConstantBindingImpl<T>(this, key, converted, stringBinding,
+ typeConverterBinding);
} catch (ErrorsException e) {
throw e;
} catch (RuntimeException e) {
- throw errors.conversionError(stringValue, source, type, matchingConverter, e)
+ throw errors.conversionError(stringValue, source, type, typeConverterBinding, e)
.toException();
}
}
@@ -320,14 +322,17 @@
final T value;
final Provider<T> provider;
final Binding<String> originalBinding;
+ final TypeConverterBinding typeConverterBinding;
ConvertedConstantBindingImpl(
- InjectorImpl injector, Key<T> key, T value, Binding<String> originalBinding) {
+ InjectorImpl injector, Key<T> key, T value, Binding<String> originalBinding,
+ TypeConverterBinding typeConverterBinding) {
super(injector, key, originalBinding.getSource(),
new ConstantFactory<T>(Initializables.of(value)), Scoping.UNSCOPED);
this.value = value;
provider = Providers.of(value);
this.originalBinding = originalBinding;
+ this.typeConverterBinding = typeConverterBinding;
}
@Override public Provider<T> getProvider() {
@@ -342,6 +347,10 @@
return value;
}
+ public TypeConverterBinding getTypeConverterBinding() {
+ return typeConverterBinding;
+ }
+
public Key<String> getSourceKey() {
return originalBinding.getKey();
}
@@ -656,9 +665,13 @@
}
public Map<Class<? extends Annotation>, Scope> getScopeBindings() {
- return state.getScopes();
+ return Collections.unmodifiableMap(state.getScopes());
}
+ public List<TypeConverterBinding> getTypeConverterBindings() {
+ return Collections.unmodifiableList(state.getConvertersThisLevel());
+ }
+
private static class BindingsMultimap {
final Map<TypeLiteral<?>, List<Binding<?>>> multimap = Maps.newHashMap();
Index: src/com/google/inject/internal/MatcherAndConverter.java
===================================================================
--- src/com/google/inject/internal/MatcherAndConverter.java (revision 1119)
+++ src/com/google/inject/internal/MatcherAndConverter.java (working copy)
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2007 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.internal;
-
-import com.google.inject.TypeLiteral;
-import static com.google.inject.internal.Preconditions.checkNotNull;
-import com.google.inject.matcher.Matcher;
-import com.google.inject.spi.TypeConverter;
-
-/**
- * @author crazybob@google.com (Bob Lee)
- */
-final class MatcherAndConverter {
-
- private final Matcher<? super TypeLiteral<?>> typeMatcher;
- private final TypeConverter typeConverter;
- private final Object source;
-
- public MatcherAndConverter(Matcher<? super TypeLiteral<?>> typeMatcher,
- TypeConverter typeConverter, Object source) {
- this.typeMatcher = checkNotNull(typeMatcher, "type matcher");
- this.typeConverter = checkNotNull(typeConverter, "converter");
- this.source = source;
- }
-
- public TypeConverter getTypeConverter() {
- return typeConverter;
- }
-
- public Matcher<? super TypeLiteral<?>> getTypeMatcher() {
- return typeMatcher;
- }
-
- public Object getSource() {
- return source;
- }
-
- @Override public String toString() {
- return typeConverter + " which matches " + typeMatcher
- + " (bound at " + source + ")";
- }
-}
Index: src/com/google/inject/internal/InjectorBuilder.java
===================================================================
--- src/com/google/inject/internal/InjectorBuilder.java (revision 1119)
+++ src/com/google/inject/internal/InjectorBuilder.java (working copy)
@@ -26,6 +26,8 @@
import com.google.inject.TypeLiteral;
import com.google.inject.Scope;
import com.google.inject.spi.Dependency;
+import com.google.inject.spi.TypeConverterBinding;
+
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -271,6 +273,9 @@
public Map<Class<? extends Annotation>, Scope> getScopeBindings() {
return delegateInjector.getScopeBindings();
}
+ public List<TypeConverterBinding> getTypeConverterBindings() {
+ return delegateInjector.getTypeConverterBindings();
+ }
public <T> Provider<T> getProvider(Key<T> key) {
throw new UnsupportedOperationException(
"Injector.getProvider(Key<T>) is not supported in Stage.TOOL");
Index: src/com/google/inject/internal/TypeConverterBindingImpl.java
===================================================================
--- src/com/google/inject/internal/TypeConverterBindingImpl.java (revision 0)
+++ src/com/google/inject/internal/TypeConverterBindingImpl.java (revision 0)
@@ -0,0 +1,66 @@
+/**
+ * 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.internal;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.Binder;
+import static com.google.inject.internal.Preconditions.checkNotNull;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.spi.ElementVisitor;
+import com.google.inject.spi.TypeConverter;
+import com.google.inject.spi.TypeConverterBinding;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public final class TypeConverterBindingImpl implements TypeConverterBinding {
+ private final Object source;
+ private final Matcher<? super TypeLiteral<?>> typeMatcher;
+ private final TypeConverter typeConverter;
+
+ public TypeConverterBindingImpl(Object source, Matcher<? super TypeLiteral<?>> typeMatcher,
+ TypeConverter typeConverter) {
+ this.source = checkNotNull(source, "source");
+ this.typeMatcher = checkNotNull(typeMatcher, "typeMatcher");
+ this.typeConverter = checkNotNull(typeConverter, "typeConverter");
+ }
+
+ public Object getSource() {
+ return source;
+ }
+
+ public Matcher<? super TypeLiteral<?>> getTypeMatcher() {
+ return typeMatcher;
+ }
+
+ public TypeConverter getTypeConverter() {
+ return typeConverter;
+ }
+
+ public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+ return visitor.visit(this);
+ }
+
+ public void applyTo(Binder binder) {
+ binder.withSource(getSource()).convertToTypes(typeMatcher, typeConverter);
+ }
+
+ @Override public String toString() {
+ return typeConverter + " which matches " + typeMatcher
+ + " (bound at " + source + ")";
+ }
+}
Index: src/com/google/inject/internal/InheritingState.java
===================================================================
--- src/com/google/inject/internal/InheritingState.java (revision 1119)
+++ src/com/google/inject/internal/InheritingState.java (working copy)
@@ -21,6 +21,8 @@
import com.google.inject.Scope;
import com.google.inject.TypeLiteral;
import static com.google.inject.internal.Preconditions.checkNotNull;
+
+import com.google.inject.spi.TypeConverterBinding;
import com.google.inject.spi.TypeListenerBinding;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
@@ -40,7 +42,7 @@
private final Map<Key<?>, Binding<?>> explicitBindings
= Collections.unmodifiableMap(explicitBindingsMutable);
private final Map<Class<? extends Annotation>, Scope> scopes = Maps.newHashMap();
- private final List<MatcherAndConverter> converters = Lists.newArrayList();
+ private final List<TypeConverterBinding> converters = Lists.newArrayList();
/*if[AOP]*/
private final List<MethodAspect> methodAspects = Lists.newArrayList();
/*end[AOP]*/
@@ -80,19 +82,19 @@
scopes.put(annotationType, scope);
}
- public Iterable<MatcherAndConverter> getConvertersThisLevel() {
+ public List<TypeConverterBinding> getConvertersThisLevel() {
return converters;
}
- public void addConverter(MatcherAndConverter matcherAndConverter) {
- converters.add(matcherAndConverter);
+ public void addConverter(TypeConverterBinding typeConverterBinding) {
+ converters.add(typeConverterBinding);
}
- public MatcherAndConverter getConverter(
+ public TypeConverterBinding getConverter(
String stringValue, TypeLiteral<?> type, Errors errors, Object source) {
- MatcherAndConverter matchingConverter = null;
+ TypeConverterBinding matchingConverter = null;
for (State s = this; s != State.NONE; s = s.parent()) {
- for (MatcherAndConverter converter : s.getConvertersThisLevel()) {
+ for (TypeConverterBinding converter : s.getConvertersThisLevel()) {
if (converter.getTypeMatcher().matches(type)) {
if (matchingConverter != null) {
errors.ambiguousTypeConversion(stringValue, source, type, matchingConverter, converter);
Index: src/com/google/inject/internal/TypeConverterBindingProcessor.java
===================================================================
--- src/com/google/inject/internal/TypeConverterBindingProcessor.java (revision 1119)
+++ src/com/google/inject/internal/TypeConverterBindingProcessor.java (working copy)
@@ -159,12 +159,12 @@
private void internalConvertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
TypeConverter converter) {
injector.state.addConverter(
- new MatcherAndConverter(typeMatcher, converter, SourceProvider.UNKNOWN_SOURCE));
+ new TypeConverterBindingImpl(SourceProvider.UNKNOWN_SOURCE, typeMatcher, converter));
}
@Override public Boolean visit(TypeConverterBinding command) {
- injector.state.addConverter(new MatcherAndConverter(
- command.getTypeMatcher(), command.getTypeConverter(), command.getSource()));
+ injector.state.addConverter(new TypeConverterBindingImpl(
+ command.getSource(), command.getTypeMatcher(), command.getTypeConverter()));
return true;
}
}
Index: src/com/google/inject/internal/State.java
===================================================================
--- src/com/google/inject/internal/State.java (revision 1119)
+++ src/com/google/inject/internal/State.java (working copy)
@@ -20,6 +20,7 @@
import com.google.inject.Key;
import com.google.inject.Scope;
import com.google.inject.TypeLiteral;
+import com.google.inject.spi.TypeConverterBinding;
import com.google.inject.spi.TypeListenerBinding;
import java.lang.annotation.Annotation;
import java.util.List;
@@ -58,17 +59,17 @@
throw new UnsupportedOperationException();
}
- public void addConverter(MatcherAndConverter matcherAndConverter) {
+ public void addConverter(TypeConverterBinding typeConverterBinding) {
throw new UnsupportedOperationException();
}
- public MatcherAndConverter getConverter(String stringValue, TypeLiteral<?> type, Errors errors,
+ public TypeConverterBinding getConverter(String stringValue, TypeLiteral<?> type, Errors errors,
Object source) {
throw new UnsupportedOperationException();
}
- public Iterable<MatcherAndConverter> getConvertersThisLevel() {
- return ImmutableSet.of();
+ public List<TypeConverterBinding> getConvertersThisLevel() {
+ return ImmutableList.of();
}
/*if[AOP]*/
@@ -120,14 +121,14 @@
void putAnnotation(Class<? extends Annotation> annotationType, Scope scope);
- void addConverter(MatcherAndConverter matcherAndConverter);
+ void addConverter(TypeConverterBinding typeConverterBinding);
/** Returns the matching converter for {@code type}, or null if none match. */
- MatcherAndConverter getConverter(
+ TypeConverterBinding getConverter(
String stringValue, TypeLiteral<?> type, Errors errors, Object source);
/** Returns all converters at this level only. */
- Iterable<MatcherAndConverter> getConvertersThisLevel();
+ List<TypeConverterBinding> getConvertersThisLevel();
/*if[AOP]*/
void addMethodAspect(MethodAspect methodAspect);
Index: src/com/google/inject/Injector.java
===================================================================
--- src/com/google/inject/Injector.java (revision 1119)
+++ src/com/google/inject/Injector.java (working copy)
@@ -20,6 +20,8 @@
import java.util.List;
import java.util.Map;
+import com.google.inject.spi.TypeConverterBinding;
+
/**
* Builds the graphs of objects that make up your application. The injector tracks the dependencies
* for each type and uses bindings to inject them. This is the core of Guice, although you rarely
@@ -232,4 +234,12 @@
* <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
*/
Map<Class<? extends Annotation>, Scope> getScopeBindings();
+
+ /**
+ * Returns a list containing all type converter bindings in the injector. The returned list
+ * is immutable.
+ *
+ * <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+ */
+ List<TypeConverterBinding> getTypeConverterBindings();
}
Index: build.xml
===================================================================
--- build.xml (revision 1119)
+++ build.xml (working copy)
@@ -85,9 +85,11 @@
<pathelement location="${build.dir}/test"/>
<pathelement location="${build.dir}/dist/guice-${version}.jar"/>
<pathelement location="lib/aopalliance.jar"/>
+ <pathelement location="lib/javax.inject.jar"/>
<pathelement location="lib/build/junit.jar"/>
<pathelement location="lib/build/servlet-api-2.5.jar"/>
<pathelement location="lib/build/easymock.jar"/>
+ <pathelement location="lib/build/javax.inject-tck.jar"/>
</classpath>
<arg value="com.google.inject.AllTests"/>
<syspropertyset>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment