Skip to content

Instantly share code, notes, and snippets.

@gissuebot
Created July 7, 2014 17:52
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/ca5305c2abdfb62a3c09 to your computer and use it in GitHub Desktop.
Save gissuebot/ca5305c2abdfb62a3c09 to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 22, comment 1
Index: C:/Documents and Settings/Michael.Barker/src/guice/test/com/google/inject/CustomConverterTest.java
===================================================================
--- C:/Documents and Settings/Michael.Barker/src/guice/test/com/google/inject/CustomConverterTest.java (revision 0)
+++ C:/Documents and Settings/Michael.Barker/src/guice/test/com/google/inject/CustomConverterTest.java (revision 0)
@@ -0,0 +1,111 @@
+package com.google.inject;
+
+import java.lang.reflect.Member;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+public class CustomConverterTest extends TestCase {
+
+ public void testURLConversion() {
+ Injector inj = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(Foo.class).to(FooImpl.class);
+ binder().bindConverter(URL.class, new URLConverter());
+ Map<String,String> config = new HashMap<String,String>();
+ config.put("bar", "http://www.google.com");
+ Names.bindProperties(binder(), config);
+ }
+ });
+ Foo f = inj.getInstance(Foo.class);
+ URL url = f.getBar();
+ assertEquals("www.google.com", url.getHost());
+ }
+
+ public void testArrayConversion() {
+ Injector inj = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(Tee.class).to(TeeImpl.class);
+ binder().bindConverter(String[].class, new ArrayConverter());
+ Map<String,String> config = new HashMap<String,String>();
+ config.put("bar", "this,is,a,test,string");
+ Names.bindProperties(binder(), config);
+ }
+ });
+ Tee tee = inj.getInstance(Tee.class);
+ String[] bar = tee.getBar();
+ assertTrue(Arrays.equals(bar,
+ new String[] { "this","is","a","test","string" }));
+ }
+
+ public void testURLConversionError() {
+ try {
+ Injector inj = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(Foo.class).to(FooImpl.class);
+ binder().bindConverter(URL.class, new URLConverter());
+ Map<String,String> config = new HashMap<String,String>();
+ config.put("bar", "www.google.com");
+ Names.bindProperties(binder(), config);
+ }
+ });
+ inj.getInstance(Foo.class);
+ assertFalse("CreationException should be thrown", true);
+ } catch (CreationException e) {
+ }
+ }
+
+ static class URLConverter implements Converter<URL> {
+
+ public URL convert(Member member, Key<URL> key, String value)
+ throws ConstantConversionException {
+ try {
+ return new URL(value);
+ } catch (MalformedURLException e) {
+ throw new ConstantConversionException(member, key, value, e);
+ }
+ }
+
+ }
+
+ static class ArrayConverter implements Converter<String[]> {
+
+ public String[] convert(Member member, Key<String[]> key, String value)
+ throws ConstantConversionException {
+ return value.split(",");
+ }
+
+ }
+
+ static interface Foo {
+ URL getBar();
+ }
+
+ static class FooImpl implements Foo {
+ @Inject @Named("bar") URL bar;
+
+ public URL getBar() {
+ return bar;
+ }
+ }
+
+ static interface Tee {
+ String[] getBar();
+ }
+
+ static class TeeImpl implements Tee {
+ @Inject @Named("bar") String[] bar;
+
+ public String[] getBar() {
+ return bar;
+ }
+ }
+
+}
Index: C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/Binder.java
===================================================================
--- C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/Binder.java (revision 326)
+++ C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/Binder.java (working copy)
@@ -16,13 +16,15 @@
package com.google.inject;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
import com.google.inject.binder.AnnotatedBindingBuilder;
import com.google.inject.binder.AnnotatedConstantBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.matcher.Matcher;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import org.aopalliance.intercept.MethodInterceptor;
/**
* Collects configuration information (primarily <i>bindings</i>) which will be
@@ -201,6 +203,11 @@
* Binds a scope to an annotation.
*/
void bindScope(Class<? extends Annotation> annotationType, Scope scope);
+
+ /**
+ * Binds a convertor to a class.
+ */
+ <T> void bindConverter(Class<T> type, Converter<? extends T> customConverter);
/**
* See the EDSL examples at {@link Binder}.
Index: C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/Converter.java
===================================================================
--- C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/Converter.java (revision 0)
+++ C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/Converter.java (revision 0)
@@ -0,0 +1,15 @@
+package com.google.inject;
+
+import java.lang.reflect.Member;
+
+/**
+ * Converts a {@code String} to another type.
+ */
+public interface Converter<T> {
+
+ /**
+ * Converts {@code String} value.
+ */
+ T convert(Member member, Key<T> key, String value)
+ throws ConstantConversionException;
+}
\ No newline at end of file
Index: C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/InjectorImpl.java
===================================================================
--- C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/InjectorImpl.java (revision 326)
+++ C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/InjectorImpl.java (working copy)
@@ -86,16 +86,20 @@
final Map<Key<?>, BindingImpl<?>> bindings;
final BindingsMultimap bindingsMultimap = new BindingsMultimap();
final Map<Class<? extends Annotation>, Scope> scopes;
+ final Map<Class<?>, Converter<?>> customConverters;
ErrorHandler errorHandler = new InvalidErrorHandler();
Object defaultSource = SourceProviders.UNKNOWN_SOURCE;
+
InjectorImpl(ConstructionProxyFactory constructionProxyFactory,
Map<Key<?>, BindingImpl<?>> bindings,
- Map<Class<? extends Annotation>, Scope> scopes) {
+ Map<Class<? extends Annotation>, Scope> scopes,
+ Map<Class<?>, Converter<?>> customConverters) {
this.constructionProxyFactory = constructionProxyFactory;
this.bindings = bindings;
this.scopes = scopes;
+ this.customConverters = customConverters;
}
/**
@@ -220,6 +224,18 @@
// TODO: Generalize everything below here and enable users to plug in
// their own converters.
+ // Do we need a custom conversion?
+ Converter<T> custom = (Converter<T>) customConverters.get(rawType);
+ if (custom != null) {
+ try {
+ T t = custom.convert(member, key, value);
+ return new ConstantFactory<T>(t);
+ }
+ catch (ConstantConversionException e) {
+ return handleConstantConversionError(
+ member, stringBinding, rawType, e);
+ }
+ }
// Do we need a primitive?
Converter<T> converter = (Converter<T>) PRIMITIVE_CONVERTERS.get(rawType);
@@ -861,18 +877,6 @@
}
}
- /**
- * Converts a {@code String} to another type.
- */
- interface Converter<T> {
-
- /**
- * Converts {@code String} value.
- */
- T convert(Member member, Key<T> key, String value)
- throws ConstantConversionException;
- }
-
Map<Class<?>, InternalFactory<?>> implicitBindings =
new HashMap<Class<?>, InternalFactory<?>>();
Index: C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/BinderImpl.java
===================================================================
--- C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/BinderImpl.java (revision 326)
+++ C:/Documents and Settings/Michael.Barker/src/guice/src/com/google/inject/BinderImpl.java (working copy)
@@ -61,6 +61,8 @@
= new ArrayList<ConstantBindingBuilderImpl>();
final Map<Class<? extends Annotation>, Scope> scopes =
new HashMap<Class<? extends Annotation>, Scope>();
+ final Map<Class<?>, Converter<?>> customConverters =
+ new HashMap<Class<?>, Converter<?>>();
final List<StaticInjection> staticInjections
= new ArrayList<StaticInjection>();
@@ -168,6 +170,13 @@
scopes.put(annotationType, nonNull(scope, "scope"));
}
}
+
+ /* (non-Javadoc)
+ * @see com.google.inject.Binder#bindConverter(java.lang.Class, com.google.inject.Converter)
+ */
+ public <T> void bindConverter(Class<T> type, Converter<? extends T> customConverter) {
+ customConverters.put(type, customConverter);
+ }
public <T> BindingBuilderImpl<T> bind(Key<T> key) {
BindingBuilderImpl<T> builder =
@@ -245,7 +254,7 @@
Map<Key<?>, BindingImpl<?>> bindings = new HashMap<Key<?>, BindingImpl<?>>();
injector = new InjectorImpl(
- proxyFactoryBuilder.create(), bindings, scopes);
+ proxyFactoryBuilder.create(), bindings, scopes, customConverters);
injector.setErrorHandler(configurationErrorHandler);
createConstantBindings();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment