// Path: src/main/java/com/statemachinesystems/envy/ConfigSource.java
// public interface ConfigSource {
// 
//     /**
//      * Retrieves the configuration value associated with the given parameter.
//      *
//      * @param parameter  the parameter to retrieve.
//      * @return           the value associated with the parameter, or null if no value was present
//      */
//     String getValue(Parameter parameter);
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/UnsupportedTypeException.java
// public class UnsupportedTypeException extends RuntimeException {
// 
//     public UnsupportedTypeException(String message) {
//         super(message);
//     }
// }
// 
// Path: src/test/java/com/statemachinesystems/envy/common/FeatureTest.java
// public abstract class FeatureTest {
// 
//     protected Envy envy() {
//         return envy(valueParserFactory(), configSource());
//     }
// 
//     protected Envy envy(ValueParserFactory valueParserFactory) {
//         return envy(valueParserFactory, configSource());
//     }
// 
//     protected Envy envy(ConfigSource configSource) {
//         return envy(valueParserFactory(), configSource);
//     }
// 
//     protected Envy envy(ValueParserFactory valueParserFactory, ConfigSource configSource) {
//         return new Envy(valueParserFactory, configSource);
//     }
// 
//     protected ValueParserFactory valueParserFactory() {
//         List<ValueParser<?>> valueParsers = new ArrayList<ValueParser<?>>(Envy.defaultValueParsers());
//         return new ValueParserFactory(valueParsers);
//     }
// 
//     protected StubConfigSource configSource() {
//         return new StubConfigSource();
//     }
// }


import com.statemachinesystems.envy.ConfigSource;
import com.statemachinesystems.envy.Default;
import com.statemachinesystems.envy.Nullable;
import com.statemachinesystems.envy.UnsupportedTypeException;
import com.statemachinesystems.envy.common.FeatureTest;
import org.junit.Test;
import scala.Option;
import java.util.Optional;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertThat;
    public void nullableAnnotationHasNoEffectForAbsentValue() {
        Java8WithAnnotation java8 = envy().proxy(Java8WithAnnotation.class);
        assertThat(java8.foo(), equalTo(Optional.<Integer>empty()));
    }

    @Test
    public void wrapsArray() {
        Java8WithArray java8 = envy(configSource().add("foo", "1,2,3")).proxy(Java8WithArray.class);
        assertArrayEquals(new Integer[]{1, 2, 3}, java8.foo().get());
    }

    @Test
    public void wrapsPrimitiveArray() {
        Java8WithPrimitiveArray java8 = envy(configSource().add("foo", "1,2,3")).proxy(Java8WithPrimitiveArray.class);
        assertArrayEquals(new int[]{1, 2, 3}, java8.foo().get());

    }

    @Test
    public void wrapsProvidedNestedValue() {
        Java8WithNested java8 = envy(configSource().add("foo.bar", "baz")).proxy(Java8WithNested.class);
        assertThat(java8.foo().get().bar(), equalTo("baz"));
    }

    @Test
    public void wrapsMissingNestedValue() {
        Java8WithNested java8 = envy().proxy(Java8WithNested.class);
        assertThat(java8.foo(), equalTo(Optional.<Java8WithNested.Nested>empty()));
    }

// Path: src/main/java/com/statemachinesystems/envy/ConfigSource.java
// public interface ConfigSource {
// 
//     /**
//      * Retrieves the configuration value associated with the given parameter.
//      *
//      * @param parameter  the parameter to retrieve.
//      * @return           the value associated with the parameter, or null if no value was present
//      */
//     String getValue(Parameter parameter);
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/UnsupportedTypeException.java
// public class UnsupportedTypeException extends RuntimeException {
// 
//     public UnsupportedTypeException(String message) {
//         super(message);
//     }
// }
// 
// Path: src/test/java/com/statemachinesystems/envy/common/FeatureTest.java
// public abstract class FeatureTest {
// 
//     protected Envy envy() {
//         return envy(valueParserFactory(), configSource());
//     }
// 
//     protected Envy envy(ValueParserFactory valueParserFactory) {
//         return envy(valueParserFactory, configSource());
//     }
// 
//     protected Envy envy(ConfigSource configSource) {
//         return envy(valueParserFactory(), configSource);
//     }
// 
//     protected Envy envy(ValueParserFactory valueParserFactory, ConfigSource configSource) {
//         return new Envy(valueParserFactory, configSource);
//     }
// 
//     protected ValueParserFactory valueParserFactory() {
//         List<ValueParser<?>> valueParsers = new ArrayList<ValueParser<?>>(Envy.defaultValueParsers());
//         return new ValueParserFactory(valueParsers);
//     }
// 
//     protected StubConfigSource configSource() {
//         return new StubConfigSource();
//     }
// }


// Path: src/test/java/com/statemachinesystems/envy/features/OptionalWrapperTest.java
import com.statemachinesystems.envy.ConfigSource;
import com.statemachinesystems.envy.Default;
import com.statemachinesystems.envy.Nullable;
import com.statemachinesystems.envy.UnsupportedTypeException;
import com.statemachinesystems.envy.common.FeatureTest;
import org.junit.Test;
import scala.Option;
import java.util.Optional;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertThat;

    public void nullableAnnotationHasNoEffectForAbsentValue() {
        Java8WithAnnotation java8 = envy().proxy(Java8WithAnnotation.class);
        assertThat(java8.foo(), equalTo(Optional.<Integer>empty()));
    }

    @Test
    public void wrapsArray() {
        Java8WithArray java8 = envy(configSource().add("foo", "1,2,3")).proxy(Java8WithArray.class);
        assertArrayEquals(new Integer[]{1, 2, 3}, java8.foo().get());
    }

    @Test
    public void wrapsPrimitiveArray() {
        Java8WithPrimitiveArray java8 = envy(configSource().add("foo", "1,2,3")).proxy(Java8WithPrimitiveArray.class);
        assertArrayEquals(new int[]{1, 2, 3}, java8.foo().get());

    }

    @Test
    public void wrapsProvidedNestedValue() {
        Java8WithNested java8 = envy(configSource().add("foo.bar", "baz")).proxy(Java8WithNested.class);
        assertThat(java8.foo().get().bar(), equalTo("baz"));
    }

    @Test
    public void wrapsMissingNestedValue() {
        Java8WithNested java8 = envy().proxy(Java8WithNested.class);
        assertThat(java8.foo(), equalTo(Optional.<Java8WithNested.Nested>empty()));
    }

    @Test(expected = UnsupportedTypeException.class)