// Path: src/main/java/com/statemachinesystems/envy/sources/DelegatingConfigSource.java
// public class DelegatingConfigSource implements ConfigSource {
// 
//     private final ConfigSource[] sources;
// 
//     /**
//      * Creates a {@link com.statemachinesystems.envy.sources.DelegatingConfigSource} using
//      * the given component sources in preference order.
//      *
//      * @param sources  component {@link com.statemachinesystems.envy.ConfigSource}s in preference order
//      */
//     public DelegatingConfigSource(ConfigSource... sources) {
//         this.sources = sources;
//     }
// 
//     @Override
//     public String getValue(Parameter parameter) {
//         for (ConfigSource source : sources) {
//             String value = source.getValue(parameter);
//             if (value != null) {
//                 return value;
//             }
//         }
//         return null;
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/sources/EnvironmentVariableConfigSource.java
// public class EnvironmentVariableConfigSource implements ConfigSource {
// 
//     @Override
//     public String getValue(Parameter parameter) {
//         return System.getenv(parameter.asEnvironmentVariableName());
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/sources/SystemPropertyConfigSource.java
// public class SystemPropertyConfigSource implements ConfigSource {
// 
//     @Override
//     public String getValue(Parameter parameter) {
//         return System.getProperty(parameter.asSystemPropertyName());
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/values/ConfigMap.java
// public class ConfigMap implements Serializable {
// 
//     private final Map<String, ConfigValue> values;
// 
//     public ConfigMap(Map<String, ConfigValue> values) {
//         this.values = values;
//     }
// 
//     public ConfigValue getValue(String methodName) {
//         return values.get(methodName);
//     }
// 
//     public Set<String> getMethodNames() {
//         return values.keySet();
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
//         ConfigMap configMap = (ConfigMap) o;
//         return Objects.equals(values, configMap.values);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(values);
//     }
// }


import com.statemachinesystems.envy.parsers.*;
import com.statemachinesystems.envy.sources.DelegatingConfigSource;
import com.statemachinesystems.envy.sources.EnvironmentVariableConfigSource;
import com.statemachinesystems.envy.sources.SystemPropertyConfigSource;
import com.statemachinesystems.envy.values.ConfigMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
     * @return  a default {@link com.statemachinesystems.envy.ConfigSource} implementation
     */
    public static ConfigSource defaultConfigSource() {
        return DEFAULT_CONFIG_SOURCE;
    }

    private static final ConfigSource DEFAULT_CONFIG_SOURCE =
            new DelegatingConfigSource(new SystemPropertyConfigSource(), new EnvironmentVariableConfigSource());

    private final ConfigExtractor configExtractor;

    /**
     * Creates a new {@link com.statemachinesystems.envy.Envy} instance with the given
     * {@link com.statemachinesystems.envy.ValueParserFactory} and {@link com.statemachinesystems.envy.ConfigSource}.
     *
     * @param valueParserFactory  the {@link com.statemachinesystems.envy.ValueParserFactory} to use
     * @param configSource        the {@link com.statemachinesystems.envy.ConfigSource} to use
     */
    public Envy(ValueParserFactory valueParserFactory, ConfigSource configSource) {
        this.configExtractor = new ConfigExtractor(valueParserFactory, configSource);
    }

    /**
     * Builds a proxy configuration object from the given interface.
     *
     * @param configClass  the configuration interface to be proxied
     * @param <T>          the type of the configuration interface
     * @return             a configuration object that implements the interface
     */
    public <T> T proxy(Class<T> configClass) {
// Path: src/main/java/com/statemachinesystems/envy/sources/DelegatingConfigSource.java
// public class DelegatingConfigSource implements ConfigSource {
// 
//     private final ConfigSource[] sources;
// 
//     /**
//      * Creates a {@link com.statemachinesystems.envy.sources.DelegatingConfigSource} using
//      * the given component sources in preference order.
//      *
//      * @param sources  component {@link com.statemachinesystems.envy.ConfigSource}s in preference order
//      */
//     public DelegatingConfigSource(ConfigSource... sources) {
//         this.sources = sources;
//     }
// 
//     @Override
//     public String getValue(Parameter parameter) {
//         for (ConfigSource source : sources) {
//             String value = source.getValue(parameter);
//             if (value != null) {
//                 return value;
//             }
//         }
//         return null;
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/sources/EnvironmentVariableConfigSource.java
// public class EnvironmentVariableConfigSource implements ConfigSource {
// 
//     @Override
//     public String getValue(Parameter parameter) {
//         return System.getenv(parameter.asEnvironmentVariableName());
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/sources/SystemPropertyConfigSource.java
// public class SystemPropertyConfigSource implements ConfigSource {
// 
//     @Override
//     public String getValue(Parameter parameter) {
//         return System.getProperty(parameter.asSystemPropertyName());
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/values/ConfigMap.java
// public class ConfigMap implements Serializable {
// 
//     private final Map<String, ConfigValue> values;
// 
//     public ConfigMap(Map<String, ConfigValue> values) {
//         this.values = values;
//     }
// 
//     public ConfigValue getValue(String methodName) {
//         return values.get(methodName);
//     }
// 
//     public Set<String> getMethodNames() {
//         return values.keySet();
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
//         ConfigMap configMap = (ConfigMap) o;
//         return Objects.equals(values, configMap.values);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(values);
//     }
// }


// Path: src/main/java/com/statemachinesystems/envy/Envy.java
import com.statemachinesystems.envy.parsers.*;
import com.statemachinesystems.envy.sources.DelegatingConfigSource;
import com.statemachinesystems.envy.sources.EnvironmentVariableConfigSource;
import com.statemachinesystems.envy.sources.SystemPropertyConfigSource;
import com.statemachinesystems.envy.values.ConfigMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

     * @return  a default {@link com.statemachinesystems.envy.ConfigSource} implementation
     */
    public static ConfigSource defaultConfigSource() {
        return DEFAULT_CONFIG_SOURCE;
    }

    private static final ConfigSource DEFAULT_CONFIG_SOURCE =
            new DelegatingConfigSource(new SystemPropertyConfigSource(), new EnvironmentVariableConfigSource());

    private final ConfigExtractor configExtractor;

    /**
     * Creates a new {@link com.statemachinesystems.envy.Envy} instance with the given
     * {@link com.statemachinesystems.envy.ValueParserFactory} and {@link com.statemachinesystems.envy.ConfigSource}.
     *
     * @param valueParserFactory  the {@link com.statemachinesystems.envy.ValueParserFactory} to use
     * @param configSource        the {@link com.statemachinesystems.envy.ConfigSource} to use
     */
    public Envy(ValueParserFactory valueParserFactory, ConfigSource configSource) {
        this.configExtractor = new ConfigExtractor(valueParserFactory, configSource);
    }

    /**
     * Builds a proxy configuration object from the given interface.
     *
     * @param configClass  the configuration interface to be proxied
     * @param <T>          the type of the configuration interface
     * @return             a configuration object that implements the interface
     */
    public <T> T proxy(Class<T> configClass) {
        ConfigMap values = configExtractor.extractConfigMap(configClass);