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.

Reply via email to