content: /**
   * 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 org.apache.aurora.common.inject;
  
  import java.lang.annotation.Annotation;
  
  import javax.inject.Qualifier;
  
  import com.google.common.base.Preconditions;
  import com.google.common.collect.ImmutableList;
  import com.google.inject.AbstractModule;
  import com.google.inject.Binder;
  import com.google.inject.BindingAnnotation;
  import com.google.inject.Key;
  import com.google.inject.Module;
  import com.google.inject.PrivateModule;
  import com.google.inject.TypeLiteral;
  
  /**
   * A utility that helps with guice bindings.
   *
   * @author John Sirois
   */
  public final class Bindings {
  
  
    private Bindings() {
      // utility
    }
  
    /**
     * Equivalent to calling {@code requireBinding(binder, Key.get(required))}.
     */
    public static void requireBinding(Binder binder, Class<?> required) {
      requireBinding(binder, Key.get(Preconditions.checkNotNull(required)));
    }
  
    /**
     * Registers {@code required} as non-optional dependency in the {@link com.google.inject.Injector}
     * associated with {@code binder}.
     *
     * @param binder A binder to require bindings against.
     * @param required The dependency that is required.
     */
    public static void requireBinding(Binder binder, final Key<?> required) {
      Preconditions.checkNotNull(binder);
      Preconditions.checkNotNull(required);
  
      binder.install(new AbstractModule() {
        @Override protected void configure() {
          requireBinding(required);
        }
      });
    }
  
    /**
     * A convenient version of {@link #exposing(Iterable, com.google.inject.Module)} when you just
     * want to expose a single binding.
     */
    public static Module exposing(Key<?> key, Module module) {
      return exposing(ImmutableList.of(key), module);
    }
  
    /**
     * Creates a module that hides all the given module's bindings and only exposes bindings for
     * the given key.
     *
     * @param keys The keys of the bindings to expose.
     * @param module The module to hide most bindings for.
     * @return A limited visibility module.
     */
    public static Module exposing(final Iterable<? extends Key<?>> keys, final Module module) {
      Preconditions.checkNotNull(keys);
      Preconditions.checkNotNull(module);
  
      return new PrivateModule() {
        @Override protected void configure() {
          install(module);
          for (Key<?> key : keys) {
            expose(key);
          }
        }
      };
    }
  
    /**
     * Checks that the given annotation type is a {@link BindingAnnotation @BindingAnnotation}.
     *
     * @param annotationType The annotation type to check.
     * @param <T> The type of the binding annotation.
     * @return The checked binding annotation type.
     * @throws NullPointerException If the given {@code annotationType} is null.
     * @throws IllegalArgumentException If the given {@code annotationType} is not a
     *     {@literal @BindingAnnotation}.
     */
    public static <T extends Annotation> Class<T> checkBindingAnnotation(Class<T> annotationType) {
      Preconditions.checkNotNull(annotationType);
      boolean bindingAnnotation = annotationType.isAnnotationPresent(BindingAnnotation.class);
      boolean qualifier = annotationType.isAnnotationPresent(Qualifier.class);
      Preconditions.checkArgument(bindingAnnotation || qualifier,
          "%s is not a @BindingAnnotation or @Qualifier", annotationType);
      return annotationType;
    }
  
    /**
     * A factory for binding {@link Key keys}.
     */
    public interface KeyFactory {
  
      /**
       * Creates plain un-annotated keys.
       */
      KeyFactory PLAIN = new KeyFactory() {
        @Override public <T> Key<T> create(Class<T> type) {
          return Key.get(type);
        }
        @Override public <T> Key<T> create(TypeLiteral<T> type) {
          return Key.get(type);
        }
      };
  
      /**
       * Creates a key for the given type.
       *
       * @param type The type to create a key for.
       * @param <T> The keyed type.
       * @return A key.
       */
      <T> Key<T> create(Class<T> type);
  
      /**
       * Creates a key for the given type.
       *
       * @param type The type to create a key for.
       * @param <T> The keyed type.
       * @return A key.
       */
      <T> Key<T> create(TypeLiteral<T> type);
    }
  
    /**
     * Creates a key factory that produces keys for a given annotation type.
     *
     * @param annotationType The annotation type to apply to all keys.
     * @return A key factory that creates annotated keys.
     */
    public static KeyFactory annotatedKeyFactory(final Class<? extends Annotation> annotationType) {
      checkBindingAnnotation(annotationType);
      return new KeyFactory() {
        @Override public <T> Key<T> create(Class<T> type) {
          return Key.get(type, annotationType);
        }
        @Override public <T> Key<T> create(TypeLiteral<T> type) {
          return Key.get(type, annotationType);
        }
      };
    }
  }
  