/**
   * Add a optional column which has stable order and name, into {@link #optionalColumnMapping} and
   * {@link #columnMapping}.
   *
   * @see MZTabColumn#createOptionalColumn(Section, MZTabColumn, Integer, IndexedElement)
   * @exception IllegalArgumentException: If user would like to add duplicate optional columns.
   * @param column SHOULD NOT set null.
   * @param msRun SHOULD NOT set null.
   */
  public void addOptionalColumn(MZTabColumn column, MsRun msRun) {
    String position = column.getLogicPosition();
    if (optionalColumnMapping.containsKey(position)) {
      throw new IllegalArgumentException(
          "There exists column "
              + optionalColumnMapping.get(position)
              + " in position "
              + position);
    }

    MZTabColumn newColumn = null;
    //        switch (section) {
    //            case Protein_Header:
    //                if (column.getName().equals(ProteinColumn.NUM_PSMS.getName()) ||
    //                        column.getName().equals(ProteinColumn.NUM_PEPTIDES_DISTINCT.getName())
    // ||
    //                        column.getName().equals(ProteinColumn.NUM_PEPTIDES_UNIQUE.getName()))
    // {
    //                    newColumn = MZTabColumn.createOptionalColumn(section, column, msRun);
    //                }
    //
    //                if (position.equals(ProteinColumn.SEARCH_ENGINE_SCORE.getOrder()) ||
    //                    position.equals(ProteinColumn.NUM_PSMS.getOrder()) ||
    //                    position.equals(ProteinColumn.NUM_PEPTIDES_DISTINCT.getOrder()) ||
    //                    position.equals(ProteinColumn.NUM_PEPTIDES_UNIQUE.getOrder())) {
    //                    newColumn = MZTabColumn.createOptionalColumn(section, column, msRun);
    //                }
    //                break;
    //            case Peptide_Header:
    //                if (position.equals(PeptideColumn.SEARCH_ENGINE_SCORE.getOrder())) {
    //                    newColumn = MZTabColumn.createOptionalColumn(section, column, msRun);
    //                }
    //                break;
    //            case Small_Molecule_Header:
    //                if (position.equals(SmallMoleculeColumn.SEARCH_ENGINE_SCORE.getOrder())) {
    //                    newColumn = MZTabColumn.createOptionalColumn(section, column, msRun);
    //                }
    //                break;
    //        }

    if (section == Section.Protein_Header) {
      if (column.getName().equals(ProteinColumn.NUM_PSMS.getName())
          || column.getName().equals(ProteinColumn.NUM_PEPTIDES_DISTINCT.getName())
          || column.getName().equals(ProteinColumn.NUM_PEPTIDES_UNIQUE.getName())) {
        newColumn = MZTabColumn.createOptionalColumn(section, column, null, msRun);
      }
    }

    if (newColumn != null) {
      optionalColumnMapping.put(newColumn.getLogicPosition(), newColumn);
      columnMapping.put(newColumn.getLogicPosition(), newColumn);
    }
  }
  /**
   * Judge the column is optional or not, based one its header name.
   *
   * @param header SHOULD NOT be null!
   */
  public boolean isOptionalColumn(String header) {
    header = header.trim().toLowerCase();

    switch (section) {
      case Protein_Header:
        if (header.startsWith(ProteinColumn.SEARCH_ENGINE_SCORE.getName())
            || header.startsWith(ProteinColumn.NUM_PSMS.getName())
            || header.startsWith(ProteinColumn.NUM_PEPTIDES_DISTINCT.getName())
            || header.startsWith(ProteinColumn.NUM_PEPTIDES_UNIQUE.getName())
            || header.startsWith("protein_abundance_assay")
            || header.startsWith("protein_abundance_study_variable")
            || header.startsWith("protein_abundance_stdev_study_variable")
            || header.startsWith("protein_abundance_std_error_study_variable")) {
          return true;
        }
        break;
      case Peptide_Header:
        if (header.startsWith(PeptideColumn.SEARCH_ENGINE_SCORE.getName())
            || header.startsWith("peptide_abundance_assay")
            || header.startsWith("peptide_abundance_study_variable")
            || header.startsWith("peptide_abundance_stdev_study_variable")
            || header.startsWith("peptide_abundance_std_error_study_variable")) {
          return true;
        }
        break;
      case Small_Molecule_Header:
        if (header.startsWith(SmallMoleculeColumn.SEARCH_ENGINE_SCORE.getName())
            || header.startsWith("smallmolecule_abundance_assay")
            || header.startsWith("smallmolecule_abundance_study_variable")
            || header.startsWith("smallmolecule_abundance_stdev_study_variable")
            || header.startsWith("smallmolecule_abundance_std_error_study_variable")) {
          return true;
        }
        break;
    }

    return header.startsWith("opt_");
  }