/* * Copyright 2010 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.gwt.inject.client.assistedinject; import com.google.gwt.core.client.GWT; import com.google.gwt.inject.client.AbstractGinModule; import com.google.gwt.inject.client.GinModules; import com.google.gwt.inject.client.Ginjector; import com.google.gwt.inject.client.binding.Color; import com.google.gwt.junit.client.GWTTestCase; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; import com.google.inject.name.Named; import java.util.Set; public class CarFactoryTest extends GWTTestCase { // FactoryProvider2 allows assisted parameters to be converted into // providers. AFAIK the new FactoryModuleBuilder doesn't allow that, nor can // I see an application. public void testAnnotatedInjectedParameters() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); CamaroFactory factory = ginjector.getCamaroFactory(); Camaro greenCamaro = factory.create(Color.Green); assertEquals(Color.Green, greenCamaro.color); assertEquals(1998, greenCamaro.modelYear); assertEquals(300, greenCamaro.horsePower); Camaro redCamaro = factory.create(Color.Red); assertEquals(Color.Red, redCamaro.color); assertEquals(1998, redCamaro.modelYear); assertEquals(300, redCamaro.horsePower); } public void testSelectInjectConstructor() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); CorvetteFactory factory = ginjector.getCorvetteFactory(); Corvette corvette = factory.create(Color.Red, true); assertEquals(Color.Red, corvette.color); assertTrue(corvette.isConvertible); assertEquals(10.4f, corvette.maxMph); } public void testSwappedParameters() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); AlternateCorvetteFactory factory = ginjector.getAlternateCorvetteFactory(); Corvette corvette = factory.create(true, Color.Green); assertEquals(Color.Green, corvette.color); assertTrue(corvette.isConvertible); assertEquals(10.4f, corvette.maxMph); } public void testNamedFactories() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); ColoredCarFactory beetleFactory = ginjector.getNamedBeetleFactory(); Beetle beetle = (Beetle) beetleFactory.create(Color.Red); assertEquals(Color.Red, beetle.color); assertEquals(5.61, beetle.engineSize); ColoredCarFactory mustangFactory = ginjector.getNamedMustangFactory(); Mustang mustang = (Mustang) mustangFactory.create(Color.Yellow); assertEquals(Color.Yellow, mustang.color); assertEquals(5.61, mustang.engineSize); } public void testMethodAndFieldInjection() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); ColoredCarFactory factory = ginjector.getNamedPorscheFactory(); Porsche porsche = (Porsche) factory.create(Color.Green); assertEquals("fooBar", porsche.name); assertEquals(Color.Green, porsche.color); assertEquals(911, porsche.model); assertEquals(5.61, porsche.price); } public void testProviderInjection() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); ColoredCarFactory factory = ginjector.getNamedFireBirdFactory(); FireBird fireBird = (FireBird) factory.create(Color.Yellow); assertEquals(Color.Yellow, fireBird.color); assertEquals("fooBar", fireBird.modifiersProvider.get()); } public void testParameterizedInjection() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); ColoredCarFactory factory = ginjector.getNamedDeLoreanFactory(); DeLorean deLorean = (DeLorean) factory.create(Color.Green); assertEquals(Color.Green, deLorean.color); assertEquals("barFoo", deLorean.features.iterator().next()); assertEquals((Integer) 54, deLorean.featureActivationSpeeds.iterator().next()); } public void testPrivateConstructorInject() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); ColoredCarFactory factory = ginjector.getNamedPriusFactory(); Prius prius = (Prius) factory.create(Color.Red); assertEquals(Color.Red, prius.color); } public void testNamedAssistedAnnotations() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); BmwFactory factory = ginjector.getBmwFactory(); M3 m3 = factory.paintOutsideIn(Color.Red, Color.Yellow); assertEquals(Color.Red, m3.exterior); assertEquals(Color.Yellow, m3.interior); M3 m3insideOut = factory.paintInsideOut(Color.Red, Color.Yellow); assertEquals(Color.Red, m3insideOut.interior); assertEquals(Color.Yellow, m3insideOut.exterior); } public void testAssistedInjectConstructorSelection() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); AudiFactory factory = ginjector.getAudiFactory(); A4 a4basic = factory.createBasic(Color.Green); assertEquals(Color.Green, a4basic.color); assertEquals("none", a4basic.modification); assertEquals(5.61, a4basic.speed); A4 a4modified = factory.createModified(Color.Red, "longer"); assertEquals(Color.Red, a4modified.color); assertEquals("longer", a4modified.modification); assertEquals(5.61, a4modified.speed); } public void testNoBindingAssistedInject() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); MustangFactory factory = ginjector.getMustangFactory(); Mustang mustang = factory.create(Color.Green); assertEquals(Color.Green, mustang.color); assertEquals(5.61, mustang.engineSize); } public void testConfigureAnnotatedReturnValue() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); AnnotatedVersatileCarFactory factory = ginjector.getAnnotatedVersatileCarFactory(); assertTrue(factory.getGermanCar(Color.Green) instanceof Beetle); assertTrue(factory.getAmericanCar(Color.Red) instanceof Mustang); } public void testBindingAssistedInject() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); ColoredCarFactory factory = ginjector.getColoredCarFactory(); Mustang mustang = (Mustang) factory.create(Color.Red); assertEquals(Color.Red, mustang.color); } public void testMultipleReturnTypes() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); VersatileCarFactory factory = ginjector.getVersatileCarFactory(); Mustang mustang = factory.getMustang(Color.Yellow); assertEquals(Color.Yellow, mustang.color); assertEquals(5.61, mustang.engineSize); Beetle beetle = factory.getBeetle(Color.Red); assertEquals(Color.Red, beetle.color); assertEquals(5.61, beetle.engineSize); } public void testBoundTypeInjection() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); HummerFactory factory = ginjector.getHummerFactory(); Hummer hummer = factory.create(5000); assertEquals(5000, hummer.size); assertTrue(hummer.insurance instanceof GreatWest); } public void testIgnoredParameterInject() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); ComplicatedMustangFactory factory = ginjector.getComplicatedMustangFactory(); Mustang mustang = factory.create(Color.Red, false); assertEquals(Color.Red, mustang.color); assertEquals(5.61, mustang.engineSize); } public void testParameterizedReturnValue() { CarFactoryGinjector ginjector = GWT.create(CarFactoryGinjector.class); ParameterizableFactory<String> factory = ginjector.getParameterizableFactoryForString(); VersatileCar<String> car = factory.create(Color.Green); assertEquals(Color.Green, car.color); assertEquals("barFoo", car.versatility.iterator().next()); } // ----------- More Parametrization Tests ----------------------------------- ///////////////////////// Classes static class Foo { Bar assistedValue; Baz injectedValue; @Inject Foo(@Assisted Bar assistedValue, Baz injectedValue) { this.assistedValue = assistedValue; this.injectedValue = injectedValue; } } static class Bar {} static class Baz {} ////////////////////// Factory interfaces interface GenericFactory<I, O> { O create(I i); } interface GenericFooFactory extends GenericFactory<Bar, Foo> {} interface NonGenericFooFactory { Foo create(Bar bar); } interface ExtendedNonGenericFooFactory extends NonGenericFooFactory {} ////////////////////// Modules static class GenericFactoryModule extends AbstractGinModule { @Override protected void configure() { install(new GinFactoryModuleBuilder().build(new TypeLiteral<GenericFactory<Bar, Foo>>(){})); } } static class GenericFooFactoryModule extends AbstractGinModule { @Override protected void configure() { install(new GinFactoryModuleBuilder().build(GenericFooFactory.class)); } } static class NonGenericFooFactoryModule extends AbstractGinModule { @Override protected void configure() { install(new GinFactoryModuleBuilder().build(NonGenericFooFactory.class)); } } static class ExtendedNonGenericFooFactoryModule extends AbstractGinModule { @Override protected void configure() { install(new GinFactoryModuleBuilder().build(ExtendedNonGenericFooFactory.class)); } } ///////////////////////// Injectors @GinModules(GenericFactoryModule.class) interface GenericFactoryTestGinjector extends Ginjector { GenericFactory<Bar, Foo> getFactory(); } @GinModules(GenericFooFactoryModule.class) interface GenericFooFactoryTestGinjector extends Ginjector { GenericFooFactory getFactory(); } @GinModules(NonGenericFooFactoryModule.class) interface NonGenericFooFactoryTestGinjector extends Ginjector { NonGenericFooFactory getFactory(); } @GinModules(ExtendedNonGenericFooFactoryModule.class) interface ExtendedNonGenericFooFactoryTestGinjector extends Ginjector { ExtendedNonGenericFooFactory getFactory(); } /////////////////////////// Tests public void testFoo() { GenericFactoryTestGinjector ginjector = GWT.create(GenericFactoryTestGinjector.class); assertNotNull(ginjector.getFactory().create(new Bar())); } public void testFoo2() { GenericFooFactoryTestGinjector ginjector = GWT.create(GenericFooFactoryTestGinjector.class); assertNotNull(ginjector.getFactory().create(new Bar())); } public void testFoo3() { NonGenericFooFactoryTestGinjector ginjector = GWT.create(NonGenericFooFactoryTestGinjector.class); assertNotNull(ginjector.getFactory().create(new Bar())); } public void testFoo4() { ExtendedNonGenericFooFactoryTestGinjector ginjector = GWT.create(ExtendedNonGenericFooFactoryTestGinjector.class); assertNotNull(ginjector.getFactory().create(new Bar())); } // ----------- Types -------------------------------------------------------- public interface Car {} public interface ColoredCarFactory { Car create(Color color); } public interface CamaroFactory { Camaro create(Color color); } public interface CorvetteFactory { Corvette create(Color color, boolean isConvertible); } public interface AlternateCorvetteFactory { Corvette create(boolean isConvertible, Color color); } public interface MustangFactory { Mustang create(Color color); } public interface ComplicatedMustangFactory { Mustang create(Color color, boolean stripes); } public interface VersatileCarFactory { Mustang getMustang(Color color); Beetle getBeetle(Color color); } public interface BmwFactory { M3 paintOutsideIn(@Assisted("exterior") Color exterior, @Assisted("interior") Color interior); M3 paintInsideOut(@Assisted("interior") Color exterior, @Assisted("exterior") Color interior); } public interface AudiFactory { A4 createBasic(Color color); A4 createModified(Color color, String modifications); } public interface HummerFactory { Hummer create(int size); } public interface AnnotatedVersatileCarFactory { @Named("german") Car getGermanCar(Color color); @Named("american") Car getAmericanCar(Color color); } public interface ParameterizableFactory<T> { VersatileCar<T> create(Color color); } public static class Mustang implements Car { private final double engineSize; private final Color color; @Inject public Mustang(double engineSize, @Assisted Color color) { this.engineSize = engineSize; this.color = color; } } public static class Beetle implements Car { private final Color color; private final double engineSize; @Inject public Beetle(@Assisted Color color, double engineSize) { this.color = color; this.engineSize = engineSize; } } public static class Camaro implements Car { private final int horsePower; private final int modelYear; private final Color color; @Inject public Camaro(@Named("horsePower") int horsePower, @Named("modelYear") int modelYear, @Assisted Color color) { this.horsePower = horsePower; this.modelYear = modelYear; this.color = color; } } public static class Corvette implements Car { private boolean isConvertible; private Color color; private float maxMph; public Corvette(Color color, boolean isConvertible) { throw new IllegalStateException("Not an @Inject constructor"); } @Inject public Corvette(@Assisted Color color, Float maxMph, @Assisted boolean isConvertible) { this.isConvertible = isConvertible; this.color = color; this.maxMph = maxMph; } } public static class Porsche implements Car { private final Color color; private final double price; private @Inject String name; private int model; @Inject public Porsche(@Assisted Color color, double price) { this.color = color; this.price = price; } @Inject void setModel(int model) { this.model = model; } } public static class FireBird implements Car { private final Provider<String> modifiersProvider; private final Color color; @Inject public FireBird(Provider<String> modifiersProvider, @Assisted Color color) { this.modifiersProvider = modifiersProvider; this.color = color; } } public static class DeLorean implements Car { private final Set<String> features; private final Set<Integer> featureActivationSpeeds; private final Color color; @Inject public DeLorean(Set<String> extraFeatures, Set<Integer> featureActivationSpeeds, @Assisted Color color) { this.features = extraFeatures; this.featureActivationSpeeds = featureActivationSpeeds; this.color = color; } } public static class Prius implements Car { final Color color; @Inject private Prius(@Assisted Color color) { this.color = color; } } public static class M3 implements Car { final Color interior; final Color exterior; @Inject public M3(@Assisted("exterior") Color exterior, @Assisted("interior") Color interior) { this.interior = interior; this.exterior = exterior; } } public static class A4 implements Car { final Color color; final double speed; final String modification; @AssistedInject public A4(@Assisted Color color, Double speed) { this.color = color; this.speed = speed; this.modification = "none"; } @AssistedInject public A4(@Assisted Color color, @Assisted String modification, Double speed) { this.color = color; this.speed = speed; this.modification = modification; } } interface InsuranceCompany {} public static class GreatWest implements InsuranceCompany {} public static class Hummer { final int size; final InsuranceCompany insurance; @Inject public Hummer(@Assisted int size, InsuranceCompany insurance) { this.size = size; this.insurance = insurance; } } public static class VersatileCar<T> { final Color color; final Set<T> versatility; @Inject public VersatileCar(@Assisted Color color, Set<T> versatility) { this.color = color; this.versatility = versatility; } } public String getModuleName() { return "com.google.gwt.inject.InjectTest"; } }