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

fi.jubic.easyconfig.internal.initializers.SetterInitializerParser Maven / Gradle / Ivy

There is a newer version: 0.10.4
Show newest version
package fi.jubic.easyconfig.internal.initializers;

import fi.jubic.easyconfig.internal.ConfigPropertyDef;
import fi.jubic.easyconfig.internal.MappingContext;
import fi.jubic.easyconfig.internal.Result;
import fi.jubic.easyconfig.internal.parameter.Mappable;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class SetterInitializerParser implements InitializerParser {
    @Override
    public  Optional>> parse(
            MappingContext context,
            ConfigPropertyDef propertyDef
    ) {
        Class propertyClass = propertyDef.getPropertyClass();

        //noinspection unchecked
        Constructor[] allConstructors = (Constructor[]) propertyClass.getConstructors();

        List setters = Stream.of(propertyClass.getMethods())
                .filter(method -> SUPPORTED_PROPERTY_ANNOTATIONS.stream()
                        .map(method::getAnnotation)
                        .anyMatch(Objects::nonNull)
                )
                .filter(method -> method.getReturnType().equals(void.class))
                .filter(method -> method.getParameterCount() == 1)
                .collect(Collectors.toList());

        if (setters.isEmpty()) {
            return Optional.empty();
        }

        Optional> optionalDefaultConstructor = Stream.of(allConstructors)
                .filter(constructor -> constructor.getParameterCount() == 0)
                .findFirst();
        if (!optionalDefaultConstructor.isPresent()) {
            return Optional.empty();
        }
        Constructor defaultConstructor = optionalDefaultConstructor.get();

        MappingContext currentContext = context.push(
                String.format(
                        "%s (setter initializer)",
                        propertyClass.getCanonicalName()
                )
        );

        Result>> parametersResult = setters.stream()
                .map(setter -> {
                    Parameter parameter = setter.getParameters()[0];
                    return PARAMETER_PARSER
                            .parseParameter(
                                    currentContext.subContext(),
                                    ConfigPropertyDef.buildForParameter(parameter, setter)
                                            .orElseThrow(IllegalStateException::new)
                            )
                            .orElseGet(() -> Result.message(
                                    currentContext.format(
                                            String.format(
                                                    "No parsed found for %s",
                                                    parameter.getClass().getCanonicalName()
                                            )
                                    )
                            ));
                })
                .collect(
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                Result::unwrap
                        )
                );

        Result> initializer = parametersResult.map(
                parameters -> (prefix, envProvider) -> Result
                        .unwrap(
                                parameters.stream()
                                        .map(parameter -> parameter.initialize(prefix, envProvider))
                                        .collect(Collectors.toList())
                        )
                        .flatMap(initializedParameters -> {
                            MappingContext initializationContext = new MappingContext(
                                    String.format(
                                            "%s (setter initializer)",
                                            propertyClass.getCanonicalName()
                                    )
                            );

                            T instance;
                            try {
                                instance = defaultConstructor.newInstance();
                            }
                            catch (InstantiationException
                                    | IllegalAccessException
                                    | InvocationTargetException e
                            ) {
                                return Result.message(
                                        initializationContext.format(
                                                "Could not initialize instance"
                                        ),
                                        e
                                );
                            }

                            for (int i = 0; i < initializedParameters.size(); i++) {
                                try {
                                    setters.get(i)
                                            .invoke(
                                                    instance,
                                                    initializedParameters.get(i)
                                            );
                                }
                                catch (IllegalAccessException | InvocationTargetException e) {
                                    return Result.message(
                                            initializationContext.format(
                                                    String.format(
                                                            "Could not invoke setter %s",
                                                            setters.get(i).getName()
                                                    )
                                            ),
                                            e
                                    );
                                }
                            }
                            return Result.of(instance);
                        })
        );
        return Optional.of(initializer);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy