Author: netdpb
Date: Wed Jul  8 12:49:54 2009
New Revision: 1042

Modified:
     
trunk/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java

Log:
Cleaned up MapBinder code, including using ImmutableSet and ImmutableMap  
where appropriate. Moved multimap binding into a nested module class.

Modified:  
trunk/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
==============================================================================
---  
trunk/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
        
(original)
+++  
trunk/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
        
Wed Jul  8 12:49:54 2009
@@ -22,9 +22,9 @@
  import com.google.inject.Key;
  import com.google.inject.Module;
  import com.google.inject.Provider;
-import com.google.inject.ProvisionException;
  import com.google.inject.TypeLiteral;
  import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.internal.ImmutableMap;
  import com.google.inject.internal.ImmutableSet;
  import com.google.inject.multibindings.Multibinder.RealMultibinder;
  import static  
com.google.inject.multibindings.Multibinder.checkConfiguration;
@@ -33,12 +33,10 @@
  import com.google.inject.spi.Dependency;
  import com.google.inject.spi.ProviderWithDependencies;
  import com.google.inject.util.Types;
-import static com.google.inject.util.Types.newParameterizedType;
  import static com.google.inject.util.Types.newParameterizedTypeWithOwner;
  import java.lang.annotation.Annotation;
  import java.util.Collections;
  import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
  import java.util.Map;
  import java.util.Map.Entry;
  import java.util.Set;
@@ -187,15 +185,14 @@
    private static <K, V> TypeLiteral<Map<K, Provider<V>>> mapOfProviderOf(
        TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
      return (TypeLiteral<Map<K, Provider<V>>>) TypeLiteral.get(
-        Types.mapOf(keyType.getType(),  
newParameterizedType(Provider.class, valueType.getType())));
+        Types.mapOf(keyType.getType(),  
Types.providerOf(valueType.getType())));
    }

    @SuppressWarnings("unchecked") // a provider map <K, Set<V>> is safely a  
Map<K, Set<Provider<V>>>
    private static <K, V> TypeLiteral<Map<K, Set<Provider<V>>>>  
mapOfSetOfProviderOf(
        TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
      return (TypeLiteral<Map<K, Set<Provider<V>>>>) TypeLiteral.get(
-        Types.mapOf(keyType.getType(),
-            Types.setOf(newParameterizedType(Provider.class,  
valueType.getType()))));
+        Types.mapOf(keyType.getType(),  
Types.setOf(Types.providerOf(valueType.getType()))));
    }

    @SuppressWarnings("unchecked") // a provider entry <K, V> is safely a  
Map.Entry<K, Provider<V>>
@@ -218,14 +215,12 @@

    /**
     * Configures the {...@code MapBinder} to handle duplicate entries.
-   * <ul>
-   * <li>When multiple equal keys are bound, the value that gets included  
in the map is
-   * arbitrary.</li>
-   * <li>In addition to the {...@code Map<K, V>} and {...@code Map<K,  
Provider<V>>}
+   * <p>When multiple equal keys are bound, the value that gets included  
in the map is
+   * arbitrary.
+   * <p>In addition to the {...@code Map<K, V>} and {...@code Map<K,  
Provider<V>>}
     * maps that are normally bound, a {...@code Map<K, Set<V>>} and
     * {...@code Map<K, Set<Provider<V>>>} are <em>also</em> bound, which  
contain
-   * all values bound to each key.</li>
-   * </ul>
+   * all values bound to each key.
     * <p>
     * When multiple modules contribute elements to the map, this  
configuration
     * option impacts all of them.
@@ -298,6 +293,8 @@
      @Override
      public MapBinder<K, V> permitDuplicates() {
        entrySetBinder.permitDuplicates();
+      binder.install(new MultimapBinder<K, V>(
+          multimapKey, providerMultimapKey, entrySetBinder.getSetKey()));
        return this;
      }

@@ -339,7 +336,7 @@
                  "Map injection failed due to duplicated key \"%s\"",  
entry.getKey());
            }

-          providerMap = Collections.unmodifiableMap(providerMapMutable);
+          providerMap = ImmutableMap.copyOf(providerMapMutable);
          }

          public Map<K, Provider<V>> get() {
@@ -369,80 +366,111 @@
            return dependencies;
          }
        });
+    }
+
+    private boolean isInitialized() {
+      return binder == null;
+    }

-      // Binds a Map<K, Set<Provider<V>>> from a collection of  
Map<Entry<K, Provider<V>> if
-      // permitDuplicates was called.
-      binder.bind(providerMultimapKey).toProvider(
-          new ProviderWithDependencies<Map<K, Set<Provider<V>>>>() {
-            private Map<K, Set<Provider<V>>> providerMultimap;
-
-            @SuppressWarnings("unused")
-            @Inject void initialize(Injector injector) {
-              if (entrySetBinder.permitsDuplicates(injector)) {
-                Map<K, Set<Provider<V>>> providerMultimapMutable = new  
LinkedHashMap<K, Set<Provider<V>>>();
+    @Override public boolean equals(Object o) {
+      return o instanceof RealMapBinder
+          && ((RealMapBinder<?, ?>) o).mapKey.equals(mapKey);
+    }
+
+    @Override public int hashCode() {
+      return mapKey.hashCode();
+    }
+
+    /**
+     * Binds {...@code Map<K, Set<V>>} and {...@code Map<K, Set<Provider<V>>>}.
+     */
+    private static final class MultimapBinder<K, V> implements Module {
+
+      private final Key<Map<K, Set<V>>> multimapKey;
+      private final Key<Map<K, Set<Provider<V>>>> providerMultimapKey;
+      private final Key<Set<Entry<K,Provider<V>>>> entrySetKey;
+
+      public MultimapBinder(
+          Key<Map<K, Set<V>>> multimapKey,
+          Key<Map<K, Set<Provider<V>>>> providerMultimapKey,
+          Key<Set<Entry<K,Provider<V>>>> entrySetKey) {
+        this.multimapKey = multimapKey;
+        this.providerMultimapKey = providerMultimapKey;
+        this.entrySetKey = entrySetKey;
+      }
+
+      @Override
+      public void configure(Binder binder) {
+        final ImmutableSet<Dependency<?>> dependencies
+            = ImmutableSet.<Dependency<?>>of(Dependency.get(entrySetKey));
+
+        final Provider<Set<Entry<K, Provider<V>>>> entrySetProvider =
+            binder.getProvider(entrySetKey);
+        // Binds a Map<K, Set<Provider<V>>> from a collection of  
Map<Entry<K, Provider<V>> if
+        // permitDuplicates was called.
+        binder.bind(providerMultimapKey).toProvider(
+            new ProviderWithDependencies<Map<K, Set<Provider<V>>>>() {
+              private Map<K, Set<Provider<V>>> providerMultimap;
+
+              @SuppressWarnings("unused")
+              @Inject void initialize(Injector injector) {
+                Map<K, ImmutableSet.Builder<Provider<V>>>  
providerMultimapMutable =
+                    new LinkedHashMap<K,  
ImmutableSet.Builder<Provider<V>>>();
                  for (Entry<K, Provider<V>> entry : entrySetProvider.get())  
{
                    if  
(!providerMultimapMutable.containsKey(entry.getKey())) {
-                    providerMultimapMutable.put(entry.getKey(), new  
LinkedHashSet<Provider<V>>());
+                    providerMultimapMutable.put(
+                        entry.getKey(),  
ImmutableSet.<Provider<V>>builder());
                    }
                     
providerMultimapMutable.get(entry.getKey()).add(entry.getValue());
                  }

-                for (Entry<K, Set<Provider<V>>> entry :  
providerMultimapMutable.entrySet()) {
-                   
entry.setValue(Collections.unmodifiableSet(entry.getValue()));
+                ImmutableMap.Builder<K, Set<Provider<V>>>  
providerMultimapBuilder =
+                    ImmutableMap.builder();
+                for (Entry<K, ImmutableSet.Builder<Provider<V>>> entry
+                    : providerMultimapMutable.entrySet()) {
+                  providerMultimapBuilder.put(entry.getKey(),  
entry.getValue().build());
                  }
-                providerMultimap =  
Collections.unmodifiableMap(providerMultimapMutable);
+                providerMultimap = providerMultimapBuilder.build();
                }
-            }

-            public Map<K, Set<Provider<V>>> get() {
-              if (providerMultimap == null) {
-                throw new ProvisionException("no binding for " +  
providerMultimapKey
-                    + " because permitDuplicates was never called");
+              @Override
+              public Map<K, Set<Provider<V>>> get() {
+                return providerMultimap;
                }
-              return providerMultimap;
-            }

-            public Set<Dependency<?>> getDependencies() {
-              return dependencies;
-            }
-          });
+              @Override
+              public Set<Dependency<?>> getDependencies() {
+                return dependencies;
+              }
+            });

-      final Provider<Map<K, Set<Provider<V>>>> multimapProvider =
-          binder.getProvider(providerMultimapKey);
-      binder.bind(multimapKey).toProvider(new  
ProviderWithDependencies<Map<K, Set<V>>>() {
-        public Map<K, Set<V>> get() {
-          Map<K,Set<V>> multimap = new LinkedHashMap<K, Set<V>>();
-          for (Entry<K, Set<Provider<V>>> entry :  
multimapProvider.get().entrySet()) {
-            K key = entry.getKey();
-            Set<V> values = new LinkedHashSet<V>();
-            for (Provider<V> valueProvider : entry.getValue()) {
-              V value = valueProvider.get();
-              checkConfiguration(value != null,
-                  "Multimap injection failed due to null value for key  
\"%s\"", key);
-              values.add(value);
+        final Provider<Map<K, Set<Provider<V>>>> multimapProvider =
+            binder.getProvider(providerMultimapKey);
+        binder.bind(multimapKey).toProvider(new  
ProviderWithDependencies<Map<K, Set<V>>>() {
+
+          @Override
+          public Map<K, Set<V>> get() {
+            ImmutableMap.Builder<K, Set<V>> multimapBuilder =  
ImmutableMap.builder();
+            for (Entry<K, Set<Provider<V>>> entry :  
multimapProvider.get().entrySet()) {
+              K key = entry.getKey();
+              ImmutableSet.Builder<V> valuesBuilder =  
ImmutableSet.builder();
+              for (Provider<V> valueProvider : entry.getValue()) {
+                V value = valueProvider.get();
+                checkConfiguration(value != null,
+                    "Multimap injection failed due to null value for key  
\"%s\"", key);
+                valuesBuilder.add(value);
+              }
+              multimapBuilder.put(key, valuesBuilder.build());
              }
-            multimap.put(key, Collections.unmodifiableSet(values));
+            return multimapBuilder.build();
            }
-          return Collections.unmodifiableMap(multimap);
-        }

-        public Set<Dependency<?>> getDependencies() {
-          return dependencies;
-        }
-      });
-    }
-
-    private boolean isInitialized() {
-      return binder == null;
-    }
-
-    @Override public boolean equals(Object o) {
-      return o instanceof RealMapBinder
-          && ((RealMapBinder<?, ?>) o).mapKey.equals(mapKey);
-    }
-
-    @Override public int hashCode() {
-      return mapKey.hashCode();
+          @Override
+          public Set<Dependency<?>> getDependencies() {
+            return dependencies;
+          }
+        });
+      }
      }

      private static final class MapEntry<K, V> implements Map.Entry<K, V> {

--~--~---------~--~----~------------~-------~--~----~
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