org.apache.aurora.common.inject.Bindings.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.aurora.common.inject.Bindings.java

Source

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