Automated g4 rollback of changelist 50265868.
*** Reason for rollback ***
Multibound set is no longer Serializable, whoops.
*** Original change description ***
Give more information when duplicate elements are found in a multibound set.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=50268399
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java b/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
index 35161c4..59fe82d 100644
--- a/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
+++ b/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
@@ -16,21 +16,16 @@
package com.google.inject.multibindings;
-import static com.google.common.base.Predicates.equalTo;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.inject.multibindings.Element.Type.MULTIBINDER;
import static com.google.inject.name.Names.named;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collections;
-import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
-import java.util.Map;
import java.util.Set;
-import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
@@ -328,16 +323,14 @@
public Set<T> get() {
checkConfiguration(isInitialized(), "Multibinder is not initialized");
- Map<T, Binding<T>> result = new LinkedHashMap<T, Binding<T>>();
+ Set<T> result = new LinkedHashSet<T>();
for (Binding<T> binding : bindings) {
final T newValue = binding.getProvider().get();
checkConfiguration(newValue != null, "Set injection failed due to null element");
- Binding<T> duplicateBinding = result.put(newValue, binding);
- if (!permitDuplicates && duplicateBinding != null) {
- throw newDuplicateValuesException(result, binding, newValue, duplicateBinding);
- }
+ checkConfiguration(result.add(newValue) || permitDuplicates,
+ "Set injection failed due to duplicated element \"%s\"", newValue);
}
- return Collections.unmodifiableSet(result.keySet());
+ return Collections.unmodifiableSet(result);
}
@SuppressWarnings("unchecked")
@@ -454,35 +447,6 @@
throw new ConfigurationException(ImmutableSet.of(new Message(Errors.format(format, args))));
}
- private static <T> ConfigurationException newDuplicateValuesException(
- Map<T, Binding<T>> existingBindings,
- Binding<T> binding,
- final T newValue,
- Binding<T> duplicateBinding) {
- T oldValue = getOnlyElement(filter(existingBindings.keySet(), equalTo(newValue)));
- String oldString = oldValue.toString();
- String newString = newValue.toString();
- if (Objects.equal(oldString, newString)) {
- // When the value strings match, just show the source of the bindings
- return new ConfigurationException(ImmutableSet.of(new Message(Errors.format(
- "Set injection failed due to duplicated element \"%s\""
- + "\n Bound at %s\n Bound at %s",
- newValue,
- duplicateBinding.getSource(),
- binding.getSource()))));
- } else {
- // When the value strings don't match, include them both as they may be useful for debugging
- return new ConfigurationException(ImmutableSet.of(new Message(Errors.format(
- "Set injection failed due to multiple elements comparing equal:"
- + "\n \"%s\"\n bound at %s"
- + "\n \"%s\"\n bound at %s",
- oldValue,
- duplicateBinding.getSource(),
- newValue,
- binding.getSource()))));
- }
- }
-
static <T> T checkNotNull(T reference, String name) {
if (reference != null) {
return reference;
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
index 82cc0fe..4e1d3f1 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
@@ -48,6 +48,7 @@
import com.google.inject.spi.LinkedKeyBinding;
import com.google.inject.util.Modules;
import com.google.inject.util.Providers;
+import com.google.inject.util.Types;
import junit.framework.TestCase;
@@ -274,94 +275,28 @@
}
public void testMultibinderSetForbidsDuplicateElements() {
- Module module1 = new AbstractModule() {
+ Module module = new AbstractModule() {
protected void configure() {
final Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
multibinder.addBinding().toInstance("A");
- }
- };
- Module module2 = new AbstractModule() {
- protected void configure() {
- final Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
multibinder.addBinding().toInstance("A");
}
};
- Injector injector = Guice.createInjector(module1, module2);
+ Injector injector = Guice.createInjector(module);
try {
injector.getInstance(Key.get(setOfString));
fail();
- } catch (ProvisionException expected) {
+ } catch(ProvisionException expected) {
assertContains(expected.getMessage(),
- "1) Set injection failed due to duplicated element \"A\"",
- "Bound at " + module1.getClass().getName(),
- "Bound at " + module2.getClass().getName());
+ "1) Set injection failed due to duplicated element \"A\"");
}
// But we can still visit the module!
- assertSetVisitor(Key.get(setOfString), stringType, setOf(module1, module2), MODULE, false, 0,
+ assertSetVisitor(Key.get(setOfString), stringType, setOf(module), MODULE, false, 0,
instance("A"), instance("A"));
}
- public void testMultibinderSetShowsBothElementsIfToStringDifferent() {
- // A simple example of a type whose toString returns more information than its equals method
- // considers.
- class ValueType {
- int a;
- int b;
- ValueType(int a, int b) {
- this.a = a;
- this.b = b;
- }
- @Override
- public boolean equals(Object obj) {
- return (obj instanceof ValueType) && (((ValueType) obj).a == a);
- }
- @Override
- public int hashCode() {
- return a;
- }
- @Override
- public String toString() {
- return String.format("ValueType(%d,%d)", a, b);
- }
- }
-
- Module module1 = new AbstractModule() {
- protected void configure() {
- final Multibinder<ValueType> multibinder =
- Multibinder.newSetBinder(binder(), ValueType.class);
- multibinder.addBinding().toInstance(new ValueType(1, 2));
- }
- };
- Module module2 = new AbstractModule() {
- protected void configure() {
- final Multibinder<ValueType> multibinder =
- Multibinder.newSetBinder(binder(), ValueType.class);
- multibinder.addBinding().toInstance(new ValueType(1, 3));
- }
- };
- Injector injector = Guice.createInjector(module1, module2);
-
- TypeLiteral<ValueType> valueType = TypeLiteral.get(ValueType.class);
- TypeLiteral<Set<ValueType>> setOfValueType = new TypeLiteral<Set<ValueType>>() {};
- try {
- injector.getInstance(Key.get(setOfValueType));
- fail();
- } catch (ProvisionException expected) {
- assertContains(expected.getMessage(),
- "1) Set injection failed due to multiple elements comparing equal:",
- "\"ValueType(1,2)\"",
- "bound at " + module1.getClass().getName(),
- "\"ValueType(1,3)\"",
- "bound at " + module2.getClass().getName());
- }
-
- // But we can still visit the module!
- assertSetVisitor(Key.get(setOfValueType), valueType, setOf(module1, module2), MODULE, false, 0,
- instance(new ValueType(1, 2)), instance(new ValueType(1, 3)));
- }
-
public void testMultibinderSetPermitDuplicateElements() {
Module ab = new AbstractModule() {
protected void configure() {