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

io.helidon.config.ConfigValues Maven / Gradle / Ivy

There is a newer version: 4.1.1
Show newest version
/*
 * Copyright (c) 2018, 2023 Oracle and/or its affiliates.
 *
 * 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 io.helidon.config;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import io.helidon.common.GenericType;

/**
 * Factory for config values.
 */
public final class ConfigValues {
    private ConfigValues() {
    }

    /**
     * Simple empty value that can be used e.g. for unit testing.
     * All ConfigValues use equals method that only cares about the optional value.
     *
     * @param  type of the value
     * @return a config value that is empty
     */
    public static  ConfigValue empty() {
        return new ConfigValueBase<>(Config.Key.create("")) {
            @Override
            public Optional asOptional() {
                return Optional.empty();
            }

            @Override
            public  ConfigValue as(Function mapper) {
                return empty();
            }

            @Override
            public  io.helidon.common.config.ConfigValue as(Class type) {
                return empty();
            }

            @Override
            public  io.helidon.common.config.ConfigValue as(GenericType type) {
                return empty();
            }

            @Override
            public Supplier supplier() {
                return () -> {
                    throw MissingValueException.create(key());
                };
            }

            @Override
            public Supplier supplier(T defaultValue) {
                return () -> defaultValue;
            }

            @Override
            public Supplier> optionalSupplier() {
                return Optional::empty;
            }

            @Override
            public String toString() {
                return "ConfigValue(empty)";
            }
        };
    }

    /**
     * Simple value that can be used e.g. for unit testing.
     * All ConfigValues use equals method that only cares about the optional value.
     *
     * @param value value to use
     * @param    type of the value
     * @return a config value that uses the value provided
     */
    public static  ConfigValue simpleValue(T value) {
        Config.Key key = Config.Key.create("");
        return new ConfigValueBase<>(key) {
            @Override
            public Optional asOptional() {
                return Optional.ofNullable(value);
            }

            @Override
            public  ConfigValue as(Function mapper) {
                return simpleValue(mapper.apply(value));
            }

            @Override
            public  io.helidon.common.config.ConfigValue as(Class type) {
                throw new ConfigMappingException(key, "Cannot map a simple value detached from configuration.");
            }

            @Override
            public  io.helidon.common.config.ConfigValue as(GenericType type) {
                throw new ConfigMappingException(key, "Cannot map a simple value detached from configuration.");
            }

            @Override
            public Supplier supplier() {
                return () -> value;
            }

            @Override
            public Supplier supplier(T defaultValue) {
                return () -> asOptional().orElse(defaultValue);
            }

            @Override
            public Supplier> optionalSupplier() {
                return this::asOptional;
            }

            @Override
            public String toString() {
                return "ConfigValue(" + value + ")";
            }
        };
    }

    static  ConfigValue create(Config config,
                                     Supplier> supplier,
                                     Function> configMethod) {
        return new GenericConfigValueImpl<>(config, supplier, configMethod);
    }

    static  ConfigValue create(Config config,
                                     Class type,
                                     ConfigMapperManager mapperManager) {

        return new GenericConfigValueImpl<>(config,
                                            () -> Optional.ofNullable(mapperManager.map(config, type)),
                                            aConfig -> aConfig.as(type));
    }

    static  ConfigValue create(Config config,
                                     GenericType genericType,
                                     ConfigMapperManager mapperManager) {
        return new GenericConfigValueImpl<>(config,
                                            () -> Optional.ofNullable(mapperManager.map(config, genericType)),
                                            aConfig -> aConfig.as(genericType));
    }

    static  ConfigValue create(Config config,
                                     Function mapper) {

        return new GenericConfigValueImpl<>(config,
                                            () -> Optional.ofNullable(mapper.apply(config)),
                                            aConfig -> aConfig.as(mapper));
    }

    static  ConfigValue> createList(Config config,
                                               Function> getValue,
                                               Function>> getListValue) {

        Supplier>> valueSupplier = () -> {
            try {
                return config.asNodeList()
                        .map(list -> list.stream()
                                .map(theConfig -> getValue.apply(theConfig).get())
                                .collect(Collectors.toList())
                        );
            } catch (MissingValueException | ConfigMappingException ex) {
                throw new ConfigMappingException(config.key(),
                                                 "Error to map complex node item to list. " + ex.getLocalizedMessage(),
                                                 ex);
            }
        };
        return new GenericConfigValueImpl<>(config, valueSupplier, getListValue);
    }

    static ConfigValue> createMap(Config config,
                                                             ConfigMapperManager mapperManager) {

        Supplier>> valueSupplier = () -> {
            Map map = mapperManager.map(config, Map.class);

            map = map.entrySet().stream().collect(
                    Collectors.toMap(
                            entry -> Config.Key.unescapeName(entry.getKey().toString()), entry -> entry.getValue()
                    )
            );
            if (map instanceof ConfigMappers.StringMap) {
                return Optional.of((ConfigMappers.StringMap) map);
            }
            return Optional.of(new ConfigMappers.StringMap(map));
        };

        return new GenericConfigValueImpl<>(config, valueSupplier, Config::asMap);
    }

    private abstract static class ConfigValueBase implements ConfigValue {
        private final Config.Key key;

        protected ConfigValueBase(Config.Key key) {
            this.key = key;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof ConfigValue) {
                return ((ConfigValue) obj).asOptional().equals(this.asOptional());
            }
            return false;
        }

        @Override
        public Config.Key key() {
            return key;
        }

        @Override
        public int hashCode() {
            return asOptional().hashCode();
        }
    }

    private static final class GenericConfigValueImpl extends ConfigValueBase {
        private final Supplier> valueSupplier;
        private final Function> configMethod;
        private final Config owningConfig;

        private GenericConfigValueImpl(Config owningConfig,
                                       Supplier> valueSupplier,
                                       Function> configMethod) {
            super(owningConfig.key());
            this.owningConfig = owningConfig;
            this.valueSupplier = valueSupplier;
            this.configMethod = configMethod;
        }

        @Override
        public Optional asOptional() {
            try {
                return valueSupplier.get();
            } catch (MissingValueException e) {
                return Optional.empty();
            }
        }

        @Override
        public  ConfigValue as(Class type) {
            return owningConfig.as(type);
        }

        @Override
        public  ConfigValue as(GenericType type) {
            return owningConfig.as(type);
        }


        @Override
        public Supplier supplier() {
            return () -> configMethod.apply(latest()).get();
        }

        @Override
        public Supplier supplier(T defaultValue) {
            return () -> configMethod.apply(latest()).orElse(defaultValue);
        }

        @Override
        public Supplier> optionalSupplier() {
            return () -> configMethod.apply(latest()).asOptional();
        }

        private Config latest() {
            return owningConfig.context().last();
        }

        @Override
        public  ConfigValue as(Function mapper) {
            return new GenericConfigValueImpl<>(owningConfig,
                                                () -> map(mapper),
                                                config -> configMethod.apply(config).as(mapper));
        }

        @Override
        public String toString() {
            return key() + ": " + asOptional().map(String::valueOf).orElse("");
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy