alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (FactoryProvider2Test.java)

This example Java source code file (FactoryProvider2Test.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

abstractmodule, assisted, assistedinject, camaro, car, color, coloredcarfactory, delegater, injector, mustang, override, provider, string, typeliteral, util

The FactoryProvider2Test.java Java example source code

/**
 * 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 static com.google.inject.Asserts.assertContains;
import static com.google.inject.Asserts.assertEqualsBothWays;

import com.google.inject.AbstractModule;
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.assistedinject.FactoryProvider2Test.Equals.ComparisonMethod;
import com.google.inject.assistedinject.FactoryProvider2Test.Equals.Impl;
import com.google.inject.matcher.Matchers;
import com.google.inject.name.Named;
import com.google.inject.name.Names;

import junit.framework.TestCase;

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

@SuppressWarnings("deprecation")
public class FactoryProvider2Test extends TestCase {

  private enum Color { BLUE, GREEN, RED, GRAY, BLACK, ORANGE, PINK }
  
  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);
  }

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

    @SuppressWarnings("unused")
    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() {
      @Override
      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 colorProvider) {
      this.modifiersProvider = modifiersProvider;
      this.colorProvider = colorProvider;
    }
  }

  public void testTypeTokenInjection() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(new TypeLiteral<Set() {}).toInstance(Collections.singleton("Flux Capacitor"));
        bind(new TypeLiteral<Set() {}).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 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() { }).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 manufacturersProvider;
    private final Color color;

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

  public static class Prius implements Car {
    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(@SuppressWarnings("unused") @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 {
      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(@SuppressWarnings("unused") @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 {
    private final SteeringWheel steeringWheel;
    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 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) {
      assertEquals(expected.getMessage(), 4, expected.getErrorMessages().size());
      // Assert each method individually, because JDK7 doesn't guarantee method ordering.
      assertContains(expected.getMessage(),
          ") 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<" + Color.class.getName() + ">] on method ["
            + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]");
      assertContains(expected.getMessage(),
          ") 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()]");
      assertContains(expected.getMessage(),
          ") 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<" + Color.class.getName() + ">"
            + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]"
            + " on method [" + ProviderBasedColoredCarFactory.class.getName() + ".createMustang()]"
      );
      assertContains(expected.getMessage(),
          ") No implementation for com.google.inject.assistedinject."
            + "FactoryProvider2Test$ProviderBasedColoredCarFactory was bound.");
    }
  }

  interface JavaxProviderBasedColoredCarFactory {
    Car createCar(javax.inject.Provider<Color> colorProvider, javax.inject.Provider 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) {
      assertEquals(expected.getMessage(), 4, expected.getErrorMessages().size());
      assertContains(expected.getMessage(),
          ") 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<" + Color.class.getName() + ">] on method ["
            + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]");
      assertContains(expected.getMessage(),
          ") 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()]");
      assertContains(expected.getMessage(),
          ") 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<" + Color.class.getName() + ">"
            + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]"
            + " on method [" + JavaxProviderBasedColoredCarFactory.class.getName() + ".createMustang()]"
      );
      assertContains(expected.getMessage(),
          ") No implementation for com.google.inject.assistedinject."
            + "FactoryProvider2Test$JavaxProviderBasedColoredCarFactory was bound.");
    }
  }

  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() {
      @Override
      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 " + Color.class.getName() + " 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 mustangTypeLiteral
        = new TypeLiteral<GenericColoredCarFactory() {};
    final TypeLiteral<GenericColoredCarFactory camaroTypeLiteral
        = new TypeLiteral<GenericColoredCarFactory() {};

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

  @SuppressWarnings("unused")
  public interface Insurance<T extends Car> {
  }

  public static class MustangInsurance implements Insurance<Mustang> {
    private final double premium;
    private final double limit;
    @SuppressWarnings("unused") 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;
    @SuppressWarnings("unused") 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 mustangInsuranceFactoryType =
        new TypeLiteral<InsuranceFactory() {};
    final TypeLiteral<InsuranceFactory camaroInsuranceFactoryType =
        new TypeLiteral<InsuranceFactory() {};

    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 {
    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 camaroInsuranceFactoryType =
        new TypeLiteral<InsuranceFactory() {};

    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() {}));
      }
    });

    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());
  }
  
  public void testDuplicateAssistedFactoryBinding() {
    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));
        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 interface Equals {

    enum ComparisonMethod { SHALLOW, DEEP; }

    interface Factory {
      Equals equals(Equals.ComparisonMethod comparisonMethod);
    }

    public static class Impl implements Equals {
      private final double sigma;
      private final ComparisonMethod comparisonMethod;

      @AssistedInject
      public Impl(double sigma, @Assisted ComparisonMethod comparisonMethod) {
        this.sigma = sigma;
        this.comparisonMethod = comparisonMethod;
      }
    }
  }

  public void testFactoryMethodCalledEquals() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).toInstance(0.01d);
        bind(Equals.Factory.class).toProvider(
            FactoryProvider.newFactory(Equals.Factory.class, Equals.Impl.class));
      }
    });
    Equals.Factory equalsFactory = injector.getInstance(Equals.Factory.class);
    Equals.Impl shallowEquals = (Impl) equalsFactory.equals(ComparisonMethod.SHALLOW);
    assertEquals(ComparisonMethod.SHALLOW, shallowEquals.comparisonMethod);
    assertEquals(0.01d, shallowEquals.sigma);
  }

  static class Segway implements Car {
    @Inject Injector injector;

    Color getColor() { return injector.getInstance(Key.get(Color.class, FactoryProvider2.DEFAULT_ANNOTATION)); }
  }

  public void testReturnValueMatchesParamValue() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      public void configure() {
        install(new FactoryModuleBuilder().build(Delegater.Factory.class));
      }
    });
    Delegater delegate = new Delegater();
    Delegater user = injector.getInstance(Delegater.Factory.class).create(delegate);
    assertSame(delegate, user.delegate);
  }

  static class Delegater {
    interface Factory {
      Delegater create(Delegater delegate);
    }

    private final Delegater delegate;

    @Inject Delegater(@Assisted Delegater delegater) {
      this.delegate = delegater;
    }

    Delegater() {
      this.delegate = null;
    }
  }

  public static abstract class AbstractAssisted {
    interface Factory<O extends AbstractAssisted, I extends CharSequence> {
      O create(I string);
    }
  }

  static class ConcreteAssisted extends AbstractAssisted {
    @Inject ConcreteAssisted(@SuppressWarnings("unused") @Assisted String string) {}
  }

  static class ConcreteAssistedWithOverride extends AbstractAssisted {
    @AssistedInject
    ConcreteAssistedWithOverride(@SuppressWarnings("unused") @Assisted String string) {}

    @AssistedInject
    ConcreteAssistedWithOverride(@SuppressWarnings("unused") @Assisted StringBuilder sb) {}

    interface Factory extends AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> {
      @Override ConcreteAssistedWithOverride create(String string);
    }

    interface Factory2 extends AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> {
      @Override ConcreteAssistedWithOverride create(String string);
      ConcreteAssistedWithOverride create(StringBuilder sb);
    }
  }

  static class ConcreteAssistedWithoutOverride extends AbstractAssisted {
    @Inject ConcreteAssistedWithoutOverride(@SuppressWarnings("unused") @Assisted String string) {}
    interface Factory extends AbstractAssisted.Factory<ConcreteAssistedWithoutOverride, String> {}
  }

  public static class Public extends AbstractAssisted {
    @AssistedInject Public(@SuppressWarnings("unused") @Assisted String string) {}
    @AssistedInject Public(@SuppressWarnings("unused") @Assisted StringBuilder sb) {}

    public interface Factory extends AbstractAssisted.Factory<Public, String> {
      @Override Public create(String string);
      Public create(StringBuilder sb);
    }
  }

  // See https://github.com/google/guice/issues/904
  public void testGeneratedDefaultMethodsForwardCorrectly() {
    final Key<AbstractAssisted.Factory concreteKey =
        new Key<AbstractAssisted.Factory() {};
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        install(new FactoryModuleBuilder().build(ConcreteAssistedWithOverride.Factory.class));
        install(new FactoryModuleBuilder().build(ConcreteAssistedWithOverride.Factory2.class));
        install(new FactoryModuleBuilder().build(ConcreteAssistedWithoutOverride.Factory.class));
        install(new FactoryModuleBuilder().build(Public.Factory.class));
        install(new FactoryModuleBuilder().build(concreteKey));
      }
    });

    ConcreteAssistedWithOverride.Factory factory1 =
        injector.getInstance(ConcreteAssistedWithOverride.Factory.class);
    factory1.create("foo");
    AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> factory1Abstract = factory1;
    factory1Abstract.create("foo");

    ConcreteAssistedWithOverride.Factory2 factory2 =
        injector.getInstance(ConcreteAssistedWithOverride.Factory2.class);
    factory2.create("foo");
    factory2.create(new StringBuilder("foo"));
    AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> factory2Abstract = factory2;
    factory2Abstract.create("foo");

    ConcreteAssistedWithoutOverride.Factory factory3 =
        injector.getInstance(ConcreteAssistedWithoutOverride.Factory.class);
    factory3.create("foo");
    AbstractAssisted.Factory<ConcreteAssistedWithoutOverride, String> factory3Abstract = factory3;
    factory3Abstract.create("foo");

    Public.Factory factory4 = injector.getInstance(Public.Factory.class);
    factory4.create("foo");
    factory4.create(new StringBuilder("foo"));
    AbstractAssisted.Factory<Public, String> factory4Abstract = factory4;
    factory4Abstract.create("foo");

    AbstractAssisted.Factory<ConcreteAssisted, String> factory5 =
        injector.getInstance(concreteKey);
    factory5.create("foo");
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java FactoryProvider2Test.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.