/**
 * Copyright (C) 2008 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.assistedinject;

import com.google.inject.AbstractModule;
import static com.google.inject.Asserts.assertContains;
import static com.google.inject.Asserts.assertEqualsBothWays;
import com.google.inject.ConfigurationException;
import com.google.inject.CreationException;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.matcher.Matchers;
import com.google.inject.name.Named;
import com.google.inject.name.Names;

import junit.framework.TestCase;

import java.awt.*;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

public class FactoryProvider2Test extends TestCase {

  public void testAssistedFactory() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).toInstance(5.0d);
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE);
    assertEquals(Color.BLUE, blueMustang.color);
    assertEquals(5.0d, blueMustang.engineSize);

    Mustang redMustang = (Mustang) carFactory.create(Color.RED);
    assertEquals(Color.RED, redMustang.color);
    assertEquals(5.0d, redMustang.engineSize);
  }

  public void testAssistedFactoryWithAnnotations() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250);
        bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984);
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Camaro.class));
      }
    });

    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Camaro blueCamaro = (Camaro) carFactory.create(Color.BLUE);
    assertEquals(Color.BLUE, blueCamaro.color);
    assertEquals(1984, blueCamaro.modelYear);
    assertEquals(250, blueCamaro.horsePower);

    Camaro redCamaro = (Camaro) carFactory.create(Color.RED);
    assertEquals(Color.RED, redCamaro.color);
    assertEquals(1984, redCamaro.modelYear);
    assertEquals(250, redCamaro.horsePower);
  }

  interface Car {}

  interface ColoredCarFactory {
    Car 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 void drive() {}
  }

  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;
    }
  }

  interface SummerCarFactory {
    Car create(Color color, boolean convertable);
  }

  public void testFactoryUsesInjectedConstructor() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(float.class).toInstance(140f);
        bind(SummerCarFactory.class).toProvider(
            FactoryProvider.newFactory(SummerCarFactory.class, Corvette.class));
      }
    });

    SummerCarFactory carFactory = injector.getInstance(SummerCarFactory.class);

    Corvette redCorvette = (Corvette) carFactory.create(Color.RED, false);
    assertEquals(Color.RED, redCorvette.color);
    assertEquals(140f, redCorvette.maxMph);
    assertFalse(redCorvette.isConvertable);
  }

  public static class Corvette implements Car {
    private boolean isConvertable;
    private Color color;
    private float maxMph;

    public Corvette(Color color, boolean isConvertable) {
      throw new IllegalStateException("Not an @AssistedInject constructor");
    }

    @Inject
    public Corvette(@Assisted Color color, Float maxMph, @Assisted boolean isConvertable) {
      this.isConvertable = isConvertable;
      this.color = color;
      this.maxMph = maxMph;
    }
  }

  public void testConstructorDoesntNeedAllFactoryMethodArguments() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(SummerCarFactory.class).toProvider(
            FactoryProvider.newFactory(SummerCarFactory.class, Beetle.class));
      }
    });
    SummerCarFactory factory = injector.getInstance(SummerCarFactory.class);

    Beetle beetle = (Beetle) factory.create(Color.RED, true);
    assertSame(Color.RED, beetle.color);
  }

  public static class Beetle implements Car {
    private final Color color;
    @Inject
    public Beetle(@Assisted Color color) {
      this.color = color;
    }
  }

  public void testMethodsAndFieldsGetInjected() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(String.class).toInstance("turbo");
        bind(int.class).toInstance(911);
        bind(double.class).toInstance(50000d);
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Porsche.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Porsche grayPorsche = (Porsche) carFactory.create(Color.GRAY);
    assertEquals(Color.GRAY, grayPorsche.color);
    assertEquals(50000d, grayPorsche.price);
    assertEquals(911, grayPorsche.model);
    assertEquals("turbo", grayPorsche.name);
  }

  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 void testProviderInjection() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(String.class).toInstance("trans am");
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Firebird.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Firebird blackFirebird = (Firebird) carFactory.create(Color.BLACK);
    assertEquals(Color.BLACK, blackFirebird.color);
    assertEquals("trans am", blackFirebird.modifiersProvider.get());
  }

  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 void testAssistedProviderInjection() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(String.class).toInstance("trans am");
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Flamingbird.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Flamingbird flamingbird = (Flamingbird) carFactory.create(Color.BLACK);
    assertEquals(Color.BLACK, flamingbird.colorProvider.get());
    assertEquals("trans am", flamingbird.modifiersProvider.get());
    
    Flamingbird flamingbird2 = (Flamingbird) carFactory.create(Color.RED);
    assertEquals(Color.RED, flamingbird2.colorProvider.get());
    assertEquals("trans am", flamingbird2.modifiersProvider.get());
    // Make sure the original flamingbird is black still.
    assertEquals(Color.BLACK, flamingbird.colorProvider.get());
  }  
  
  public static class Flamingbird implements Car {
    private final Provider<String> modifiersProvider;
    private final Provider<Color> colorProvider;

    @Inject
    public Flamingbird(Provider<String> modifiersProvider, @Assisted Provider<Color> colorProvider) {
      this.modifiersProvider = modifiersProvider;
      this.colorProvider = colorProvider;
    }
  }

  public void testTypeTokenInjection() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(new TypeLiteral<Set<String>>() {}).toInstance(Collections.singleton("Flux Capacitor"));
        bind(new TypeLiteral<Set<Integer>>() {}).toInstance(Collections.singleton(88));
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, DeLorean.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    DeLorean deLorean = (DeLorean) carFactory.create(Color.GRAY);
    assertEquals(Color.GRAY, deLorean.color);
    assertEquals("Flux Capacitor", deLorean.features.iterator().next());
    assertEquals(new Integer(88), deLorean.featureActivationSpeeds.iterator().next());
  }

  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 void testTypeTokenProviderInjection() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(new TypeLiteral<Set<String>>() { }).toInstance(Collections.singleton("Datsun"));
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Z.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Z orangeZ = (Z) carFactory.create(Color.ORANGE);
    assertEquals(Color.ORANGE, orangeZ.color);
    assertEquals("Datsun", orangeZ.manufacturersProvider.get().iterator().next());
  }

  public static class Z implements Car {
    private final Provider<Set<String>> manufacturersProvider;
    private final Color color;

    @Inject
    public Z(Provider<Set<String>> manufacturersProvider, @Assisted Color color) {
      this.manufacturersProvider = manufacturersProvider;
      this.color = color;
    }
  }

  public static class Prius implements Car {
    @SuppressWarnings("unused")
    final Color color;

    @Inject
    private Prius(@Assisted Color color) {
      this.color = color;
    }
  }

  public void testAssistInjectionInNonPublicConstructor() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Prius.class));
      }
    });
    Prius prius = (Prius) injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE);
    assertEquals(prius.color, Color.ORANGE);
  }

  public static class ExplodingCar implements Car {
    @Inject
    public ExplodingCar(@Assisted Color color) {
      throw new IllegalStateException("kaboom!");
    }
  }

  public void testExceptionDuringConstruction() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, ExplodingCar.class));
      }
    });
    try {
      injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE);
      fail();
    } catch (IllegalStateException e) {
      assertEquals("kaboom!", e.getMessage());
    }
  }

  public static class DefectiveCar implements Car {
    @Inject
    public DefectiveCar() throws ExplosionException, FireException {
      throw new ExplosionException();
    }
  }

  public static class ExplosionException extends Exception { }
  public static class FireException extends Exception { }

  public interface DefectiveCarFactoryWithNoExceptions {
    Car createCar();
  }

  public interface DefectiveCarFactory {
    Car createCar() throws FireException;
  }

  public interface CorrectDefectiveCarFactory {
    Car createCar() throws FireException, ExplosionException;
  }

  public void testConstructorExceptionsAreThrownByFactory() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(CorrectDefectiveCarFactory.class).toProvider(
            FactoryProvider.newFactory(CorrectDefectiveCarFactory.class, DefectiveCar.class));
      }
    });
    try {
      injector.getInstance(CorrectDefectiveCarFactory.class).createCar();
      fail();
    } catch (FireException e) {
      fail();
    } catch (ExplosionException expected) {
    }
  }

  public static class WildcardCollection {

    public interface Factory {
      WildcardCollection create(Collection<?> items);
    }

    @Inject
    public WildcardCollection(@Assisted Collection<?> items) { }
  }

  public void testWildcardGenerics() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(WildcardCollection.Factory.class).toProvider(
            FactoryProvider.newFactory(WildcardCollection.Factory.class, WildcardCollection.class));
      }
    });
    WildcardCollection.Factory factory = injector.getInstance(WildcardCollection.Factory.class);
    factory.create(Collections.emptyList());
  }

  public static class SteeringWheel {}

  public static class Fiat implements Car {
    @SuppressWarnings("unused")
    private final SteeringWheel steeringWheel;
    @SuppressWarnings("unused")
    private final Color color;

    @Inject
    public Fiat(SteeringWheel steeringWheel, @Assisted Color color) {
      this.steeringWheel = steeringWheel;
      this.color = color;
    }
  }

  public void testFactoryWithImplicitBindings() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Fiat.class));
      }
    });

    ColoredCarFactory coloredCarFactory = injector.getInstance(ColoredCarFactory.class);
    Fiat fiat = (Fiat) coloredCarFactory.create(Color.GREEN);
    assertEquals(Color.GREEN, fiat.color);
    assertNotNull(fiat.steeringWheel);
  }

  public void testFactoryFailsWithMissingBinding() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(ColoredCarFactory.class).toProvider(
              FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "Could not find a suitable constructor in java.lang.Double.",
          "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java");
    }
  }
  
  public void testFactoryFailsWithMissingBindingInToolStage() {
    try {
      Guice.createInjector(Stage.TOOL, new AbstractModule() {
        @Override protected void configure() {
          bind(ColoredCarFactory.class).toProvider(
              FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "Could not find a suitable constructor in java.lang.Double.",
          "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java");
    }
  }

  public void testMethodsDeclaredInObject() {
    Injector injector = Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(Double.class).toInstance(5.0d);
          bind(ColoredCarFactory.class).toProvider(
              FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
        }
      });

    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    assertEqualsBothWays(carFactory, carFactory);
  }

  static class Subaru implements Car {
    @Inject @Assisted Provider<Color> colorProvider;
  }

  public void testInjectingProviderOfParameter() {
    Injector injector = Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(ColoredCarFactory.class).toProvider(
              FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class));
        }
      });

    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
    Subaru subaru = (Subaru) carFactory.create(Color.RED);

    assertSame(Color.RED, subaru.colorProvider.get());
    assertSame(Color.RED, subaru.colorProvider.get());
    
    Subaru sedan  = (Subaru) carFactory.create(Color.BLUE);
    assertSame(Color.BLUE, sedan.colorProvider.get());
    assertSame(Color.BLUE, sedan.colorProvider.get());
    
    // and make sure the subaru is still red
    assertSame(Color.RED, subaru.colorProvider.get());
  }

  public void testInjectingNullParameter() {
    Injector injector = Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(ColoredCarFactory.class).toProvider(
              FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class));
        }
      });

    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
    Subaru subaru = (Subaru) carFactory.create(null);

    assertNull(subaru.colorProvider.get());
    assertNull(subaru.colorProvider.get());
  }

  interface ProviderBasedColoredCarFactory {
    Car createCar(Provider<Color> colorProvider, Provider<String> stringProvider);
    Mustang createMustang(@Assisted("color") Provider<Color> colorProvider);
  }

  public void testAssistedProviderIsDisallowed() {
    try {
      Guice.createInjector(new AbstractModule() {
          @Override protected void configure() {
            bind(ProviderBasedColoredCarFactory.class).toProvider(
                FactoryProvider.newFactory(ProviderBasedColoredCarFactory.class, Subaru.class));
          }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [1] with key"
            + " [com.google.inject.Provider<java.awt.Color>] on method ["
            + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]",
          "2) A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [2] with key"
            + " [com.google.inject.Provider<java.lang.String>] on method ["
            + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]",
          "3) A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [1] with key"
            + " [com.google.inject.Provider<java.awt.Color>"
            + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]"
            + " on method [" + ProviderBasedColoredCarFactory.class.getName() + ".createMustang()]"
      );
      
    }
  }

  interface JavaxProviderBasedColoredCarFactory {
    Car createCar(javax.inject.Provider<Color> colorProvider, javax.inject.Provider<String> stringProvider);
    Mustang createMustang(@Assisted("color") javax.inject.Provider<Color> colorProvider);
  }

  public void testAssistedJavaxProviderIsDisallowed() {
    try {
      Guice.createInjector(new AbstractModule() {
          @Override protected void configure() {
            bind(JavaxProviderBasedColoredCarFactory.class).toProvider(
                FactoryProvider.newFactory(JavaxProviderBasedColoredCarFactory.class, Subaru.class));
          }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [1] with key"
            + " [com.google.inject.Provider<java.awt.Color>] on method ["
            + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]",
          "2) A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [2] with key"
            + " [com.google.inject.Provider<java.lang.String>] on method ["
            + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]",
          "3) A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [1] with key"
            + " [com.google.inject.Provider<java.awt.Color>"
            + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]"
            + " on method [" + JavaxProviderBasedColoredCarFactory.class.getName() + ".createMustang()]"
      );
    }
  }

  public void testFactoryUseBeforeInitialization() {
    ColoredCarFactory carFactory = FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class)
        .get();
    try {
      carFactory.create(Color.RED);
      fail();
    } catch (IllegalStateException expected) {
      assertContains(expected.getMessage(),
          "Factories.create() factories cannot be used until they're initialized by Guice.");
    }
  }

  interface MustangFactory {
    Mustang create(Color color);
  }

  public void testFactoryBuildingConcreteTypes() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(double.class).toInstance(5.0d);
        // note there is no 'thatMakes()' call here:
        bind(MustangFactory.class).toProvider(
            FactoryProvider.newFactory(MustangFactory.class, Mustang.class));
      }
    });
    MustangFactory factory = injector.getInstance(MustangFactory.class);

    Mustang mustang = factory.create(Color.RED);
    assertSame(Color.RED, mustang.color);
    assertEquals(5.0d, mustang.engineSize);
  }

  static class Fleet {
    @Inject Mustang mustang;
    @Inject Camaro camaro;
  }

  interface FleetFactory {
    Fleet createFleet(Color color);
  }

  public void testInjectDeepIntoConstructedObjects() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(double.class).toInstance(5.0d);
        bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250);
        bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984);
        bind(FleetFactory.class).toProvider(FactoryProvider.newFactory(FleetFactory.class,
            Fleet.class));
      }
    });

    FleetFactory fleetFactory = injector.getInstance(FleetFactory.class);
    Fleet fleet = fleetFactory.createFleet(Color.RED);

    assertSame(Color.RED, fleet.mustang.color);
    assertEquals(5.0d, fleet.mustang.engineSize);
    assertSame(Color.RED, fleet.camaro.color);
    assertEquals(250, fleet.camaro.horsePower);
    assertEquals(1984, fleet.camaro.modelYear);
  }

  interface TwoToneCarFactory {
    Car create(@Assisted("paint") Color paint, @Assisted("fabric") Color fabric);
  }

  static class Maxima implements Car {
    @Inject @Assisted("paint") Color paint;
    @Inject @Assisted("fabric") Color fabric;
  }

  public void testDistinctKeys() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(TwoToneCarFactory.class).toProvider(
            FactoryProvider.newFactory(TwoToneCarFactory.class, Maxima.class));
      }
    });

    TwoToneCarFactory factory = injector.getInstance(TwoToneCarFactory.class);
    Maxima maxima = (Maxima) factory.create(Color.BLACK, Color.GRAY);
    assertSame(Color.BLACK, maxima.paint);
    assertSame(Color.GRAY, maxima.fabric);
  }

  interface DoubleToneCarFactory {
    Car create(@Assisted("paint") Color paint, @Assisted("paint") Color morePaint);
  }

  public void testDuplicateKeys() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(DoubleToneCarFactory.class).toProvider(
              FactoryProvider.newFactory(DoubleToneCarFactory.class, Maxima.class));
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(), "A binding to java.awt.Color annotated with @"
          + Assisted.class.getName() + "(value=paint) was already configured at");
    }
  }

  /*if[AOP]*/
  public void testMethodInterceptorsOnAssistedTypes() {
    final AtomicInteger invocationCount = new AtomicInteger();
    final org.aopalliance.intercept.MethodInterceptor interceptor
        = new org.aopalliance.intercept.MethodInterceptor() {
      public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation)
          throws Throwable {
        invocationCount.incrementAndGet();
        return methodInvocation.proceed();
      }
    };

    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindInterceptor(Matchers.any(), Matchers.any(), interceptor);
        bind(Double.class).toInstance(5.0d);
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
      }
    });

    ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class);
    Mustang mustang = (Mustang) factory.create(Color.GREEN);
    assertEquals(0, invocationCount.get());
    mustang.drive();
    assertEquals(1, invocationCount.get());
  }
  /*end[AOP]*/

  /**
   * Our factories aren't reusable across injectors. Although this behaviour isn't something we
   * like, I have a test case to make sure the error message is pretty.
   */
  public void testFactoryReuseErrorMessageIsPretty() {
    final Provider<ColoredCarFactory> factoryProvider
        = FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class);

    Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        bind(Double.class).toInstance(5.0d);
        bind(ColoredCarFactory.class).toProvider(factoryProvider);
      }
    });

    try {
      Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(Double.class).toInstance(5.0d);
          bind(ColoredCarFactory.class).toProvider(factoryProvider);
        }
      });
      fail();
    } catch(CreationException expected) {
      assertContains(expected.getMessage(),
          "Factories.create() factories may only be used in one Injector!");
    }
  }

  public void testNonAssistedFactoryMethodParameter() {
    try {
      FactoryProvider.newFactory(NamedParameterFactory.class, Mustang.class);
      fail();
    } catch(ConfigurationException expected) {
      assertContains(expected.getMessage(),
          "Only @Assisted is allowed for factory parameters, but found @" + Named.class.getName());
    }
  }

  interface NamedParameterFactory {
    Car create(@Named("seats") int seats, double engineSize);
  }


  public void testDefaultAssistedAnnotation() throws NoSuchFieldException {
    Assisted plainAssisted
        = Subaru.class.getDeclaredField("colorProvider").getAnnotation(Assisted.class);
    assertEqualsBothWays(FactoryProvider2.DEFAULT_ANNOTATION, plainAssisted);
    assertEquals(FactoryProvider2.DEFAULT_ANNOTATION.toString(), plainAssisted.toString());
  }

  interface GenericColoredCarFactory<T extends Car> {
    T create(Color color);
  }

  public void testGenericAssistedFactory() {
    final TypeLiteral<GenericColoredCarFactory<Mustang>> mustangTypeLiteral
        = new TypeLiteral<GenericColoredCarFactory<Mustang>>() {};
    final TypeLiteral<GenericColoredCarFactory<Camaro>> camaroTypeLiteral
        = new TypeLiteral<GenericColoredCarFactory<Camaro>>() {};

    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).toInstance(5.0d);
        bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250);
        bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984);
        bind(mustangTypeLiteral)
            .toProvider(FactoryProvider.newFactory(mustangTypeLiteral, TypeLiteral.get(Mustang.class)));
        bind(camaroTypeLiteral)
            .toProvider(FactoryProvider.newFactory(camaroTypeLiteral, TypeLiteral.get(Camaro.class)));
      }
    });

    GenericColoredCarFactory<Mustang> mustangFactory
        = injector.getInstance(Key.get(mustangTypeLiteral));
    GenericColoredCarFactory<Camaro> camaroFactory
        = injector.getInstance(Key.get(camaroTypeLiteral));

    Mustang blueMustang = mustangFactory.create(Color.BLUE);
    assertEquals(Color.BLUE, blueMustang.color);
    assertEquals(5.0d, blueMustang.engineSize);

    Camaro redCamaro = camaroFactory.create(Color.RED);
    assertEquals(Color.RED, redCamaro.color);
    assertEquals(1984, redCamaro.modelYear);
    assertEquals(250, redCamaro.horsePower);
  }

  public interface Insurance<T extends Car> {
  }

  public static class MustangInsurance implements Insurance<Mustang> {
    private final double premium;
    private final double limit;
    private Mustang car;

    @Inject
    public MustangInsurance(@Named("lowLimit") double limit, @Assisted Mustang car,
        @Assisted double premium) {
      this.premium = premium;
      this.limit = limit;
      this.car = car;
    }

    public void sell() {}
  }

  public static class CamaroInsurance implements Insurance<Camaro> {
    private final double premium;
    private final double limit;
    private Camaro car;

    @Inject
    public CamaroInsurance(@Named("highLimit") double limit, @Assisted Camaro car,
        @Assisted double premium) {
      this.premium = premium;
      this.limit = limit;
      this.car = car;
    }

    public void sell() {}
  }

  public interface MustangInsuranceFactory {
    public Insurance<Mustang> create(Mustang car, double premium);
  }

  public interface CamaroInsuranceFactory {
    public Insurance<Camaro> create(Camaro car, double premium);
  }

  public void testAssistedFactoryForConcreteType() {

    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d);
        bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d);
        bind(MustangInsuranceFactory.class).toProvider(
            FactoryProvider.newFactory(MustangInsuranceFactory.class, MustangInsurance.class));
        bind(CamaroInsuranceFactory.class).toProvider(
            FactoryProvider.newFactory(CamaroInsuranceFactory.class, CamaroInsurance.class));
      }
    });

    MustangInsuranceFactory mustangInsuranceFactory =
        injector.getInstance(MustangInsuranceFactory.class);
    CamaroInsuranceFactory camaroInsuranceFactory =
        injector.getInstance(CamaroInsuranceFactory.class);

    Mustang mustang = new Mustang(5000d, Color.BLACK);
    MustangInsurance mustangPolicy =
        (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d);
    assertEquals(800.0d, mustangPolicy.premium);
    assertEquals(50000.0d, mustangPolicy.limit);

    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
    CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d);
    assertEquals(800.0d, camaroPolicy.premium);
    assertEquals(100000.0d, camaroPolicy.limit);
  }

  public interface InsuranceFactory<T extends Car> {
    public Insurance<T> create(T car, double premium);
  }

  public void testAssistedFactoryForParameterizedType() {
    final TypeLiteral<InsuranceFactory<Mustang>> mustangInsuranceFactoryType =
        new TypeLiteral<InsuranceFactory<Mustang>>() {};
    final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType =
        new TypeLiteral<InsuranceFactory<Camaro>>() {};

    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d);
        bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d);
        bind(mustangInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
            mustangInsuranceFactoryType, TypeLiteral.get(MustangInsurance.class)));
        bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
            camaroInsuranceFactoryType, TypeLiteral.get(CamaroInsurance.class)));
      }
    });

    InsuranceFactory<Mustang> mustangInsuranceFactory =
        injector.getInstance(Key.get(mustangInsuranceFactoryType));
    InsuranceFactory<Camaro> camaroInsuranceFactory =
        injector.getInstance(Key.get(camaroInsuranceFactoryType));

    Mustang mustang = new Mustang(5000d, Color.BLACK);
    MustangInsurance mustangPolicy =
        (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d);
    assertEquals(800.0d, mustangPolicy.premium);
    assertEquals(50000.0d, mustangPolicy.limit);

    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
    CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d);
    assertEquals(800.0d, camaroPolicy.premium);
    assertEquals(100000.0d, camaroPolicy.limit);
  }

  public static class AutoInsurance<T extends Car> implements Insurance<T> {
    private final double premium;
    private final double limit;
    private final T car;

    @Inject
    public AutoInsurance(double limit, @Assisted T car, @Assisted double premium) {
      this.limit = limit;
      this.car = car;
      this.premium = premium;
    }

    public void sell() {}
  }

  public void testAssistedFactoryForTypeVariableParameters() {
    final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType =
        new TypeLiteral<InsuranceFactory<Camaro>>() {};

    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).toInstance(50000.0d);
        bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
            camaroInsuranceFactoryType, new TypeLiteral<AutoInsurance<Camaro>>() {}));
      }
    });

    InsuranceFactory<Camaro> camaroInsuranceFactory =
        injector.getInstance(Key.get(camaroInsuranceFactoryType));

    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
    AutoInsurance camaroPolicy = (AutoInsurance) camaroInsuranceFactory.create(camaro, 800.0d);
    assertEquals(800.0d, camaroPolicy.premium);
    assertEquals(50000.0d, camaroPolicy.limit);
    assertEquals(camaro, camaroPolicy.car);
  }

  public void testInjectingAndUsingInjector() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Segway.class));
      }
    });

    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
    Segway green = (Segway)carFactory.create(Color.GREEN);
    assertSame(Color.GREEN, green.getColor());
    assertSame(Color.GREEN, green.getColor());
    
    Segway pink = (Segway)carFactory.create(Color.PINK);
    assertSame(Color.PINK, pink.getColor());
    assertSame(Color.PINK, pink.getColor());
    assertSame(Color.GREEN, green.getColor());
  }
  
  static class Segway implements Car {
    @Inject Injector injector;
    
    Color getColor() { return injector.getInstance(Key.get(Color.class, FactoryProvider2.DEFAULT_ANNOTATION)); }
  }
  
  
}
