All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.facebook.airlift.configuration.ConfigBinder Maven / Gradle / Ivy

There is a newer version: 0.216
Show newest version
package com.facebook.airlift.configuration;

import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.multibindings.Multibinder;

import java.lang.annotation.Annotation;
import java.util.Optional;

import static com.google.inject.multibindings.Multibinder.newSetBinder;
import static java.util.Objects.requireNonNull;

public class ConfigBinder
{
    public static ConfigBinder configBinder(Binder binder)
    {
        return new ConfigBinder(new GuiceConfigBinder(binder));
    }

    static ConfigBinder configBinder(ConfigurationFactory configurationFactory, Optional bindingSource)
    {
        return new ConfigBinder(new CallbackConfigBinder(configurationFactory, bindingSource));
    }

    public interface InternalConfigBinder
    {
         void bind(ConfigurationBinding configurationBinding);

         void bindConfigDefaults(ConfigDefaultsHolder configDefaultsHolder);

        void bindConfigurationBindingListener(ConfigurationBindingListener configurationBindingListener);
    }

    private static final class GuiceConfigBinder
            implements InternalConfigBinder
    {
        private final Binder binder;
        private Multibinder listenerMultibinder;

        public GuiceConfigBinder(Binder binder)
        {
            this.binder = requireNonNull(binder, "binder is null").skipSources(getClass(), ConfigBinder.class);
            this.listenerMultibinder = newSetBinder(binder, ConfigurationBindingListenerHolder.class);
        }

        @Override
        public  void bind(ConfigurationBinding configurationBinding)
        {
            Key key = configurationBinding.getKey();
            binder.bind(key).toProvider(new ConfigurationProvider<>(configurationBinding));
            createConfigDefaultsBinder(key);
        }

        @Override
        public  void bindConfigDefaults(ConfigDefaultsHolder configDefaultsHolder)
        {
            createConfigDefaultsBinder(configDefaultsHolder.getConfigKey()).addBinding().toInstance(configDefaultsHolder);
        }

        @Override
        public void bindConfigurationBindingListener(ConfigurationBindingListener configurationBindingListener)
        {
            listenerMultibinder.addBinding().toInstance(new ConfigurationBindingListenerHolder(configurationBindingListener));
        }

        private  Multibinder> createConfigDefaultsBinder(Key key)
        {
            TypeLiteral> typeLiteral = getTypeLiteral(key);

            if (key.getAnnotationType() == null) {
                return newSetBinder(binder, typeLiteral);
            }
            if (key.hasAttributes()) {
                return newSetBinder(binder, typeLiteral, key.getAnnotation());
            }
            return newSetBinder(binder, typeLiteral, key.getAnnotationType());
        }

        @SuppressWarnings("unchecked")
        private static  TypeLiteral> getTypeLiteral(Key key)
        {
            TypeToken typeToken = (TypeToken) TypeToken.of(key.getTypeLiteral().getType());
            return (TypeLiteral>)
                    TypeLiteral.get(new TypeToken>() {}
                            .where(new TypeParameter() {}, typeToken)
                            .getType());
        }
    }

    private static final class CallbackConfigBinder
            implements InternalConfigBinder
    {
        private final ConfigurationFactory configurationFactory;
        private final Optional bindingSource;

        public CallbackConfigBinder(ConfigurationFactory configurationFactory, Optional bindingSource)
        {
            this.configurationFactory = requireNonNull(configurationFactory, "configurationFactory is null");
            this.bindingSource = requireNonNull(bindingSource, "bindingSource is null");
        }

        @Override
        public  void bind(ConfigurationBinding configurationBinding)
        {
            configurationFactory.registerConfigurationProvider(new ConfigurationProvider<>(configurationBinding), bindingSource);
        }

        @Override
        public  void bindConfigDefaults(ConfigDefaultsHolder configDefaultsHolder)
        {
            configurationFactory.registerConfigDefaults(configDefaultsHolder);
        }

        @Override
        public void bindConfigurationBindingListener(ConfigurationBindingListener configurationBindingListener)
        {
            configurationFactory.addConfigurationBindingListener(configurationBindingListener);
        }
    }

    private final InternalConfigBinder binder;

    private ConfigBinder(InternalConfigBinder binder)
    {
        this.binder = requireNonNull(binder, "binder is null");
    }

    public  void bindConfig(Class configClass)
    {
        requireNonNull(configClass, "configClass is null");

        bindConfig(Key.get(configClass), configClass, null);
    }

    public  void bindConfig(Class configClass, Annotation annotation)
    {
        requireNonNull(configClass, "configClass is null");
        requireNonNull(annotation, "annotation is null");

        bindConfig(Key.get(configClass, annotation), configClass, null);
    }

    public  void bindConfig(Class configClass, Class annotation)
    {
        requireNonNull(configClass, "configClass is null");
        requireNonNull(annotation, "annotation is null");

        bindConfig(Key.get(configClass, annotation), configClass, null);
    }

    public  void bindConfig(Class configClass, String prefix)
    {
        requireNonNull(configClass, "configClass is null");

        bindConfig(Key.get(configClass), configClass, prefix);
    }

    public  void bindConfig(Class configClass, Annotation annotation, String prefix)
    {
        requireNonNull(configClass, "configClass is null");
        requireNonNull(annotation, "annotation is null");

        bindConfig(Key.get(configClass, annotation), configClass, prefix);
    }

    public  void bindConfig(Class configClass, Class annotation, String prefix)
    {
        requireNonNull(configClass, "configClass is null");
        requireNonNull(annotation, "annotation is null");

        bindConfig(Key.get(configClass, annotation), configClass, prefix);
    }

    public  void bindConfig(Key key, Class configClass, String prefix)
    {
        binder.bind(new ConfigurationBinding<>(key, configClass, Optional.ofNullable(prefix)));
    }

    public  void bindConfigDefaults(Class configClass, ConfigDefaults configDefaults)
    {
        requireNonNull(configClass, "configClass is null");
        requireNonNull(configDefaults, "configDefaults is null");

        bindConfigDefaults(Key.get(configClass), configDefaults);
    }

    public  void bindConfigDefaults(Class configClass, Annotation annotation, ConfigDefaults configDefaults)
    {
        requireNonNull(configClass, "configClass is null");
        requireNonNull(annotation, "annotation is null");
        requireNonNull(configDefaults, "configDefaults is null");

        bindConfigDefaults(Key.get(configClass, annotation), configDefaults);
    }

    public  void bindConfigDefaults(Class configClass, Class annotation, ConfigDefaults configDefaults)
    {
        requireNonNull(configClass, "configClass is null");
        requireNonNull(annotation, "annotation is null");
        requireNonNull(configDefaults, "configDefaults is null");

        bindConfigDefaults(Key.get(configClass, annotation), configDefaults);
    }

    public  void bindConfigDefaults(Key key, ConfigDefaults configDefaults)
    {
        binder.bindConfigDefaults(new ConfigDefaultsHolder<>(key, configDefaults));
    }

    /**
     * Binds default values for all the instances of given config class for the current binder
     */
    public  void bindConfigGlobalDefaults(Class configClass, ConfigDefaults configDefaults)
    {
        Key key = Key.get(configClass, GlobalDefaults.class);
        binder.bindConfigDefaults(new ConfigDefaultsHolder<>(key, configDefaults));
    }

    /**
     * Binds a configuration binding listener that can create additional config bindings.
     */
    public void bindConfigurationBindingListener(ConfigurationBindingListener configurationBindingListener)
    {
        binder.bindConfigurationBindingListener(configurationBindingListener);
    }
}