class StateTypeConverter {

    public static <T> T convert(String value, Class<T> to) {
        if (value == null && !(String.class.equals(to) || String[].class.equals(to))) {
            return null;
        }

        if (String.class.equals(to)) {
            return to.cast(value);
        } else if (Integer.class.equals(to)) {
            return to.cast(Integer.valueOf(value));
        } else if (int.class.equals(to)) {
            return (T) Integer.valueOf(value);
        } else if (Double.class.equals(to)) {
            return to.cast(Double.valueOf(value));
        } else if (double.class.equals(to)) {
            return (T) Double.valueOf(value);
        } else if (Long.class.equals(to)) {
            return to.cast(Long.valueOf(value));
        } else if (long.class.equals(value)) {
            return (T) Long.valueOf(value);
        } else if (Boolean.class.equals(to)) {
            return to.cast(Boolean.valueOf(value));
        } else if (boolean.class.equals(to)) {
            return (T) Boolean.valueOf(value);
        } else if (URL.class.equals(to)) {
            try {
                return to.cast(new URI(value).toURL());
            } catch (MalformedURLException e) {
                throw new IllegalArgumentException("Unable to convert value " + value + " to URL", e);
            } catch (URISyntaxException e) {
                throw new IllegalArgumentException("Unable to convert value " + value + " to URL", e);
            }
        } else if (URI.class.equals(to)) {
            try {
                return to.cast(new URI(value));
            } catch (URISyntaxException e) {
                throw new IllegalArgumentException("Unable to convert value " + value + " to URL", e);
            }
        } else {
            String trimmedValue = extractEnumName(value);
            if (to.isEnum()) {
                return (T) Enum.valueOf((Class<Enum>) to, trimmedValue.toUpperCase());
            } else if (String[].class.equals(to)) {
                final String[] convertedArray = value.split(",");
                if (convertedArray.length == 0) {
                    return to.cast(new String[0]);
                }

                trimElements(convertedArray);

                if (convertedArray.length == 1 && hasOnlyBlanks(convertedArray)) {
                    return to.cast(new String[0]);
                }

                return to.cast(convertedArray);
            } else if (Collection.class.isAssignableFrom(to)) {
                final String[] convertedArray = value.split(",");
                if (convertedArray.length == 0) {
                    return to.cast(new ArrayList<>());
                }

                trimElements(convertedArray);

                if (convertedArray.length == 1 && hasOnlyBlanks(convertedArray)) {
                    return to.cast(new ArrayList<>());
                }

                return to.cast(Arrays.asList(convertedArray));
            } else if (Charset.class.equals(to)) {
                return to.cast(Charset.forName(trimmedValue.toUpperCase()));
            } else if (Class.class.equals(to)) {
                try {
                    Object clazz = Class.forName(value);
                    return to.cast(clazz);
                } catch (Exception e) {
                    throw new IllegalArgumentException("Unable to find class [" + value + "].", e);
                }
            } else // Try to create instance via reflection
            {
                try {
                    Object instance = Class.forName(value).newInstance();
                    return to.cast(instance);
                } catch (Exception e) {
                    throw new IllegalArgumentException(
                        "Unable to convert value [" + value + "] to a class [" + to.getName() + "].", e);
                }
            }
        }
    }

}