/**
   * Parses a CSV header line and creates the corresponding resulting schema in the section (i.e.: a
   * set of fields with positions)
   */
  protected List<Field> parseHeaders(List<String[]> csvLines) {
    Section section = sectionInstance.getSection();
    String sectionId = section.getId();

    String headers[] = csvLines.get(0);
    log.trace("Headers for section " + sectionId + ": " + Arrays.toString(headers));

    int nlines = csvLines.size();

    for (int j = 0; j < headers.length; j++) {
      String header = StringUtils.trimToNull(headers[j]);

      if (header == null) {
        // Empty header, let's remove all!
        //
        log.warn(i18n.msg("empty_column", j));

        for (int i = 0; i < nlines; i++) {
          String[] line = csvLines.get(i);
          if (j == line.length)
          // This happens sometime: the header has one extra-tab and the lines are OK
          // we need to recraft the header only in that case
          {
            continue;
          }
          csvLines.set(i, (String[]) ArrayUtils.remove(line, j));
        }
        headers = csvLines.get(0);

        j--; // Restart from this point, which is now the next column
        continue;
      }
      log.trace("Working on header " + j + ":" + header);
      Field field = section.getFieldByHeader(header, false);

      if (field == null) {
        throw new TabValidationException(
            i18n.msg("unexpected_field_in_section_error", header, sectionId));
      }

      // Let's add a new real field on the basis of the header. The new field created gets its id
      // from the
      // original one in the schema, so it will have the "canonical" form, independently on what we
      // found
      // on the input (e.g.: upper case).
      //
      field = field.parseHeader(header, j, false);
      sectionInstance.addField(field);
    }
    return sectionInstance.getFields();
  }