// 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/values/ConfigValue.java
// public interface ConfigValue<T> extends Serializable {
// 
//     static <T> ConfigValue<T> of(T value, ConfigValue.Status status, Method method) {
//         return method.getAnnotation(Sensitive.class) != null
//             ? new SensitiveValue<>(value, status)
//             : new ResolvedValue<>(value, status);
//     }
// 
//     enum Status {
//         CONFIGURED,
//         MISSING,
//         DEFAULTED
//     }
// 
//     /**
//      * Returns the fully extracted and parsed value, or a default.
//      *
//      * @param proxy  the proxy this value belongs to
//      */
//     T getValue(Object proxy);
// 
//     /**
//      * Returns the value formatted as a String.
//      *
//      * @param proxy  the proxy this value belongs to
//      * @return  the value formatted as a String
//      */
//     String format(Object proxy);
// 
//     /**
//      * Indicates whether the value was found in the underlying {@link ConfigSource},
//      * missing, or replaced by a default value.
//      */
//     Status getStatus();
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/Assertions.java
// public static void assertInterface(Class<?> c) {
//     if (! c.isInterface()) {
//         throw new IllegalArgumentException(
//                 String.format("%s is not an interface", c.getCanonicalName()));
//     }
// }


import com.statemachinesystems.envy.values.ConfigMap;
import com.statemachinesystems.envy.values.ConfigValue;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import static com.statemachinesystems.envy.Assertions.assertInterface;
package com.statemachinesystems.envy;




/**
 * Handles method calls on proxied configuration interfaces.
 *
 * @see java.lang.reflect.InvocationHandler
 */
public class ProxyInvocationHandler implements InvocationHandler, Serializable {

    /**
     * Builds a proxy configuration object from the given interface and configuration values.
     *
     * @param configClass  the configuration interface to be proxied
     * @param values       map of configuration values indexed by method name
     * @param <T>          the type of the configuration interface
     * @return             a configuration object that implements the interface
     */
    public static <T> T proxy(Class<T> configClass, ConfigMap values) {
// 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/values/ConfigValue.java
// public interface ConfigValue<T> extends Serializable {
// 
//     static <T> ConfigValue<T> of(T value, ConfigValue.Status status, Method method) {
//         return method.getAnnotation(Sensitive.class) != null
//             ? new SensitiveValue<>(value, status)
//             : new ResolvedValue<>(value, status);
//     }
// 
//     enum Status {
//         CONFIGURED,
//         MISSING,
//         DEFAULTED
//     }
// 
//     /**
//      * Returns the fully extracted and parsed value, or a default.
//      *
//      * @param proxy  the proxy this value belongs to
//      */
//     T getValue(Object proxy);
// 
//     /**
//      * Returns the value formatted as a String.
//      *
//      * @param proxy  the proxy this value belongs to
//      * @return  the value formatted as a String
//      */
//     String format(Object proxy);
// 
//     /**
//      * Indicates whether the value was found in the underlying {@link ConfigSource},
//      * missing, or replaced by a default value.
//      */
//     Status getStatus();
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/Assertions.java
// public static void assertInterface(Class<?> c) {
//     if (! c.isInterface()) {
//         throw new IllegalArgumentException(
//                 String.format("%s is not an interface", c.getCanonicalName()));
//     }
// }


// Path: src/main/java/com/statemachinesystems/envy/ProxyInvocationHandler.java
import com.statemachinesystems.envy.values.ConfigMap;
import com.statemachinesystems.envy.values.ConfigValue;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import static com.statemachinesystems.envy.Assertions.assertInterface;

package com.statemachinesystems.envy;




/**
 * Handles method calls on proxied configuration interfaces.
 *
 * @see java.lang.reflect.InvocationHandler
 */
public class ProxyInvocationHandler implements InvocationHandler, Serializable {

    /**
     * Builds a proxy configuration object from the given interface and configuration values.
     *
     * @param configClass  the configuration interface to be proxied
     * @param values       map of configuration values indexed by method name
     * @param <T>          the type of the configuration interface
     * @return             a configuration object that implements the interface
     */
    public static <T> T proxy(Class<T> configClass, ConfigMap values) {
        assertInterface(configClass);