11package de .exlll .configlib ;
22
33import java .lang .reflect .Type ;
4- import java .util .Collections ;
5- import java .util .HashMap ;
6- import java .util .LinkedHashMap ;
7- import java .util .Map ;
4+ import java .util .*;
85import java .util .function .Function ;
96import java .util .function .Predicate ;
107import java .util .function .UnaryOperator ;
@@ -28,6 +25,7 @@ public class ConfigurationProperties {
2825 private final boolean outputNulls ;
2926 private final boolean inputNulls ;
3027 private final boolean serializeSetsAsLists ;
28+ private final EnvVarResolutionConfiguration envVarResolutionConfiguration ;
3129
3230 /**
3331 * Constructs a new instance of this class with values taken from the given builder.
@@ -49,6 +47,10 @@ protected ConfigurationProperties(Builder<?> builder) {
4947 this .outputNulls = builder .outputNulls ;
5048 this .inputNulls = builder .inputNulls ;
5149 this .serializeSetsAsLists = builder .serializeSetsAsLists ;
50+ this .envVarResolutionConfiguration = requireNonNull (
51+ builder .envVarResolutionConfiguration ,
52+ "environment variable resolution configuration"
53+ );
5254 }
5355
5456 /**
@@ -100,9 +102,18 @@ public static abstract class Builder<B extends Builder<B>> {
100102 private boolean outputNulls = false ;
101103 private boolean inputNulls = false ;
102104 private boolean serializeSetsAsLists = true ;
105+ private EnvVarResolutionConfiguration envVarResolutionConfiguration
106+ = EnvVarResolutionConfiguration .disabled ();
103107
108+ /** Default constructor */
104109 protected Builder () {}
105110
111+ /**
112+ * A constructor that initializes the values of this builder with the values
113+ * of the given {@code ConfigurationProperties} object.
114+ *
115+ * @param properties the properties used to initialize the values of this builder
116+ */
106117 protected Builder (ConfigurationProperties properties ) {
107118 this .serializersByType .putAll (properties .serializersByType );
108119 this .serializerFactoriesByType .putAll (properties .serializerFactoriesByType );
@@ -113,6 +124,7 @@ protected Builder(ConfigurationProperties properties) {
113124 this .outputNulls = properties .outputNulls ;
114125 this .inputNulls = properties .inputNulls ;
115126 this .serializeSetsAsLists = properties .serializeSetsAsLists ;
127+ this .envVarResolutionConfiguration = properties .envVarResolutionConfiguration ;
116128 }
117129
118130 /**
@@ -289,6 +301,26 @@ final B serializeSetsAsLists(boolean serializeSetsAsLists) {
289301 return getThis ();
290302 }
291303
304+ /**
305+ * Configures whether and how environment variables should be resolved.
306+ * <p>
307+ * The default is {@link EnvVarResolutionConfiguration#disabled()} which
308+ * is a configuration that disables the resolution of environment variables.
309+ *
310+ * @param configuration the {@code EnvVarResolutionConfiguration}
311+ * @return this builder
312+ * @throws NullPointerException if {@code configuration} is null
313+ */
314+ public final B setEnvVarResolutionConfiguration (
315+ EnvVarResolutionConfiguration configuration
316+ ) {
317+ this .envVarResolutionConfiguration = requireNonNull (
318+ configuration ,
319+ "environment variable resolution configuration"
320+ );
321+ return getThis ();
322+ }
323+
292324 /**
293325 * Builds a {@code ConfigurationProperties} instance.
294326 *
@@ -304,6 +336,139 @@ final B serializeSetsAsLists(boolean serializeSetsAsLists) {
304336 protected abstract B getThis ();
305337 }
306338
339+ /**
340+ * A collection of values used to configure the resolution of environment variables.
341+ */
342+ public static final class EnvVarResolutionConfiguration {
343+ private static final EnvVarResolutionConfiguration DISABLED =
344+ new EnvVarResolutionConfiguration ();
345+ private final boolean resolveEnvVars ;
346+ private final String prefix ;
347+ private final boolean caseSensitive ;
348+
349+ /**
350+ * Returns a configuration object that disables the resolution of
351+ * environment variables.
352+ *
353+ * @return configuration object that disables the resolution of
354+ * environment variables.
355+ */
356+ public static EnvVarResolutionConfiguration disabled () {
357+ return DISABLED ;
358+ }
359+
360+ /**
361+ * Returns a configuration object that resolves environment variables
362+ * that start with the given prefix. Specifying a non-empty prefix that
363+ * is specific to your project is highly recommended.
364+ * <p>
365+ * On UNIX systems environment variables are case-sensitive.
366+ * On Windows they are case-insensitive.
367+ * <ul>
368+ * <li>
369+ * If you want to (or have to, because you are on Windows) target the
370+ * values of your configuration using uppercase environment variables,
371+ * then you have to disable case-sensitive resolution.
372+ * <p>
373+ * For example, if you have a YAML configuration with the following content
374+ * <pre>
375+ * alPHA:
376+ * be_ta: 1
377+ * ga_mma:
378+ * dELTa: 2
379+ * </pre>
380+ * then, with {@code caseSensitive} set to {@code false}, you can overwrite
381+ * the values 1 and 2 using the environment variables
382+ * {@code ALPHA_BE_TA} and {@code GA_MMA_DELTA}, respectively.
383+ * </li>
384+ * <li>
385+ * If your configuration contains paths that differ only in their case,
386+ * but are otherwise the same, and if you want to target these paths
387+ * individually, then you have to enable case-sensitive resolution.
388+ * <p>
389+ * For example, if you have a YAML configuration with the following content
390+ * <pre>
391+ * alpha:
392+ * beta: 1
393+ * ALPHA:
394+ * BETA: 2
395+ * </pre>
396+ * and you want to target the values of {@code beta} and {@code BETA}
397+ * individually, then you have to set {@code caseSensitive} to {@code true}.
398+ * After doing so you can overwrite the values 1 and 2 by using the environment
399+ * variables {@code alpha_beta} and {@code ALPHA_BETA}, respectively.
400+ * </li>
401+ * <li>
402+ * If you specify a non-empty prefix, then all variables that you want to
403+ * be resolved have to start with that prefix. For example, if you choose
404+ * {@code MY_PREFIX_} as your prefix, then the four variables listed
405+ * above have to be named {@code MY_PREFIX_ALPHA_BE_TA},
406+ * {@code MY_PREFIX_GA_MMA_DELTA}, {@code MY_PREFIX_alpha_beta}, and
407+ * {@code MY_PREFIX_ALPHA_BETA}, respectively.
408+ * </li>
409+ * </ul>
410+ *
411+ * @param prefix string the environment variables have to be prefixed with
412+ * @param caseSensitive specifies whether the resolution should be case-sensitive
413+ * @return configuration object that resolves environment variables
414+ * that start with the given prefix
415+ * @throws NullPointerException if {@code prefix} is null
416+ */
417+ public static EnvVarResolutionConfiguration resolveEnvVarsWithPrefix (
418+ String prefix ,
419+ boolean caseSensitive
420+ ) {
421+ return new EnvVarResolutionConfiguration (true , prefix , caseSensitive );
422+ }
423+
424+ private EnvVarResolutionConfiguration () {
425+ this (false , "" , false );
426+ }
427+
428+ // create 'Builder' class if more configuration options are added
429+ private EnvVarResolutionConfiguration (
430+ boolean resolveEnvVars ,
431+ String prefix ,
432+ boolean caseSensitive
433+ ) {
434+ this .resolveEnvVars = resolveEnvVars ;
435+ this .prefix = requireNonNull (prefix , "prefix" );
436+ this .caseSensitive = caseSensitive ;
437+ }
438+
439+ /**
440+ * Returns whether environment variables should be resolved.
441+ *
442+ * @return whether environment variables should be resolved
443+ */
444+ public boolean resolveEnvVars () {
445+ return resolveEnvVars ;
446+ }
447+
448+ /**
449+ * Returns the string with which the environment variables must begin
450+ * in order to be resolved.
451+ *
452+ * @return the string environment variables have to begin with to be resolved
453+ * @see EnvVarResolutionConfiguration#resolveEnvVarsWithPrefix(String, boolean)
454+ */
455+ public String prefix () {
456+ return prefix ;
457+ }
458+
459+ /**
460+ * Returns whether the resolution of environment variables should be
461+ * case-sensitive.
462+ *
463+ * @return whether the resolution of environment variables should be
464+ * case-sensitive
465+ * @see EnvVarResolutionConfiguration#resolveEnvVarsWithPrefix(String, boolean)
466+ */
467+ public boolean caseSensitive () {
468+ return caseSensitive ;
469+ }
470+ }
471+
307472 /**
308473 * Returns the field filter used to filter the fields of a configuration class.
309474 *
@@ -388,4 +553,14 @@ public final boolean inputNulls() {
388553 final boolean serializeSetsAsLists () {
389554 return serializeSetsAsLists ;
390555 }
556+
557+ /**
558+ * Returns the configuration that determines whether and how environment
559+ * variables should be resolved.
560+ *
561+ * @return the configuration
562+ */
563+ public final EnvVarResolutionConfiguration getEnvVarResolutionConfiguration () {
564+ return envVarResolutionConfiguration ;
565+ }
391566}
0 commit comments