class MediaTypeHeaderDelegate implements RuntimeDelegate.HeaderDelegate<MediaType> {

    @Override
    public MediaType fromString(String header) {
        if (header == null) {
            throw new IllegalArgumentException();
        }

        try {
            int subTypeSeparatorIndex = scan(header, SUB_TYPE_SEPARATOR);
            int paramsSeparatorIndex = scan(header, PARAMS_SEPARATOR);

            String type;
            String subType;

            if (charAtIsNot(header, subTypeSeparatorIndex, SUB_TYPE_SEPARATOR)
                && charAtIsNot(header, paramsSeparatorIndex, PARAMS_SEPARATOR)) {

                return new MediaType(header, null);

            } else if (charAtIs(header, subTypeSeparatorIndex, SUB_TYPE_SEPARATOR)
                       && charAtIsNot(header, paramsSeparatorIndex, PARAMS_SEPARATOR)) {

                return new MediaType(removeWhitespaces(header.substring(0, subTypeSeparatorIndex)),
                                     removeWhitespaces(header.substring(subTypeSeparatorIndex + 1)));

            } else if (charAtIsNot(header, subTypeSeparatorIndex, SUB_TYPE_SEPARATOR) && paramsSeparatorIndex == 0) {

                // string just start from ';'
                type = null;
                subType = null;

            } else if (charAtIsNot(header, subTypeSeparatorIndex, SUB_TYPE_SEPARATOR)
                       && charAtIs(header, paramsSeparatorIndex, PARAMS_SEPARATOR)) {

                // there is no '/' but present ';'
                type = removeWhitespaces(header.substring(0, paramsSeparatorIndex));
                subType = null;

            } else {

                type = removeWhitespaces(header.substring(0, subTypeSeparatorIndex));
                subType = header.substring(subTypeSeparatorIndex + 1, paramsSeparatorIndex);

            }

            Map<String, String> params = new HeaderParameterParser().parse(header);
            return new MediaType(type, subType, params);

        } catch (ParseException e) {
            throw new IllegalArgumentException(e);
        }
    }

}