Package se.jbee.inject.service

Source Code of se.jbee.inject.service.TestServiceBinds$Service

package se.jbee.inject.service;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static se.jbee.inject.Dependency.dependency;
import static se.jbee.inject.Type.raw;

import org.junit.Test;

import se.jbee.inject.Dependency;
import se.jbee.inject.Injector;
import se.jbee.inject.Supplier;
import se.jbee.inject.Type;
import se.jbee.inject.bootstrap.Bootstrap;

public class TestServiceBinds {

  /**
   * Think of this as an application specific service interface that normally would have been
   * defined within your application code. This is what 'your' code asks for whereby you don't get
   * any dependencies pointing in direction of the DI framework inside your normal application
   * code. The only place you are coupled to the DI-framework is still in the binding code that is
   * additional to the application code.
   */
  private static interface Service<P, R> {

    R calc( P param );
  }

  /**
   * This is an adapter to 'your' application specific service interface adapting to the
   * {@link ServiceMethod} interface of the DI-framework. So internally both are resolvable.
   */
  private static class ServiceSupplier
      implements Supplier<Service<?, ?>> {

    @Override
    public Service<?, ?> supply( Dependency<? super Service<?, ?>> dependency, Injector injector ) {
      ServiceProvider provider = injector.resolve( dependency( ServiceProvider.class ) );
      Type<? super Service<?, ?>> type = dependency.getType();
      return newService( provider.provide( type.parameter( 0 ), type.parameter( 1 ) ) );
    }

    private static <P, R> Service<P, R> newService( ServiceMethod<P, R> service ) {
      return new ServiceToServiceMethodAdapter<P, R>( service );
    }

    static class ServiceToServiceMethodAdapter<P, R>
        implements Service<P, R> {

      private final ServiceMethod<P, R> service;

      ServiceToServiceMethodAdapter( ServiceMethod<P, R> service ) {
        super();
        this.service = service;
      }

      @Override
      public R calc( P param ) {
        return service.invoke( param );
      }

    }

  }

  private static class ServiceBindsModule
      extends ServiceModule {

    @Override
    protected void declare() {
      bindServiceMethodsIn( MathService.class );
      starbind( Service.class ).toSupplier( ServiceSupplier.class );
    }

  }

  static class MathService {

    Long square( Integer value ) {
      return value.longValue() * value;
    }
  }

  @Test
  public void thatServiceCanBeResolvedWhenHavingGenericsInSameOrder() {
    Injector injector = Bootstrap.injector( ServiceBindsModule.class );
    @SuppressWarnings ( { "rawtypes" } )
    Dependency<Service> dependency = dependency( raw( Service.class ).parametized(
        Integer.class, Long.class ) );
    @SuppressWarnings ( "unchecked" )
    Service<Integer, Long> square = injector.resolve( dependency );
    assertThat( square.calc( 2 ), is( 4L ) );
  }

}
TOP

Related Classes of se.jbee.inject.service.TestServiceBinds$Service

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.