Revision: 1376
Author: sberlin
Date: Thu Nov 18 18:33:32 2010
Log: issue 436 -- add Injector.getTypeConverters, and expand
ConvertedConstantBinding to expose the TypeConverter for it. patch
graciously provided by Stuart, thanks!
http://code.google.com/p/google-guice/source/detail?r=1376
Deleted:
/trunk/core/src/com/google/inject/internal/MatcherAndConverter.java
Modified:
/trunk/core/src/com/google/inject/Injector.java
/trunk/core/src/com/google/inject/internal/Errors.java
/trunk/core/src/com/google/inject/internal/InheritingState.java
/trunk/core/src/com/google/inject/internal/InjectorImpl.java
/trunk/core/src/com/google/inject/internal/InternalInjectorCreator.java
/trunk/core/src/com/google/inject/internal/State.java
/trunk/core/src/com/google/inject/internal/TypeConverterBindingProcessor.java
/trunk/core/src/com/google/inject/spi/ConvertedConstantBinding.java
/trunk/core/src/com/google/inject/spi/TypeConverterBinding.java
/trunk/core/test/com/google/inject/TypeConversionTest.java
=======================================
--- /trunk/core/src/com/google/inject/internal/MatcherAndConverter.java Sat
Jul 3 08:51:31 2010
+++ /dev/null
@@ -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.util.Preconditions.checkNotNull;
-import com.google.inject.matcher.Matcher;
-import com.google.inject.spi.TypeConverter;
-
-/**
- * @author [email protected] (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 + ")";
- }
-}
=======================================
--- /trunk/core/src/com/google/inject/Injector.java Sat Jul 3 08:42:51 2010
+++ /trunk/core/src/com/google/inject/Injector.java Thu Nov 18 18:33:32 2010
@@ -19,6 +19,9 @@
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+
+import com.google.inject.spi.TypeConverterBinding;
/**
* Builds the graphs of objects that make up your application. The
injector tracks the dependencies
@@ -247,4 +250,14 @@
* @since 3.0
*/
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.
+ *
+ * @since 3.0
+ */
+ Set<TypeConverterBinding> getTypeConverterBindings();
+}
=======================================
--- /trunk/core/src/com/google/inject/internal/Errors.java Sat Oct 30
07:15:06 2010
+++ /trunk/core/src/com/google/inject/internal/Errors.java Thu Nov 18
18:33:32 2010
@@ -34,6 +34,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;
@@ -52,7 +53,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
@@ -136,30 +137,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"
@@ -609,7 +610,7 @@
}
boolean appliesTo(Object o) {
- return type.isAssignableFrom(o.getClass());
+ return o != null && type.isAssignableFrom(o.getClass());
}
String convert(Object o) {
=======================================
--- /trunk/core/src/com/google/inject/internal/InheritingState.java Sat
Jul 3 08:51:31 2010
+++ /trunk/core/src/com/google/inject/internal/InheritingState.java Thu Nov
18 18:33:32 2010
@@ -24,6 +24,7 @@
import com.google.inject.internal.util.Lists;
import com.google.inject.internal.util.Maps;
import static com.google.inject.internal.util.Preconditions.checkNotNull;
+import com.google.inject.spi.TypeConverterBinding;
import com.google.inject.spi.TypeListenerBinding;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
@@ -43,7 +44,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]*/
@@ -83,19 +84,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);
=======================================
--- /trunk/core/src/com/google/inject/internal/InjectorImpl.java Fri Oct 29
05:00:27 2010
+++ /trunk/core/src/com/google/inject/internal/InjectorImpl.java Thu Nov 18
18:33:32 2010
@@ -46,6 +46,7 @@
import com.google.inject.spi.HasDependencies;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.ProviderBinding;
+import com.google.inject.spi.TypeConverterBinding;
import com.google.inject.util.Providers;
import java.lang.annotation.Annotation;
import java.lang.reflect.GenericArrayType;
@@ -377,9 +378,9 @@
// Find a matching type converter.
TypeLiteral<T> type = key.getTypeLiteral();
- MatcherAndConverter matchingConverter =
state.getConverter(stringValue, type, errors, source);
-
- if (matchingConverter == null) {
+ TypeConverterBinding typeConverterBinding =
state.getConverter(stringValue, type, errors, source);
+
+ if (typeConverterBinding == null) {
// No converter can handle the given type.
return null;
}
@@ -387,23 +388,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();
}
}
@@ -413,14 +415,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() {
@@ -434,6 +439,10 @@
public T getValue() {
return value;
}
+
+ public TypeConverterBinding getTypeConverterBinding() {
+ return typeConverterBinding;
+ }
public Key<String> getSourceKey() {
return originalBinding.getKey();
@@ -829,7 +838,11 @@
}
public Map<Class<? extends Annotation>, Scope> getScopeBindings() {
- return state.getScopes();
+ return ImmutableMap.copyOf(state.getScopes());
+ }
+
+ public Set<TypeConverterBinding> getTypeConverterBindings() {
+ return ImmutableSet.copyOf(state.getConvertersThisLevel());
}
private static class BindingsMultimap {
=======================================
--- /trunk/core/src/com/google/inject/internal/InternalInjectorCreator.java
Tue Nov 2 14:23:30 2010
+++ /trunk/core/src/com/google/inject/internal/InternalInjectorCreator.java
Thu Nov 18 18:33:32 2010
@@ -29,10 +29,12 @@
import com.google.inject.internal.util.Iterables;
import com.google.inject.internal.util.Stopwatch;
import com.google.inject.spi.Dependency;
+import com.google.inject.spi.TypeConverterBinding;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Builds a tree of injectors. This is a primary injector, plus child
injectors needed for each
@@ -286,6 +288,9 @@
public Map<Class<? extends Annotation>, Scope> getScopeBindings() {
return delegateInjector.getScopeBindings();
}
+ public Set<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");
=======================================
--- /trunk/core/src/com/google/inject/internal/State.java Sat Jul 3
08:51:31 2010
+++ /trunk/core/src/com/google/inject/internal/State.java Thu Nov 18
18:33:32 2010
@@ -23,6 +23,7 @@
import com.google.inject.internal.util.ImmutableList;
import com.google.inject.internal.util.ImmutableMap;
import com.google.inject.internal.util.ImmutableSet;
+import com.google.inject.spi.TypeConverterBinding;
import com.google.inject.spi.TypeListenerBinding;
import java.lang.annotation.Annotation;
import java.util.List;
@@ -61,17 +62,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]*/
@@ -123,14 +124,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);
=======================================
---
/trunk/core/src/com/google/inject/internal/TypeConverterBindingProcessor.java
Sat Jul 3 08:51:31 2010
+++
/trunk/core/src/com/google/inject/internal/TypeConverterBindingProcessor.java
Thu Nov 18 18:33:32 2010
@@ -161,12 +161,12 @@
private void internalConvertToTypes(Matcher<? super TypeLiteral<?>>
typeMatcher,
TypeConverter converter) {
injector.state.addConverter(
- new MatcherAndConverter(typeMatcher, converter,
SourceProvider.UNKNOWN_SOURCE));
+ new TypeConverterBinding(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 TypeConverterBinding(
+ command.getSource(), command.getTypeMatcher(),
command.getTypeConverter()));
return true;
}
}
=======================================
--- /trunk/core/src/com/google/inject/spi/ConvertedConstantBinding.java Fri
Dec 26 18:57:04 2008
+++ /trunk/core/src/com/google/inject/spi/ConvertedConstantBinding.java Thu
Nov 18 18:33:32 2010
@@ -34,6 +34,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)}.
=======================================
--- /trunk/core/src/com/google/inject/spi/TypeConverterBinding.java Sat
Jul 3 08:51:31 2010
+++ /trunk/core/src/com/google/inject/spi/TypeConverterBinding.java Thu Nov
18 18:33:32 2010
@@ -36,7 +36,7 @@
private final Matcher<? super TypeLiteral<?>> typeMatcher;
private final TypeConverter typeConverter;
- TypeConverterBinding(Object source, Matcher<? super TypeLiteral<?>>
typeMatcher,
+ public TypeConverterBinding(Object source, Matcher<? super
TypeLiteral<?>> typeMatcher,
TypeConverter typeConverter) {
this.source = checkNotNull(source, "source");
this.typeMatcher = checkNotNull(typeMatcher, "typeMatcher");
@@ -62,4 +62,9 @@
public void applyTo(Binder binder) {
binder.withSource(getSource()).convertToTypes(typeMatcher,
typeConverter);
}
-}
+
+ @Override public String toString() {
+ return typeConverter + " which matches " + typeMatcher
+ + " (bound at " + source + ")";
+ }
+}
=======================================
--- /trunk/core/test/com/google/inject/TypeConversionTest.java Sat Jul 3
08:51:31 2010
+++ /trunk/core/test/com/google/inject/TypeConversionTest.java Thu Nov 18
18:33:32 2010
@@ -19,7 +19,9 @@
import static com.google.inject.Asserts.assertContains;
import com.google.inject.internal.util.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 +211,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 {
--
You received this message because you are subscribed to the Google Groups
"google-guice-dev" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-guice-dev?hl=en.