/**
  * Binds hk {@link Factory}. If bean is {@link HK2Managed} then registered directly as factory.
  * Otherwise register factory through special "lazy bridge" to delay guice factory bean
  * instantiation. Also registers factory directly (through wrapper to be able to inject factory by
  * its type).
  *
  * @param binder hk binder
  * @param injector guice injector
  * @param type factory to bind
  * @param <T> actual type (used to workaround type checks)
  * @see ru.vyarus.dropwizard.guice.module.jersey.support.LazyGuiceFactory
  * @see ru.vyarus.dropwizard.guice.module.jersey.support.GuiceComponentFactory
  */
 @SuppressWarnings("unchecked")
 public static <T> void bindFactory(
     final AbstractBinder binder, final Injector injector, final Class<?> type) {
   // resolve Factory<T> actual type to bind properly
   final Class<T> res = (Class<T>) GenericsResolver.resolve(type).type(Factory.class).generic(0);
   if (isHK2Managed(type)) {
     binder.bindFactory((Class<Factory<T>>) type).to(res).in(Singleton.class);
   } else {
     binder.bindFactory(new LazyGuiceFactory(injector, type)).to(res);
     // binding factory type to be able to autowire factory by name
     binder.bindFactory(new GuiceComponentFactory(injector, type)).to(type);
   }
 }
 /**
  * Binds component into HK context. If component is annotated with {@link HK2Managed}, then
  * registers type, otherwise register guice "bridge" factory around component.
  *
  * @param binder hk binder
  * @param injector guice injector
  * @param type component type
  * @see ru.vyarus.dropwizard.guice.module.jersey.support.GuiceComponentFactory
  */
 @SuppressWarnings("unchecked")
 public static void bindComponent(
     final AbstractBinder binder, final Injector injector, final Class<?> type) {
   if (isHK2Managed(type)) {
     binder.bind(type).in(Singleton.class);
   } else {
     // default case: simple service registered directly (including resource)
     binder.bindFactory(new GuiceComponentFactory(injector, type)).to(type);
   }
 }
 /**
  * Binds jersey specific component (component implements jersey interface or extends class).
  * Specific binding is required for types directly supported by jersey (e.g. ExceptionMapper).
  * Such types must be bound to target interface directly, otherwise jersey would not be able to
  * resolve them.
  *
  * <p>If type is {@link HK2Managed}, binds directly. Otherwise, use guice "bridge" factory to
  * lazily bind type.
  *
  * <p>Shortcut methods provided for most common cases.
  *
  * @param binder hk binder
  * @param injector guice injector
  * @param type type which implements specific jersey interface or extends class
  * @param specificType specific jersey type (interface or abstract class)
  * @see #bindExceptionMapper(AbstractBinder, Injector, Class)
  * @see #bindInjectionResolver(AbstractBinder, Injector, Class)
  * @see #bindValueFactoryProvider(AbstractBinder, Injector, Class)
  */
 @SuppressWarnings("unchecked")
 public static void bindSpecificComponent(
     final AbstractBinder binder,
     final Injector injector,
     final Class<?> type,
     final Class<?> specificType) {
   // resolve generics of specific type
   final GenericsContext context = GenericsResolver.resolve(type).type(specificType);
   final List<Type> genericTypes = context.genericTypes();
   final Type[] generics = genericTypes.toArray(new Type[genericTypes.size()]);
   final Type binding =
       generics.length > 0 ? new ParameterizedTypeImpl(specificType, generics) : specificType;
   if (isHK2Managed(type)) {
     binder.bind(type).to(binding).in(Singleton.class);
   } else {
     binder.bindFactory(new GuiceComponentFactory(injector, type)).to(type).in(Singleton.class);
     binder.bind(type).to(binding).in(Singleton.class);
   }
 }