@SuppressWarnings({"rawtypes", "unchecked"})
  private <T> T convert(
      MetaData md, String[] data, Class<T> type, T defaultValue, Annotation annotation) {
    Object out = data[md.index];

    if (out == null) {
      out = defaultValue == null ? md.defaultValue : defaultValue;
    }

    if (annotation == null) {
      initializeMetadataConversions(data, md);
      out = md.convert(out);

      if (out == null) {
        out = defaultValue == null ? md.defaultValue : defaultValue;
      }
    }

    if (type != null) {
      if (out != null && type.isAssignableFrom(out.getClass())) {
        return (T) out;
      }
      Conversion conversion;
      if (type != String.class) {
        if (annotation == null) {
          conversion = conversionByType.get(type);
          if (conversion == null) {
            conversion = AnnotationHelper.getDefaultConversion(type, null);
            conversionByType.put(type, conversion);
          }
        } else {
          Map<Annotation, Conversion> m = conversionsByAnnotation.get(type);
          if (m == null) {
            m = new HashMap<Annotation, Conversion>();
            conversionsByAnnotation.put(type, m);
          }
          conversion = m.get(annotation);
          if (conversion == null) {
            conversion = AnnotationHelper.getConversion(type, annotation);
            m.put(annotation, conversion);
          }
        }

        if (conversion == null) {
          String message = "";
          if (type == Date.class || type == Calendar.class) {
            message = ". Need to specify format for date";
          }
          DataProcessingException exception =
              new DataProcessingException(
                  "Cannot convert '{value}' to " + type.getName() + message);
          exception.setValue(out);
          exception.setErrorContentLength(context.errorContentLength());
          throw exception;
        }
        out = conversion.execute(out);
      }
    }
    if (type == null) {
      return (T) out;
    }
    try {
      return type.cast(out);
    } catch (ClassCastException e) {
      DataProcessingException exception =
          new DataProcessingException(
              "Cannot cast value '{value}' of type "
                  + out.getClass().toString()
                  + " to "
                  + type.getName());
      exception.setValue(out);
      exception.setErrorContentLength(context.errorContentLength());
      throw exception;
    }
  }
 @SuppressWarnings("rawtypes")
 private <T> T convert(
     MetaData md, String[] data, Class<T> expectedType, Conversion[] conversions) {
   return expectedType.cast(convert(md, data, conversions));
 }