// Path: src/main/java/com/statemachinesystems/envy/parsers/ArrayValueParser.java
// public class ArrayValueParser<T> implements ValueParser<T[]> {
// 
//     public static final String DEFAULT_SEPARATOR = ",";
//     private static final int INCLUDE_TRAILING = -1;
// 
//     private final ValueParser<T> valueParser;
//     private final String separator;
// 
//     public ArrayValueParser(ValueParser<T> valueParser, String separator) {
//         this.valueParser = valueParser;
//         this.separator = separator;
//     }
// 
//     public ArrayValueParser(ValueParser<T> valueParser) {
//         this(valueParser, DEFAULT_SEPARATOR);
//     }
// 
//     @Override
//     public T[] parseValue(String value) {
//         String[] parts = value.isEmpty()
//             ? new String[] {}
//             : value.split(separator, INCLUDE_TRAILING);
// 
//         @SuppressWarnings("unchecked")
//         T[] array = (T[]) Array.newInstance(valueParser.getValueClass(), parts.length);
// 
//         for (int i = 0; i < parts.length; i++) {
//             array[i] = valueParser.parseValue(parts[i]);
//         }
//         return array;
//     }
// 
//     @Override
//     @SuppressWarnings("unchecked")
//     public Class<T[]> getValueClass() {
//         return (Class<T[]>) Array.newInstance(valueParser.getValueClass(), 0).getClass();
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/parsers/EnumValueParser.java
// public class EnumValueParser<T extends Enum<T>> implements ValueParser<T> {
// 
//     private final Class<T> enumClass;
// 
//     public EnumValueParser(Class<T> enumClass) {
//         assertEnum(enumClass);
//         this.enumClass = enumClass;
//     }
// 
//     @Override
//     public T parseValue(String value) {
//         for (Object constant : enumClass.getEnumConstants()) {
//             if (value.equals(((Enum<?>) constant).name())) {
//                 @SuppressWarnings("unchecked")
//                 T enumValue = (T) constant;
// 
//                 return enumValue;
//             }
//         }
//         throw new IllegalArgumentException(
//                 String.format("No constant '%s' for enum %s", value, enumClass.getName()));
//     }
// 
//     @Override
//     public Class<T> getValueClass() {
//         return enumClass;
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/parsers/ReflectionValueParser.java
// public class ReflectionValueParser<T> implements ValueParser<T> {
// 
//     public static <T> ReflectionValueParser<T> parserOrNull(Class<T> valueClass) {
//         Constructor<T> constructor = stringConstructorOrNull(valueClass);
//         return constructor != null
//                 ? new ReflectionValueParser<T>(constructor)
//                 : null;
//     }
// 
//     public static <T> Constructor<T> stringConstructorOrNull(Class<T> targetClass) {
//         @SuppressWarnings("unchecked")
//         Constructor<T>[] constructors = (Constructor<T>[]) targetClass.getConstructors();
// 
//         for (Constructor<T> constructor : constructors) {
//             if (isStringConstructor(constructor)) {
//                 return constructor;
//             }
//         }
//         return null;
//     }
// 
//     public static <T> boolean isStringConstructor(Constructor<T> constructor) {
//         Class<?>[] parameterTypes = constructor.getParameterTypes();
//         return parameterTypes.length == 1
//                 && parameterTypes[0].isAssignableFrom(String.class);// TODO CharSequence instead?
//     }
// 
//     private final Constructor<T> constructor;
// 
//     private ReflectionValueParser(Constructor<T> constructor) {
//         this.constructor = constructor;
//     }
// 
//     @Override
//     public T parseValue(String value) {
//         try {
//             return constructor.newInstance(value);
//         } catch (Exception e) {
//             throw new RuntimeException(e.getMessage(), e);
//         }
//     }
// 
//     @Override
//     public Class<T> getValueClass() {
//         return constructor.getDeclaringClass();
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/Conversions.java
// public static Class<?> toBoxed(Class<?> c) {
//     return c.isPrimitive()
//             ? primitiveToBoxed.get(c)
//             : c;
// }


import com.statemachinesystems.envy.parsers.ArrayValueParser;
import com.statemachinesystems.envy.parsers.EnumValueParser;
import com.statemachinesystems.envy.parsers.ReflectionValueParser;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import static com.statemachinesystems.envy.Conversions.toBoxed;
     * Returns null if no applicable parser is available.
     *
     * @param propertyClass  the class for which to create the {@link com.statemachinesystems.envy.ValueParser}
     * @return               a {@link com.statemachinesystems.envy.ValueParser} for the given class, or null if
     *                       no applicable parser is available
     */
    @SuppressWarnings("unchecked")
    public <T> ValueParser<T> getValueParser(Class<T> propertyClass) {
        return (ValueParser<T>) getValueParser(propertyClass, true);
    }

    private ValueParser<?> getValueParser(Class<?> propertyClass, boolean allowArrays) {
        ValueParser<?> parser = valueParsers.get(toBoxed(propertyClass));

        if (parser != null) {
            return parser;
        } else if (propertyClass.isEnum()) {
            return enumValueParser(propertyClass);
        } else if (propertyClass.isArray()) {
            if (! allowArrays) {
                throw new UnsupportedTypeException("Nested arrays are not supported");
            }
            return arrayValueParser(propertyClass);
        } else {
            return ReflectionValueParser.parserOrNull(propertyClass);
        }
    }

    private ValueParser<?> enumValueParser(Class<?> propertyClass) {
        @SuppressWarnings("unchecked")
// Path: src/main/java/com/statemachinesystems/envy/parsers/ArrayValueParser.java
// public class ArrayValueParser<T> implements ValueParser<T[]> {
// 
//     public static final String DEFAULT_SEPARATOR = ",";
//     private static final int INCLUDE_TRAILING = -1;
// 
//     private final ValueParser<T> valueParser;
//     private final String separator;
// 
//     public ArrayValueParser(ValueParser<T> valueParser, String separator) {
//         this.valueParser = valueParser;
//         this.separator = separator;
//     }
// 
//     public ArrayValueParser(ValueParser<T> valueParser) {
//         this(valueParser, DEFAULT_SEPARATOR);
//     }
// 
//     @Override
//     public T[] parseValue(String value) {
//         String[] parts = value.isEmpty()
//             ? new String[] {}
//             : value.split(separator, INCLUDE_TRAILING);
// 
//         @SuppressWarnings("unchecked")
//         T[] array = (T[]) Array.newInstance(valueParser.getValueClass(), parts.length);
// 
//         for (int i = 0; i < parts.length; i++) {
//             array[i] = valueParser.parseValue(parts[i]);
//         }
//         return array;
//     }
// 
//     @Override
//     @SuppressWarnings("unchecked")
//     public Class<T[]> getValueClass() {
//         return (Class<T[]>) Array.newInstance(valueParser.getValueClass(), 0).getClass();
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/parsers/EnumValueParser.java
// public class EnumValueParser<T extends Enum<T>> implements ValueParser<T> {
// 
//     private final Class<T> enumClass;
// 
//     public EnumValueParser(Class<T> enumClass) {
//         assertEnum(enumClass);
//         this.enumClass = enumClass;
//     }
// 
//     @Override
//     public T parseValue(String value) {
//         for (Object constant : enumClass.getEnumConstants()) {
//             if (value.equals(((Enum<?>) constant).name())) {
//                 @SuppressWarnings("unchecked")
//                 T enumValue = (T) constant;
// 
//                 return enumValue;
//             }
//         }
//         throw new IllegalArgumentException(
//                 String.format("No constant '%s' for enum %s", value, enumClass.getName()));
//     }
// 
//     @Override
//     public Class<T> getValueClass() {
//         return enumClass;
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/parsers/ReflectionValueParser.java
// public class ReflectionValueParser<T> implements ValueParser<T> {
// 
//     public static <T> ReflectionValueParser<T> parserOrNull(Class<T> valueClass) {
//         Constructor<T> constructor = stringConstructorOrNull(valueClass);
//         return constructor != null
//                 ? new ReflectionValueParser<T>(constructor)
//                 : null;
//     }
// 
//     public static <T> Constructor<T> stringConstructorOrNull(Class<T> targetClass) {
//         @SuppressWarnings("unchecked")
//         Constructor<T>[] constructors = (Constructor<T>[]) targetClass.getConstructors();
// 
//         for (Constructor<T> constructor : constructors) {
//             if (isStringConstructor(constructor)) {
//                 return constructor;
//             }
//         }
//         return null;
//     }
// 
//     public static <T> boolean isStringConstructor(Constructor<T> constructor) {
//         Class<?>[] parameterTypes = constructor.getParameterTypes();
//         return parameterTypes.length == 1
//                 && parameterTypes[0].isAssignableFrom(String.class);// TODO CharSequence instead?
//     }
// 
//     private final Constructor<T> constructor;
// 
//     private ReflectionValueParser(Constructor<T> constructor) {
//         this.constructor = constructor;
//     }
// 
//     @Override
//     public T parseValue(String value) {
//         try {
//             return constructor.newInstance(value);
//         } catch (Exception e) {
//             throw new RuntimeException(e.getMessage(), e);
//         }
//     }
// 
//     @Override
//     public Class<T> getValueClass() {
//         return constructor.getDeclaringClass();
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/Conversions.java
// public static Class<?> toBoxed(Class<?> c) {
//     return c.isPrimitive()
//             ? primitiveToBoxed.get(c)
//             : c;
// }


// Path: src/main/java/com/statemachinesystems/envy/ValueParserFactory.java
import com.statemachinesystems.envy.parsers.ArrayValueParser;
import com.statemachinesystems.envy.parsers.EnumValueParser;
import com.statemachinesystems.envy.parsers.ReflectionValueParser;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import static com.statemachinesystems.envy.Conversions.toBoxed;

     * Returns null if no applicable parser is available.
     *
     * @param propertyClass  the class for which to create the {@link com.statemachinesystems.envy.ValueParser}
     * @return               a {@link com.statemachinesystems.envy.ValueParser} for the given class, or null if
     *                       no applicable parser is available
     */
    @SuppressWarnings("unchecked")
    public <T> ValueParser<T> getValueParser(Class<T> propertyClass) {
        return (ValueParser<T>) getValueParser(propertyClass, true);
    }

    private ValueParser<?> getValueParser(Class<?> propertyClass, boolean allowArrays) {
        ValueParser<?> parser = valueParsers.get(toBoxed(propertyClass));

        if (parser != null) {
            return parser;
        } else if (propertyClass.isEnum()) {
            return enumValueParser(propertyClass);
        } else if (propertyClass.isArray()) {
            if (! allowArrays) {
                throw new UnsupportedTypeException("Nested arrays are not supported");
            }
            return arrayValueParser(propertyClass);
        } else {
            return ReflectionValueParser.parserOrNull(propertyClass);
        }
    }

    private ValueParser<?> enumValueParser(Class<?> propertyClass) {
        @SuppressWarnings("unchecked")
        ValueParser<?> enumValueParser = new EnumValueParser(propertyClass);