package com.statemachinesystems.envy;

import com.statemachinesystems.envy.parsers.ArrayValueParser;
import com.statemachinesystems.envy.parsers.EnumValueParser;
import com.statemachinesystems.envy.parsers.ReflectionValueParser;

import java.util.HashMap;
import java.util.Map;

public class ValueParserFactory {

    private static final Map<Class<?>, Class<?>> primitiveToBoxed = new HashMap<Class<?>, Class<?>>();

    {
        primitiveToBoxed.put(boolean.class, Boolean.class);
        primitiveToBoxed.put(byte.class, Byte.class);
        primitiveToBoxed.put(char.class, Character.class);
        primitiveToBoxed.put(double.class, Double.class);
        primitiveToBoxed.put(float.class, Float.class);
        primitiveToBoxed.put(int.class, Integer.class);
        primitiveToBoxed.put(long.class, Long.class);
        primitiveToBoxed.put(short.class, Short.class);
        primitiveToBoxed.put(void.class, Void.class);
    }

    private static Class<?> boxed(Class<?> propertyClass) {
        return propertyClass.isPrimitive()
                ? primitiveToBoxed.get(propertyClass)
                : propertyClass;
    }

    private final Map<Class<?>, ValueParser<?>> valueParsers;

    public ValueParserFactory(ValueParser<?>... valueParsers) {
        this.valueParsers = new HashMap<Class<?>, ValueParser<?>>();

        for (ValueParser<?> parser : valueParsers) {
            this.valueParsers.put(parser.getValueClass(), parser);
        }
    }

    public ValueParser<?> getValueParser(Class<?> propertyClass) {
        return getValueParser(propertyClass, true);
    }

    private ValueParser<?> getValueParser(Class<?> propertyClass, boolean allowArrays) {
        ValueParser<?> parser = valueParsers.get(boxed(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 {
            parser = ReflectionValueParser.parserOrNull(propertyClass);
            if (parser == null) {
                throw new UnsupportedTypeException(
                        String.format("Cannot parse value of class %s", propertyClass.getCanonicalName()));
            }
            return parser;
        }
    }

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

        return enumValueParser;
    }

    private ValueParser<?> arrayValueParser(Class<?> propertyClass) {
        Class<?> componentType = propertyClass.getComponentType();

        @SuppressWarnings("unchecked")
        ValueParser<?> arrayValueParser =
                new ArrayValueParser(getValueParser(componentType, false));

        return arrayValueParser;
    }
}

@@ -223,16 +223,70 @@
 arser;%0A%0A
+import java.util.Arrays;%0Aimport java.util.Collection;%0A
 import j
@@ -1301,32 +1301,155 @@
 valueParsers) %7B%0A
+        this(Arrays.asList(valueParsers));%0A    %7D%0A%0A    public ValueParserFactory(Collection%3CValueParser%3C?%3E%3E valueParsers) %7B%0A
         this.val

Support both array and collection arguments in ValueParserFactory constructor