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

io.rxmicro.config.Config Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2020. https://rxmicro.io
 *
 * 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.rxmicro.config;

import java.util.List;

import static io.rxmicro.common.util.Strings.splitByCamelCase;
import static java.util.stream.Collectors.joining;

/**
 * The parent class for all config classes.
 *
 * @author nedis
 * @see ConfigSource
 * @since 0.1
 */
public abstract class Config {

    /**
     * Defines a character that used as list (set, sorted set, map entries) values delimiter.
     *
     * 

* Collection examples: * * propertyName1=value1,value2,value3 * * For such cases {@code propertyName1} can be converted to {@link List}{@code } * (or {@link java.util.Set}{@code } or {@link java.util.SortedSet}{@code } if possible) instance automatically. * *

* Map examples: * * propertyName2=key1=value1,key2=value2,key3=value3 * * For such cases {@code propertyName2} can be converted to {@link java.util.Map}{@code } instance automatically. */ public static final Character VALUES_DELIMITER = ','; /** * Defines a character that used as key-value map entry delimiter. * *

* For example: * * propertyName=key1=value1,key2=value2,key3=value3 * * For such cases {@code propertyName} can be converted to {@link java.util.Map}{@code } instance automatically. */ public static final Character KEY_VALUE_ENTRY_DELIMITER = '='; /** * Default name for config file or class path resource without extension. * *

* This name used by {@link ConfigSource#RXMICRO_CLASS_PATH_RESOURCE} or * {@link ConfigSource#RXMICRO_FILE_AT_THE_HOME_DIR} or * {@link ConfigSource#RXMICRO_FILE_AT_THE_RXMICRO_CONFIG_DIR} or * {@link ConfigSource#RXMICRO_FILE_AT_THE_CURRENT_DIR}. */ public static final String RX_MICRO_CONFIG_FILE_NAME = "rxmicro"; /** * Allows defining the prefix name that will be used for all environment variable source for configs. * *

* The RxMicro framework allows using the environment variables for configuring the config instances. * By default the ${namespace}.${propertyName}=${propertyValue} format is used. * *

* But some tools add the additional restrictions for environment variables: * *

* Environment variable names used by the utilities in the Shell and Utilities volume of IEEE Std 1003.1-2001 consist solely of * uppercase letters, digits, and the '_' (underscore) from the characters defined in Portable Character Set and do not begin with * a digit. Other characters may be permitted by an implementation; applications shall tolerate the presence of such names. * *

* So the RxMicro framework must support both: *

    *
  • {@code export TEST_CONFIG_CLASS_PROPERTY_NAME=value}
  • *
  • {@code export test-config-class.propertyName=value}
  • *
* environment variable names for the {@code propertyName} that defined at the {@code TestConfigClassConfig} class. * *

* If {@value #RX_MICRO_CONFIG_ENVIRONMENT_VARIABLE_PREFIX} is defined the RxMicro framework will expect the following * environment variable name for the {@code propertyName} that defined at the {@code TestConfigClassConfig} class: * {@code export ${RX_MICRO_CONFIG_ENVIRONMENT_VARIABLE_PREFIX}_TEST_CONFIG_CLASS_PROPERTY_NAME=value} */ public static final String RX_MICRO_CONFIG_ENVIRONMENT_VARIABLE_PREFIX = "RX_MICRO_CONFIG_ENVIRONMENT_VARIABLE_PREFIX"; /** * Default name for config directory. * *

* This name used by {@link ConfigSource#SEPARATE_FILE_AT_THE_RXMICRO_CONFIG_DIR} or * {@link ConfigSource#RXMICRO_FILE_AT_THE_RXMICRO_CONFIG_DIR}. */ public static final String RX_MICRO_CONFIG_DIRECTORY_NAME = ".rxmicro"; private static final String AS_MAP_CONFIG_NAME = AsMapConfig.class.getSimpleName(); private static final String CONFIG_NAME = Config.class.getSimpleName(); /** * Defines the default namespace for the config class. * * @param configClass the config class * @return the default namespace */ public static String getDefaultNameSpace(final Class configClass) { return getDefaultNameSpace(configClass.getSimpleName()); } /** * Defines the default namespace for config simple class name (without package). * * @param configSimpleClassName the config simple class name * @return the default namespace */ public static String getDefaultNameSpace(final String configSimpleClassName) { final List words = splitByCamelCase(getValidConfigSimpleClassName(configSimpleClassName)); return words.stream() .map(String::toLowerCase) .collect(joining("-")); } private static String getValidConfigSimpleClassName(final String name) { if (name.endsWith(AS_MAP_CONFIG_NAME)) { return name.substring(0, name.length() - AS_MAP_CONFIG_NAME.length()); } else if (name.endsWith(CONFIG_NAME)) { return name.substring(0, name.length() - CONFIG_NAME.length()); } else { return name; } } /** * Returns the default namespace for config instance. * * @return the default namespace for config instance */ public String getNameSpace() { return getDefaultNameSpace(getClass()); } /** * Validates the config instance state after injection all properties. * *

* By default this implementation joins exceptions returned by {@link #getAllFoundConfigExceptions(String)} method and * throws a single {@link ConfigException} instance with joined messages and suppressed stacktraces. * *

* Note: If it is necessary to interrupt the launching of microservice as soon as possible, * You must override {@link #validate(String)} method instead of {@link #getAllFoundConfigExceptions(String)} one! * *

* Note: If it is necessary to view all detected config errors per config instance, * You must override {@link #getAllFoundConfigExceptions(String)} method instead of {@link #validate(String)} one! * * @param namespace the config namespace * @throws ConfigException if current config instance has invalid state * @see #getAllFoundConfigExceptions(String) */ protected void validate(final String namespace) { final List exceptions = getAllFoundConfigExceptions(namespace); if (!exceptions.isEmpty()) { final ConfigException exception = new ConfigException( "'?' config contains the following validation errors:\n?", namespace, exceptions.stream().map(Throwable::getMessage).collect(joining("\n")) ); exceptions.forEach(exception::addSuppressed); throw exception; } } /** * Returns the exception list that must be joined to the single {@link ConfigException} instance. * * @param namespace the config namespace * @return the exception list that must be joined to the single {@link ConfigException} instance. * @see #validate(String) */ protected List getAllFoundConfigExceptions(final String namespace) { return List.of(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy