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

nl.vpro.guice.OptionalModule Maven / Gradle / Ivy

There is a newer version: 5.3.3
Show newest version
package nl.vpro.guice;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.*;
import java.time.Duration;
import java.util.Optional;

import jakarta.inject.Named;

import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.multibindings.OptionalBinder;
import com.google.inject.name.Names;

import nl.vpro.util.DefaultValue;
import nl.vpro.util.TimeUtils;

/**
 @ Uses {@link OptionalBinder} to provide null's or @DefaultValue's for @Named parameters of the type Optional
 * @author Michiel Meeuwissen
 * @since 1.69
 */
@Slf4j
public class OptionalModule extends AbstractModule {

    private final Class[] classes;

    public OptionalModule(Class... classes) {
        this.classes = classes;
    }

    @Override
    protected void configure() {
        configure(binder(), classes);
    }


    public static void configure(Binder binder, Class... classes) {
        for (Class clazz : classes) {
            for (Field f : clazz.getDeclaredFields()) {
                bind(binder, f, f.getType(), f.getGenericType());
            }
            for (Constructor c : clazz.getConstructors()) {
                for (Parameter parameter : c.getParameters())  {
                    bind(binder, parameter, parameter.getType(), parameter.getParameterizedType());
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    protected static void bind(Binder binder, AnnotatedElement f, Class type, Type parameterizedType) {
        if (Optional.class.isAssignableFrom(type)) {
            try {
                OptionalBinder optionalBinder;
                Class valueClass = Class.forName(((ParameterizedType) parameterizedType).getActualTypeArguments()[0].getTypeName());
                Named annotation = f.getAnnotation(Named.class);
                if (annotation != null) {
                    String name = annotation.value();
                    optionalBinder = OptionalBinder.newOptionalBinder(binder, Key.get(valueClass, Names.named(name)));
                } else {
                    optionalBinder = OptionalBinder.newOptionalBinder(binder, valueClass);
                }
                DefaultValue defaultValue = f.getAnnotation(DefaultValue.class);
                if (defaultValue != null) {
                    String value = defaultValue.value();
                    // TODO don't we have access to guice type convertors?
                    if (valueClass.isInstance(value)) {
                        optionalBinder.setDefault().toInstance(value);
                    } else if (Duration.class.isAssignableFrom(valueClass)) {
                        optionalBinder.setDefault().toInstance(TimeUtils.parseDuration(value).orElse(null));

                    }
                }
            } catch (ClassNotFoundException e) {
                log.error(e.getMessage(), e);
            }
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy