Package se.jbee.inject.bind

Source Code of se.jbee.inject.bind.TestConfigurationDependentBinds

package se.jbee.inject.bind;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static se.jbee.inject.Dependency.dependency;
import static se.jbee.inject.Instance.anyOf;
import static se.jbee.inject.Name.named;
import static se.jbee.inject.Name.namedInternal;
import static se.jbee.inject.Type.raw;
import static se.jbee.inject.bootstrap.Configuring.configuring;
import static se.jbee.inject.bootstrap.Inspect.methodsReturn;
import static se.jbee.inject.util.Typecast.providerTypeOf;

import org.junit.Test;

import se.jbee.inject.Dependency;
import se.jbee.inject.Injector;
import se.jbee.inject.Name;
import se.jbee.inject.bind.TestInspectorBinds.Resource;
import se.jbee.inject.bootstrap.Bootstrap;
import se.jbee.inject.bootstrap.BootstrapperBundle;
import se.jbee.inject.bootstrap.Configuring;
import se.jbee.inject.util.Provider;
import se.jbee.inject.util.Scoped;

/**
* This test demonstrates how to switch between different implementations during runtime dependent
* on a setting in some configuration object.
*
* @author Jan Bernitt (jan@jbee.se)
*/
public class TestConfigurationDependentBinds {

  private static interface Validator {

    boolean valid( String input );
  }

  private static enum ValidationStrength {
    PERMISSIVE,
    STRICT
  }

  private static class Permissive
      implements Validator {

    @Override
    public boolean valid( String input ) {
      return true; // just for testing
    }

  }

  private static class Strict
      implements Validator {

    @Override
    public boolean valid( String input ) {
      return false; // just for testing
    }

  }

  private static class Configuration {

    private ValidationStrength validationStrength;
    private Integer number;

    /**
     * Will be detected as service method and thereby used
     */
    @SuppressWarnings ( "unused" )
    public ValidationStrength getValidationStrength() {
      return validationStrength;
    }

    public void setValidationStrength( ValidationStrength validationStrength ) {
      this.validationStrength = validationStrength;
    }

    /**
     * Will be detected as service method and thereby used
     */
    @Resource ( "answer" )
    public Integer getNumber() {
      return number;
    }

    public void setNumber( Integer number ) {
      this.number = number;
    }

  }

  /*
   * Module and Bundle code to setup scenario
   */

  /**
   * This module demonstrates CDI on a low level using general binds.
   */
  private static class ConfigurationDependentBindsModule
      extends BinderModule {

    @Override
    protected void declare() {
      per( Scoped.INJECTION ).bind( Validator.class ).to(
          configuring( anyOf( ValidationStrength.class ) ) );
      bind( namedInternal( (ValidationStrength) null ), Validator.class ).to(
          Permissive.class );
      bind( namedInternal( ValidationStrength.PERMISSIVE ), Validator.class ).to(
          Permissive.class );
      bind( namedInternal( ValidationStrength.STRICT ), Validator.class ).to( Strict.class );

      // the below is just *a* example - it is just important to provide the 'value' per injection
      per( Scoped.INJECTION ).bind( methodsReturn( raw( ValidationStrength.class ) ) ).in(
          Configuration.class );
    }
  }

  /**
   * The same as above using {@link #configbind(Class)}s. The important difference is that it is
   * not required to manually bind to a {@link Configuring} value. This is done implicitly with
   * each of the configbind calls. This also allow to use them in different modules without
   * causing clashes.
   *
   * @author Jan Bernitt (jan@jbee.se)
   */
  private static class ConfigurationDependentBindsModule2
      extends BinderModule {

    @Override
    protected void declare() {
      configbind( Validator.class ).on( ValidationStrength.PERMISSIVE ).to( Permissive.class );
      configbind( Validator.class ).on( ValidationStrength.STRICT ).to( Strict.class );
      configbind( Validator.class ).onOther( ValidationStrength.class ).to( Permissive.class );

      // the below is just *a* example - it is just important to provide the 'value' per injection
      per( Scoped.INJECTION ).bind( methodsReturn( raw( ValidationStrength.class ) ) ).in(
          Configuration.class );
    }

  }

  private static class ConfigurationDependentBindsModule3
      extends BinderModule {

    @Override
    protected void declare() {
      Name answer = named( "answer" );
      ConfigBinder<String> bind = configbind( String.class );
      bind.on( answer, 42 ).to( "Now it is 42" );
      bind.on( answer, 7 ).to( "Now it is 7" );
      bind.onOther( answer, Integer.class ).to( "Default is undefined" );

      // the below is just *a* example - it is just important to provide the 'value' per injection
      per( Scoped.INJECTION ).bind(
          methodsReturn( raw( int.class ) ).namedBy( Resource.class ) ).in(
          Configuration.class );
    }

  }

  private static class ConfigurationDependentBindsBundle
      extends BootstrapperBundle {

    @Override
    protected void bootstrap() {
      install( ConfigurationDependentBindsModule.class );
      install( BuildinBundle.PROVIDER );
    }

  }

  @Test
  public void thatReconfigurationIsResolvedToAnotherImplementation() {
    Injector injector = Bootstrap.injector( ConfigurationDependentBindsModule.class );
    assertReconfigurationIsResolvedToAnotherImplementation( injector );
  }

  @Test
  public void thatReconfigurationIsResolvedToAnotherImplementation2() {
    Injector injector = Bootstrap.injector( ConfigurationDependentBindsModule2.class );
    assertReconfigurationIsResolvedToAnotherImplementation( injector );
  }

  private static void assertReconfigurationIsResolvedToAnotherImplementation( Injector injector ) {
    Dependency<Validator> dependency = dependency( Validator.class );
    Configuration config = injector.resolve( dependency( Configuration.class ) );
    Validator v = injector.resolve( dependency );
    String input = "input";
    assertTrue( v.valid( input ) ); // default was PERMISSIVE
    config.setValidationStrength( ValidationStrength.STRICT );
    v = injector.resolve( dependency );
    assertFalse( v.valid( input ) ); // STRICT
    config.setValidationStrength( ValidationStrength.PERMISSIVE );
    v = injector.resolve( dependency );
    assertTrue( v.valid( input ) ); // PERMISSIVE
  }

  @Test
  public void thatReconfigurationIsProvidedToAnotherImplementation() {
    Injector injector = Bootstrap.injector( ConfigurationDependentBindsBundle.class );
    Configuration config = injector.resolve( dependency( Configuration.class ) );
    Provider<Validator> v = injector.resolve( dependency( providerTypeOf( Validator.class ) ) );
    String input = "input";
    assertTrue( v.provide().valid( input ) );
    config.setValidationStrength( ValidationStrength.STRICT );
    assertFalse( v.provide().valid( input ) );
    config.setValidationStrength( ValidationStrength.PERMISSIVE );
    assertTrue( v.provide().valid( input ) );
  }

  @Test
  public void thatReconfigurationResolvedUsingNamedInstances() {
    assertConfigNumberResolvedToStringEnding( null, "undefined" );
    assertConfigNumberResolvedToStringEnding( 7, "7" );
    assertConfigNumberResolvedToStringEnding( 42, "42" );
    assertConfigNumberResolvedToStringEnding( 123, "undefined" ); // equal to null
  }

  private static void assertConfigNumberResolvedToStringEnding( Integer configValue, String ending ) {
    Injector injector = Bootstrap.injector( ConfigurationDependentBindsModule3.class );
    Configuration config = injector.resolve( dependency( Configuration.class ) );
    config.setNumber( configValue );
    String v = injector.resolve( dependency( String.class ) );
    assertTrue( v.endsWith( ending ) );
  }
}
TOP

Related Classes of se.jbee.inject.bind.TestConfigurationDependentBinds

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.