mirror of https://github.com/apache/druid.git
Conditional multi bind
Usage example: ConditionalMultibind.create(props, binder, Animal.class) .conditionBinder("animal.type", Predicates.equalTo("cat"), Cat.class) .conditionBinder("animal.type", Predicates.equalTo("dog"), Dog.class); At binding time, this will check the value set for property "animal.type" in props. If the value is "cat", it will add a binding to Cat.class. If the value is "dog", it will add a binding to Dog.class. At ingestion time, you will get the items that satisfy their corresponding predicates by calling injector.getInstance(Key.get(new TypeLiteral<Set<Animal>>(){}))
This commit is contained in:
parent
56343c6cdc
commit
62edbab434
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets licenses this file
|
||||
* to you 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 io.druid.guice;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Provides the ability to conditionally bind an item to a set. The condition is based on the value set in the
|
||||
* runtime.properties.
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* ConditionalMultibind.create(props, binder, Animal.class)
|
||||
* .addConditionBinding("animal.type", Predicates.equalTo("cat"), Cat.class)
|
||||
* .addConditionBinding("animal.type", Predicates.equalTo("dog"), Dog.class);
|
||||
*
|
||||
* At binding time, this will check the value set for property "animal.type" in props. If the value is "cat", it will
|
||||
* add a binding to Cat.class. If the value is "dog", it will add a binding to Dog.class.
|
||||
*
|
||||
* At injection time, you will get the items that satisfy their corresponding predicates by calling
|
||||
* injector.getInstance(Key.get(new TypeLiteral<Set<Animal>>(){}))
|
||||
*/
|
||||
public class ConditionalMultibind<T>
|
||||
{
|
||||
|
||||
/**
|
||||
* Create a ConditionalMultibind that resolves items to be added to the set at "binding" time.
|
||||
*
|
||||
* @param properties the runtime properties.
|
||||
* @param binder the binder for the injector that is being configured.
|
||||
* @param type the type that will be injected.
|
||||
* @param <T> interface type.
|
||||
*
|
||||
* @return An instance of ConditionalMultibind that can be used to add conditional bindings.
|
||||
*/
|
||||
public static <T> ConditionalMultibind<T> create(Properties properties, Binder binder, Class<T> type)
|
||||
{
|
||||
return new ConditionalMultibind<T>(properties, Multibinder.<T>newSetBinder(binder, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ConditionalMultibind that resolves items to be added to the set at "binding" time.
|
||||
*
|
||||
* @param properties the runtime properties.
|
||||
* @param binder the binder for the injector that is being configured.
|
||||
* @param type the type that will be injected.
|
||||
* @param <T> interface type.
|
||||
* @param annotationType the binding annotation.
|
||||
*
|
||||
* @return An instance of ConditionalMultibind that can be used to add conditional bindings.
|
||||
*/
|
||||
public static <T> ConditionalMultibind<T> create(
|
||||
Properties properties,
|
||||
Binder binder,
|
||||
Class<T> type,
|
||||
Class<? extends Annotation> annotationType
|
||||
)
|
||||
{
|
||||
return new ConditionalMultibind<T>(properties, Multibinder.<T>newSetBinder(binder, type, annotationType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ConditionalMultibind that resolves items to be added to the set at "binding" time.
|
||||
*
|
||||
* @param properties the runtime properties.
|
||||
* @param binder the binder for the injector that is being configured.
|
||||
* @param type the type that will be injected.
|
||||
* @param <T> interface type.
|
||||
*
|
||||
* @return An instance of ConditionalMultibind that can be used to add conditional bindings.
|
||||
*/
|
||||
public static <T> ConditionalMultibind<T> create(Properties properties, Binder binder, TypeLiteral<T> type)
|
||||
{
|
||||
return new ConditionalMultibind<T>(properties, Multibinder.<T>newSetBinder(binder, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ConditionalMultibind that resolves items to be added to the set at "binding" time.
|
||||
*
|
||||
* @param properties the runtime properties.
|
||||
* @param binder the binder for the injector that is being configured.
|
||||
* @param type the type that will be injected.
|
||||
* @param <T> interface type.
|
||||
* @param annotationType the binding annotation.
|
||||
*
|
||||
* @return An instance of ConditionalMultibind that can be used to add conditional bindings.
|
||||
*/
|
||||
public static <T> ConditionalMultibind<T> create(
|
||||
Properties properties,
|
||||
Binder binder,
|
||||
TypeLiteral<T> type,
|
||||
Class<? extends Annotation> annotationType
|
||||
)
|
||||
{
|
||||
return new ConditionalMultibind<T>(properties, Multibinder.<T>newSetBinder(binder, type, annotationType));
|
||||
}
|
||||
|
||||
|
||||
private final Properties properties;
|
||||
private final Multibinder<T> multibinder;
|
||||
|
||||
public ConditionalMultibind(Properties properties, Multibinder<T> multibinder)
|
||||
{
|
||||
this.properties = properties;
|
||||
this.multibinder = multibinder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally bind target to the set.
|
||||
*
|
||||
* @param target the target class to which it adds a binding.
|
||||
*
|
||||
* @return self to support a continuous syntax for adding more conditional bindings.
|
||||
*/
|
||||
public ConditionalMultibind<T> addBinding(Class<? extends T> target)
|
||||
{
|
||||
multibinder.addBinding().to(target);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally bind target to the set.
|
||||
*
|
||||
* @param target the target instance to which it adds a binding.
|
||||
*
|
||||
* @return self to support a continuous syntax for adding more conditional bindings.
|
||||
*/
|
||||
public ConditionalMultibind<T> addBinding(T target)
|
||||
{
|
||||
multibinder.addBinding().toInstance(target);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally bind target to the set.
|
||||
*
|
||||
* @param target the target type to which it adds a binding.
|
||||
*
|
||||
* @return self to support a continuous syntax for adding more conditional bindings.
|
||||
*/
|
||||
public ConditionalMultibind<T> addBinding(TypeLiteral<T> target)
|
||||
{
|
||||
multibinder.addBinding().to(target);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditionally bind target to the set. If "condition" returns true, add a binding to "target".
|
||||
*
|
||||
* @param property the property to inspect on
|
||||
* @param condition the predicate used to verify whether to add a binding to "target"
|
||||
* @param target the target class to which it adds a binding.
|
||||
*
|
||||
* @return self to support a continuous syntax for adding more conditional bindings.
|
||||
*/
|
||||
public ConditionalMultibind<T> addConditionBinding(
|
||||
String property,
|
||||
Predicate<String> condition,
|
||||
Class<? extends T> target
|
||||
)
|
||||
{
|
||||
final String value = properties.getProperty(property);
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
if (condition.apply(value)) {
|
||||
multibinder.addBinding().to(target);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditionally bind target to the set. If "condition" returns true, add a binding to "target".
|
||||
*
|
||||
* @param property the property to inspect on
|
||||
* @param condition the predicate used to verify whether to add a binding to "target"
|
||||
* @param target the target instance to which it adds a binding.
|
||||
*
|
||||
* @return self to support a continuous syntax for adding more conditional bindings.
|
||||
*/
|
||||
public ConditionalMultibind<T> addConditionBinding(
|
||||
String property,
|
||||
Predicate<String> condition,
|
||||
T target
|
||||
)
|
||||
{
|
||||
final String value = properties.getProperty(property);
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
if (condition.apply(value)) {
|
||||
multibinder.addBinding().toInstance(target);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditionally bind target to the set. If "condition" returns true, add a binding to "target".
|
||||
*
|
||||
* @param property the property to inspect on
|
||||
* @param condition the predicate used to verify whether to add a binding to "target"
|
||||
* @param target the target type to which it adds a binding.
|
||||
*
|
||||
* @return self to support a continuous syntax for adding more conditional bindings.
|
||||
*/
|
||||
public ConditionalMultibind<T> addConditionBinding(
|
||||
String property,
|
||||
Predicate<String> condition,
|
||||
TypeLiteral<T> target
|
||||
)
|
||||
{
|
||||
final String value = properties.getProperty(property);
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
if (condition.apply(value)) {
|
||||
multibinder.addBinding().to(target);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,477 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets licenses this file
|
||||
* to you 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 io.druid.guice;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.BindingAnnotation;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ConditionalMultibindTest
|
||||
{
|
||||
|
||||
private static final String ANIMAL_TYPE = "animal.type";
|
||||
|
||||
private Properties props;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
props = new Properties();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiConditionalBind_cat()
|
||||
{
|
||||
props.setProperty("animal.type", "cat");
|
||||
|
||||
Injector injector = Guice.createInjector(new Module()
|
||||
{
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
ConditionalMultibind.create(props, binder, Animal.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("cat"), Cat.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("dog"), Dog.class);
|
||||
}
|
||||
});
|
||||
|
||||
Set<Animal> animalSet = injector.getInstance(Key.get(new TypeLiteral<Set<Animal>>()
|
||||
{
|
||||
}));
|
||||
|
||||
Assert.assertEquals(1, animalSet.size());
|
||||
Assert.assertEquals(animalSet, ImmutableSet.<Animal>of(new Cat()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiConditionalBind_cat_dog()
|
||||
{
|
||||
props.setProperty("animal.type", "pets");
|
||||
|
||||
Injector injector = Guice.createInjector(new Module()
|
||||
{
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
ConditionalMultibind.create(props, binder, Animal.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Cat.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Dog.class);
|
||||
}
|
||||
});
|
||||
|
||||
Set<Animal> animalSet = injector.getInstance(Key.get(new TypeLiteral<Set<Animal>>()
|
||||
{
|
||||
}));
|
||||
|
||||
Assert.assertEquals(2, animalSet.size());
|
||||
Assert.assertEquals(animalSet, ImmutableSet.<Animal>of(new Cat(), new Dog()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiConditionalBind_cat_dog_non_continuous_syntax()
|
||||
{
|
||||
props.setProperty("animal.type", "pets");
|
||||
|
||||
Injector injector = Guice.createInjector(new Module()
|
||||
{
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
ConditionalMultibind.create(props, binder, Animal.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Cat.class);
|
||||
|
||||
ConditionalMultibind.create(props, binder, Animal.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Dog.class);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Set<Animal> animalSet = injector.getInstance(Key.get(new TypeLiteral<Set<Animal>>()
|
||||
{
|
||||
}));
|
||||
|
||||
Assert.assertEquals(2, animalSet.size());
|
||||
Assert.assertEquals(animalSet, ImmutableSet.<Animal>of(new Cat(), new Dog()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiConditionalBind_multiple_modules()
|
||||
{
|
||||
props.setProperty("animal.type", "pets");
|
||||
|
||||
Injector injector = Guice.createInjector(
|
||||
new Module()
|
||||
{
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
ConditionalMultibind.create(props, binder, Animal.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Cat.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Dog.class);
|
||||
}
|
||||
},
|
||||
new Module()
|
||||
{
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
ConditionalMultibind.create(props, binder, Animal.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("not_match"), Tiger.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Fish.class);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Set<Animal> animalSet = injector.getInstance(Key.get(new TypeLiteral<Set<Animal>>()
|
||||
{
|
||||
}));
|
||||
|
||||
Assert.assertEquals(3, animalSet.size());
|
||||
Assert.assertEquals(animalSet, ImmutableSet.<Animal>of(new Cat(), new Dog(), new Fish()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiConditionalBind_multiple_modules_with_annotation()
|
||||
{
|
||||
props.setProperty("animal.type", "pets");
|
||||
|
||||
Injector injector = Guice.createInjector(
|
||||
new Module()
|
||||
{
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
ConditionalMultibind.create(props, binder, Animal.class, SanDiego.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Cat.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Dog.class);
|
||||
}
|
||||
},
|
||||
new Module()
|
||||
{
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
ConditionalMultibind.create(props, binder, Animal.class, SanDiego.class)
|
||||
.addBinding(new Bird())
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Tiger.class);
|
||||
|
||||
ConditionalMultibind.create(props, binder, Animal.class, SanJose.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Fish.class);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Set<Animal> animalSet_1 = injector.getInstance(Key.get(new TypeLiteral<Set<Animal>>()
|
||||
{
|
||||
}, SanDiego.class));
|
||||
Assert.assertEquals(4, animalSet_1.size());
|
||||
Assert.assertEquals(animalSet_1, ImmutableSet.<Animal>of(new Bird(), new Cat(), new Dog(), new Tiger()));
|
||||
|
||||
Set<Animal> animalSet_2 = injector.getInstance(Key.get(new TypeLiteral<Set<Animal>>()
|
||||
{
|
||||
}, SanJose.class));
|
||||
Assert.assertEquals(1, animalSet_2.size());
|
||||
Assert.assertEquals(animalSet_2, ImmutableSet.<Animal>of(new Fish()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiConditionalBind_inject()
|
||||
{
|
||||
props.setProperty("animal.type", "pets");
|
||||
|
||||
Injector injector = Guice.createInjector(
|
||||
new Module()
|
||||
{
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
ConditionalMultibind.create(props, binder, Animal.class)
|
||||
.addBinding(Bird.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Cat.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Dog.class);
|
||||
}
|
||||
},
|
||||
new Module()
|
||||
{
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
ConditionalMultibind.create(props, binder, Animal.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("not_match"), Tiger.class)
|
||||
.addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), Fish.class);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
PetShotAvails shop = new PetShotAvails();
|
||||
injector.injectMembers(shop);
|
||||
|
||||
Assert.assertEquals(4, shop.animals.size());
|
||||
Assert.assertEquals(shop.animals, ImmutableSet.<Animal>of(new Bird(), new Cat(), new Dog(), new Fish()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiConditionalBind_typeLiteral()
|
||||
{
|
||||
props.setProperty("animal.type", "pets");
|
||||
|
||||
final Set<Animal> set1 = ImmutableSet.<Animal>of(new Dog(), new Tiger());
|
||||
final Set<Animal> set2 = ImmutableSet.<Animal>of(new Cat(), new Fish());
|
||||
final Set<Animal> set3 = ImmutableSet.<Animal>of(new Cat());
|
||||
final Set<Animal> union = new HashSet<>();
|
||||
union.addAll(set1);
|
||||
union.addAll(set2);
|
||||
|
||||
final Zoo<Animal> zoo1 = new Zoo<>(set1);
|
||||
final Zoo<Animal> zoo2 = new Zoo<>();
|
||||
|
||||
Injector injector = Guice.createInjector(
|
||||
new Module()
|
||||
{
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
ConditionalMultibind.create(props, binder,
|
||||
new TypeLiteral<Set<Animal>>()
|
||||
{
|
||||
}
|
||||
).addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), set1
|
||||
).addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), set2);
|
||||
|
||||
ConditionalMultibind.create(props, binder,
|
||||
new TypeLiteral<Zoo<Animal>>()
|
||||
{
|
||||
}
|
||||
).addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), zoo1);
|
||||
}
|
||||
},
|
||||
new Module()
|
||||
{
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
ConditionalMultibind.create(props, binder,
|
||||
new TypeLiteral<Set<Animal>>()
|
||||
{
|
||||
}
|
||||
).addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), set3);
|
||||
|
||||
ConditionalMultibind.create(props, binder,
|
||||
new TypeLiteral<Set<Animal>>()
|
||||
{
|
||||
},
|
||||
SanDiego.class
|
||||
).addConditionBinding(ANIMAL_TYPE, Predicates.equalTo("pets"), union);
|
||||
|
||||
ConditionalMultibind.create(props, binder,
|
||||
new TypeLiteral<Zoo<Animal>>()
|
||||
{
|
||||
}
|
||||
).addBinding(new TypeLiteral<Zoo<Animal>>()
|
||||
{
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Set<Set<Animal>> actualAnimalSet = injector.getInstance(Key.get(new TypeLiteral<Set<Set<Animal>>>()
|
||||
{
|
||||
}));
|
||||
Assert.assertEquals(3, actualAnimalSet.size());
|
||||
Assert.assertEquals(ImmutableSet.of(set1, set2, set3), actualAnimalSet);
|
||||
|
||||
actualAnimalSet = injector.getInstance(Key.get(new TypeLiteral<Set<Set<Animal>>>()
|
||||
{
|
||||
}, SanDiego.class));
|
||||
Assert.assertEquals(1, actualAnimalSet.size());
|
||||
Assert.assertEquals(ImmutableSet.of(union), actualAnimalSet);
|
||||
|
||||
final Set<Zoo<Animal>> actualZooSet = injector.getInstance(Key.get(new TypeLiteral<Set<Zoo<Animal>>>()
|
||||
{
|
||||
}));
|
||||
Assert.assertEquals(2, actualZooSet.size());
|
||||
Assert.assertEquals(ImmutableSet.of(zoo1, zoo2), actualZooSet);
|
||||
}
|
||||
|
||||
static abstract class Animal
|
||||
{
|
||||
private final String type;
|
||||
|
||||
Animal(String type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Animal{" +
|
||||
"type='" + type + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Animal animal = (Animal) o;
|
||||
|
||||
return type != null ? type.equals(animal.type) : animal.type == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return type != null ? type.hashCode() : 0;
|
||||
}
|
||||
}
|
||||
|
||||
static class PetShotAvails
|
||||
{
|
||||
@Inject
|
||||
Set<Animal> animals;
|
||||
}
|
||||
|
||||
static class Dog extends Animal
|
||||
{
|
||||
Dog()
|
||||
{
|
||||
super("dog");
|
||||
}
|
||||
}
|
||||
|
||||
static class Cat extends Animal
|
||||
{
|
||||
Cat()
|
||||
{
|
||||
super("cat");
|
||||
}
|
||||
}
|
||||
|
||||
static class Fish extends Animal
|
||||
{
|
||||
Fish()
|
||||
{
|
||||
super("fish");
|
||||
}
|
||||
}
|
||||
|
||||
static class Tiger extends Animal
|
||||
{
|
||||
Tiger()
|
||||
{
|
||||
super("tiger");
|
||||
}
|
||||
}
|
||||
|
||||
static class Bird extends Animal
|
||||
{
|
||||
Bird()
|
||||
{
|
||||
super("bird");
|
||||
}
|
||||
}
|
||||
|
||||
static class Zoo<T>
|
||||
{
|
||||
Set<T> animals;
|
||||
|
||||
public Zoo()
|
||||
{
|
||||
animals = new HashSet<>();
|
||||
}
|
||||
|
||||
public Zoo(Set<T> animals)
|
||||
{
|
||||
this.animals = animals;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Zoo<?> zoo = (Zoo<?>) o;
|
||||
|
||||
return animals != null ? animals.equals(zoo.animals) : zoo.animals == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return animals != null ? animals.hashCode() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Zoo{" +
|
||||
"animals=" + animals +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@BindingAnnotation
|
||||
@interface SanDiego
|
||||
{
|
||||
}
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@BindingAnnotation
|
||||
@interface SanJose
|
||||
{
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue