/**
   * Check whether s qualifier string exists in a StringVector for that qualifier. If the
   * StringVector contains the hit, organism, description & e-value then return true.
   *
   * @param qualStr
   * @param qualStringVector
   * @return
   */
  public static boolean containsStringInStringVector(
      final String qualStr, final StringVector qualStringVector) {
    StringVector sim1 = StringVector.getStrings(qualStr, ";");
    for (int i = 0; i < qualStringVector.size(); i++) {
      String thisStr = (String) qualStringVector.get(i);

      StringVector sim2 = StringVector.getStrings(thisStr, ";");

      // hit
      if (!((String) sim1.get(1)).equals((String) sim2.get(1))) continue;

      // organism
      if (!((String) sim1.get(2)).equals((String) sim2.get(2))) continue;

      // description
      if (!((String) sim1.get(3)).equals((String) sim2.get(3))) continue;

      // e-value
      final String evalueString1 = getField("E()=", qualStr);
      final String evalueString2 = getField("E()=", thisStr);
      if (!(evalueString1.equals(evalueString2))) continue;

      return true;
    }
    return false;
  }
 private void appendToBuffer(StringVector qualifierStr, StringBuffer buff) {
   for (int j = 0; j < qualifierStr.size(); ++j) {
     String str = (String) qualifierStr.elementAt(j);
     if (j != 0) buff.append(", " + str);
     else buff.append(str);
   }
 }
  /**
   * Return a qualifier copy of the qualifier provided that does not contain any of the values in
   * the StringVector.
   *
   * @param newQualifier
   * @param oldValues
   * @return
   * @throws InvalidRelationException
   */
  protected static Qualifier getQualifierWithoutDuplicateValues(
      final Qualifier qualifier, final StringVector values) throws InvalidRelationException {
    final Qualifier newQualifier;
    if (values == null || values.size() < 1) newQualifier = qualifier;
    else {
      StringVector newValues = qualifier.getValues();
      StringVector valuesToAdd = new StringVector();

      for (int k = 0; k < newValues.size(); k++) {
        if (!values.contains(newValues.get(k))) {
          if (qualifier.getName().equals("history")) {
            if (!uk.ac.sanger.artemis.components.genebuilder.cv.HistoryBox.contains(
                values, (String) newValues.get(k))) valuesToAdd.add(newValues.get(k));
          } else valuesToAdd.add(newValues.get(k));
        }
      }

      if (valuesToAdd.size() == 0) return null;
      newQualifier = new Qualifier(qualifier.getName(), valuesToAdd);
    }
    return newQualifier;
  }
  /**
   * Add a new qualifier to a list of qualifiers
   *
   * @param qualifiers
   * @param newQualifier
   */
  private void addNewQualifier(QualifierVector qualifiers, Qualifier newQualifier) {
    Qualifier qualifier;
    if ((qualifier = qualifiers.getQualifierByName(newQualifier.getName())) != null) {
      final StringVector newValues = newQualifier.getValues();
      final StringVector values = qualifier.getValues();

      if (newValues == null) return;
      for (int j = 0; j < newValues.size(); j++) {
        String newValue = (String) newValues.get(j);
        if (!values.contains(newValue)) qualifier.addValue(newValue);
      }
    } else qualifiers.addElement(newQualifier);
  }
  /**
   * Optionally transfer GO fields with evidence code ISO and link back to the original source in
   * the WITH/FROM column.
   *
   * @param setEvidenceAndWithFrom
   * @param feature
   * @param qName
   * @param values
   * @return
   */
  private static StringVector getTransferValues(
      final boolean setEvidenceAndWithFrom,
      final Feature feature,
      final String qName,
      final StringVector values) {
    if (!setEvidenceAndWithFrom) return values;

    if (qName.equals("GO") || qName.equals("product")) {
      final StringVector tvalues = new StringVector();
      final String gene = getGeneName(feature);
      for (int i = 0; i < values.size(); i++) {
        String val =
            changeField("evidence=", "Inferred from Sequence Orthology", null, values.get(i));

        if (gene != null) val = changeField("with=", "GeneDB:" + gene, "|", val);
        tvalues.add(val);
      }
      return tvalues;
    }
    return values;
  }
  /**
   * Set up the expander button to display qualifier values.
   *
   * @param butt - expander button
   * @param qualifier - the qualifer that is being displayed
   * @param qualifierValueBox - Box containing the values
   * @param qualifierNameCheckBox - JCheckBox for the given qualifier
   * @param pane
   * @return
   */
  private Vector<JCheckBox> setExpanderButton(
      final JButton butt,
      final Qualifier qualifier,
      final Box qualifierValueBox,
      final JCheckBox qualifierNameCheckBox) {
    butt.setMargin(new Insets(0, 0, 0, 0));
    butt.setHorizontalAlignment(SwingConstants.RIGHT);
    butt.setHorizontalTextPosition(SwingConstants.RIGHT);
    butt.setBorderPainted(false);
    butt.setFont(butt.getFont().deriveFont(Font.BOLD));
    butt.setForeground(TransferAnnotationTool.STEEL_BLUE);

    butt.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            if (butt.getText().equals("+")) butt.setText("-");
            else butt.setText("+");

            qualifierValueBox.setVisible(butt.getText().equals("-"));
            revalidate();
          }
        });

    // set-up qualifier values list
    qualifierValueBox.setVisible(false);
    final Vector<JCheckBox> qualifierValuesCheckBox = new Vector<JCheckBox>();
    final StringVector values = qualifier.getValues();
    if (values != null) {
      for (int i = 0; i < values.size(); i++) {
        final JCheckBox cb = new JCheckBox(values.get(i), qualifierNameCheckBox.isSelected());
        cb.setFont(cb.getFont().deriveFont(Font.ITALIC));
        qualifierValueBox.add(cb);
        qualifierValuesCheckBox.add(cb);
      }
    }
    return qualifierValuesCheckBox;
  }
 /**
  * Get a StringBuffer representation of the values in a StringVector
  *
  * @param v
  * @return
  */
 private static StringBuffer parseStringVector(final StringVector v) {
   StringBuffer buff = new StringBuffer();
   for (int i = 0; i < v.size(); i++) buff.append("    " + v.elementAt(i) + "\n");
   return buff;
 }
  /**
   * Transfer selected qualifiers to the list of features defined by the selected names.
   *
   * @param qualifierCheckBoxes - list of qualifier check boxes
   * @param geneNameTextArea - text with a list of feature names to transfer to
   * @param feature - feature to copy from
   * @param entryGroup
   * @param sameKey
   * @param overwrite
   */
  protected static int transferAnnotation(
      final Hashtable<JCheckBox, Vector<JCheckBox>> qualifierCheckBoxes,
      final Vector<JCheckBox> geneNameCheckBoxes,
      final Feature orginatingFeature,
      final EntryGroup entryGroup,
      final boolean sameKey,
      final boolean overwrite,
      final boolean setEvidenceAndWithFrom,
      final StringBuffer buff,
      final StringBuffer genesUpdated) {
    // transfer selected annotation to genes
    final QualifierVector qualifiers = orginatingFeature.getQualifiers();
    final QualifierVector qualifiersToTransfer = new QualifierVector();

    Enumeration<JCheckBox> enumQualifiers = qualifierCheckBoxes.keys();
    while (enumQualifiers.hasMoreElements()) {
      JCheckBox cb = enumQualifiers.nextElement();
      if (cb.isSelected()) {
        Vector<JCheckBox> qualifierValuesCheckBox = qualifierCheckBoxes.get(cb);
        final StringVector values = qualifiers.getQualifierByName(cb.getText()).getValues();
        StringVector valuesToTransfer = new StringVector(values);

        logger4j.debug("TRANSFER " + cb.getText());
        for (int i = 0; i < qualifierValuesCheckBox.size(); i++) {
          JCheckBox valuesCb = qualifierValuesCheckBox.get(i);
          if (!valuesCb.isSelected()) {
            valuesToTransfer.remove(valuesCb.getText());
            logger4j.debug("NOT TRANSFERING " + valuesCb.getText());
          }
        }

        if (valuesToTransfer.size() < 1) continue;

        valuesToTransfer =
            new StringVector(
                getTransferValues(
                    setEvidenceAndWithFrom, orginatingFeature, cb.getText(), valuesToTransfer));

        qualifiersToTransfer.addElement(new Qualifier(cb.getText(), valuesToTransfer));
      }
    }

    int count = 0;
    for (int i = 0; i < geneNameCheckBoxes.size(); i++) {
      if (geneNameCheckBoxes.get(i).isSelected()) count++;
    }

    if (count < 1) {
      JOptionPane.showMessageDialog(
          null, "No genes selected.", "Warning", JOptionPane.WARNING_MESSAGE);
      return -1;
    }

    String geneNames[] = new String[count];
    count = 0;
    for (int i = 0; i < geneNameCheckBoxes.size(); i++) {
      JCheckBox cb = geneNameCheckBoxes.get(i);
      if (cb.isSelected()) {
        geneNames[count] = cb.getText();
        logger4j.debug("TRANSFER ANNOTATION TO " + geneNames[count]);
        count++;
      }
    }

    final String key = orginatingFeature.getKey().getKeyString();
    final FeatureVector features = entryGroup.getAllFeatures();

    // transfer selected annotation
    entryGroup.getActionController().startAction();
    geneNames =
        transfer(
            features,
            qualifiersToTransfer,
            key,
            sameKey,
            overwrite,
            GeneUtils.isDatabaseEntry(entryGroup),
            geneNames,
            genesUpdated);
    entryGroup.getActionController().endAction();

    //
    // Commit changes to genes not in Artemis but in the database
    //
    Vector<String> genesNotFound = null;
    if (geneNames != null
        && orginatingFeature.getEntry().getEMBLEntry() instanceof DatabaseDocumentEntry) {
      DatabaseDocumentEntry db_entry =
          (DatabaseDocumentEntry) orginatingFeature.getEntry().getEMBLEntry();
      DatabaseDocument doc = (DatabaseDocument) db_entry.getDocument();

      for (int i = 0; i < geneNames.length; i++) {
        DatabaseDocumentEntry newDbEntry = GeneEdit.makeGeneEntry(null, geneNames[i], doc, null);

        if (newDbEntry == null) {
          if (genesNotFound == null) genesNotFound = new Vector<String>();
          genesNotFound.add(geneNames[i]);
          continue;
        }

        char[] c = new char[1];
        PartialSequence ps = new PartialSequence(c, 100, 0, null, null);
        newDbEntry.setPartialSequence(ps);
        Entry entry = null;
        try {
          entry = new Entry(newDbEntry);
        } catch (Exception e) {
          e.printStackTrace();
        }

        SimpleEntryGroup entry_group = new SimpleEntryGroup();
        entry_group.addElement(entry);

        ChadoTransactionManager ctm = new ChadoTransactionManager();
        entry_group.addFeatureChangeListener(ctm);
        entry_group.addEntryChangeListener(ctm);
        ctm.setEntryGroup(entry_group);

        transfer(
            entry.getAllFeatures(),
            qualifiersToTransfer,
            key,
            sameKey,
            overwrite,
            true,
            geneNames,
            genesUpdated);

        for (int j = 0; j < ctm.getTransactionCount(); j++)
          buff.append(ctm.getTransactionAt(j).getLogComment() + "\n");
        ChadoTransactionManager.commit((DatabaseDocument) newDbEntry.getDocument(), false, ctm);

        entry_group.removeFeatureChangeListener(ctm);
        entry_group.removeEntryChangeListener(ctm);
        // if(newDbEntry != null)
        // GeneEdit.showGeneEditor(null, geneNames[i], newDbEntry);
      }
    }

    if (genesNotFound != null)
      JOptionPane.showMessageDialog(
          null,
          "Gene(s) Not Found:\n" + genesNotFound.toString(),
          "Gene(s) Not Found",
          JOptionPane.WARNING_MESSAGE);
    return 0;
  }
  /** Read key and qualifier mappings for CHADO to EMBL */
  private static void initDatabaseMappings() {
    InputStream keyStream = Options.class.getResourceAsStream("/key_mapping");
    if (keyStream == null) keyStream = Options.class.getResourceAsStream("/etc/key_mapping");

    InputStream qualifierStream = Options.class.getResourceAsStream("/qualifier_mapping");
    if (qualifierStream == null)
      qualifierStream = Options.class.getResourceAsStream("/etc/qualifier_mapping");

    final Properties keyMapProperties = new Properties();
    final Properties qualifierMapProperties = new Properties();
    try {
      keyMapProperties.load(keyStream);
      qualifierMapProperties.load(qualifierStream);

      if (System.getProperty("nohistory") != null)
        qualifierMapProperties.setProperty("history", "");
    } catch (IOException e) {
      e.printStackTrace();
    }

    // parse the keyMapProperties
    DATABASE_MAP_KEYS = new Object[keyMapProperties.size()][3];
    final Enumeration keysenum = keyMapProperties.propertyNames();
    int n = 0;
    while (keysenum.hasMoreElements()) {
      String current_map_name = (String) keysenum.nextElement();

      final StringVector property_values =
          Options.getPropertyValues(keyMapProperties, current_map_name);

      DATABASE_MAP_KEYS[n][0] = current_map_name;
      DATABASE_MAP_KEYS[n][1] = property_values.get(0);
      if (property_values.size() == 2) {
        String qualifierString[] = ((String) property_values.get(1)).split("=");
        final uk.ac.sanger.artemis.io.Qualifier qualifier;
        if (qualifierString.length == 2)
          qualifier = new uk.ac.sanger.artemis.io.Qualifier(qualifierString[0], qualifierString[1]);
        else qualifier = new uk.ac.sanger.artemis.io.Qualifier(qualifierString[0]);
        DATABASE_MAP_KEYS[n][2] = qualifier;
      } else DATABASE_MAP_KEYS[n][2] = null;
      n++;
    }

    // parse the qualifier mappings
    Enumeration qualifiersenum = qualifierMapProperties.propertyNames();
    n = 0;

    Vector qualifiersToRemove = new Vector();
    while (qualifiersenum.hasMoreElements()) {
      String current_map_name = (String) qualifiersenum.nextElement();
      final StringVector property_values =
          Options.getPropertyValues(qualifierMapProperties, current_map_name);
      if (property_values == null || property_values.size() == 0)
        qualifiersToRemove.add(current_map_name);
      else n++;
    }

    DATABASE_QUALIFIERS_TO_MAP = new String[n][2];
    DATABASE_QUALIFIERS_TO_REMOVE = qualifiersToRemove.toArray();

    qualifiersenum = qualifierMapProperties.propertyNames();
    n = 0;

    while (qualifiersenum.hasMoreElements()) {
      String current_map_name = (String) qualifiersenum.nextElement();
      final StringVector property_values =
          Options.getPropertyValues(qualifierMapProperties, current_map_name);
      if (property_values != null && property_values.size() > 0) {
        DATABASE_QUALIFIERS_TO_MAP[n][0] = current_map_name;
        DATABASE_QUALIFIERS_TO_MAP[n][1] = (String) property_values.get(0);
        n++;
      }
    }
  }
  /**
   * Merge qualifiers
   *
   * @param qualifiers
   * @param newQualifiers
   */
  private void combineQualifiers(
      final QualifierVector qualifiers, final QualifierVector newQualifiers, final boolean isGene) {
    for (int i = 0; i < newQualifiers.size(); i++) {
      Qualifier newQualifier = (Qualifier) newQualifiers.get(i);

      if (newQualifier.getName().equals("ID") && !isGene) {
        continue;
      }

      // convert GO evidence to codes (e.g. ND=No biological Data available)
      if (newQualifier.getName().equals("GO")) {
        final StringVector newValues = newQualifier.getValues();
        final StringVector tmpNewValues = new StringVector();
        for (int j = 0; j < newValues.size(); j++) {
          String val = GoBox.getEvidenceCodeGoTextFromText((String) newValues.get(j));
          tmpNewValues.add(val);
        }

        newQualifier = new Qualifier("GO", tmpNewValues);
      }

      if (newQualifier.getName().equals("product")) {
        final StringVector newValues = newQualifier.getValues();
        final StringVector tmpNewValues = new StringVector();
        for (int j = 0; j < newValues.size(); j++) {
          String val = (String) newValues.get(j);

          int ind = 0;
          if ((ind = val.indexOf(";db_xref=")) > -1) val = val.substring(0, ind);

          if ((ind = val.indexOf(";evidence=")) > -1) val = val.substring(0, ind);

          if (val.startsWith("term=")) val = val.substring(5, val.length());

          if (val.endsWith(";")) val = val.substring(0, val.length() - 1);

          tmpNewValues.add(val);
        }

        newQualifier = new Qualifier("product", tmpNewValues);
      }

      if (newQualifier.getName().equals("orthologous_to")
          || newQualifier.getName().equals("paralogous_to")) {
        final StringVector newValues = newQualifier.getValues();
        final StringVector tmpNewValues = new StringVector();
        for (int j = 0; j < newValues.size(); j++) {
          if (!newValues.get(j).equals("")) tmpNewValues.add(newValues.get(j));
        }
        if (tmpNewValues.size() == 0) continue;

        Pattern p = Pattern.compile("\\w+:link=\\w+");
        for (int j = 0; j < tmpNewValues.size(); j++) {
          String valueStr = (String) tmpNewValues.get(j);
          String newValueStr;
          int indexEnd = valueStr.indexOf(';');
          String endStr = "";
          if (indexEnd > -1) endStr = valueStr.substring(indexEnd);
          Matcher m = p.matcher(valueStr);
          while (m.find()) {
            int index = valueStr.indexOf("link=", m.start());
            newValueStr =
                valueStr.substring(m.start(), index)
                    + valueStr.substring(index + 5, m.end())
                    + endStr;
            if (newQualifier.getName().equals("orthologous_to"))
              newQualifier = new Qualifier("orthologous_to", newValueStr);
            else newQualifier = new Qualifier("paralogous_to", newValueStr);
            qualifiers.addElement(newQualifier);
          }
        }
        continue;
      }

      addNewQualifier(qualifiers, newQualifier);
    }
  }
  /**
   * Contruct a component for a similarity line
   *
   * @param similarity
   * @param similarityString
   */
  protected SimilarityTable(final Qualifier simQualifier, final DatabaseDocument doc) {
    this.origQualifiers = new QualifierVector();
    this.origQualifiers.add(simQualifier);

    infoLevelButton.setOpaque(false);
    infoLevelButton.setHorizontalAlignment(SwingConstants.LEFT);
    tableData.setSize(NUMBER_COLUMNS);

    tableData.setElementAt(ORGANISM_COL, 0);
    tableData.setElementAt(HIT_COL, 1);
    tableData.setElementAt(HIT_DBXREF_COL, 2);
    tableData.setElementAt(DESCRIPTION_COL, 3);
    tableData.setElementAt(EVALUE_COL, 4);
    tableData.setElementAt(LENGTH_COL, 5);
    tableData.setElementAt(ID_COL, 6);
    tableData.setElementAt(QUERY_COL, 7);
    tableData.setElementAt(SUBJECT_COL, 8);
    tableData.setElementAt(SCORE_COL, 9);
    tableData.setElementAt(OVERLAP_COL, 10);
    tableData.setElementAt(METHOD_COL, 11);
    tableData.setElementAt(REMOVE_BUTTON_COL, 12);

    // add rows of similarity
    StringVector sims = simQualifier.getValues();
    for (int i = 0; i < sims.size(); i++) rowData.add(getRowData((String) sims.get(i), tableData));

    JTable similarityTable = new JTable(rowData, tableData);
    setTable(similarityTable);

    // set hand cursor
    similarityTable.addMouseMotionListener(
        new MouseMotionAdapter() {
          private Cursor handCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);

          public void mouseMoved(MouseEvent e) {
            int col = table.columnAtPoint(e.getPoint());

            String colName = table.getColumnName(col);

            if (colName.equals(HIT_COL)
                || colName.equals(HIT_DBXREF_COL)
                || colName.equals(REMOVE_BUTTON_COL)) table.setCursor(handCursor);
            else table.setCursor(Cursor.getDefaultCursor());
          }
        });

    similarityTable.setColumnSelectionAllowed(false);
    similarityTable.setRowSelectionAllowed(true);

    packColumn(similarityTable, getColumnIndex(LENGTH_COL), 4);
    packColumn(similarityTable, getColumnIndex(EVALUE_COL), 4);
    packColumn(similarityTable, getColumnIndex(ID_COL), 4);
    packColumn(similarityTable, getColumnIndex(HIT_COL), 6);
    packColumn(similarityTable, getColumnIndex(HIT_DBXREF_COL), 6);

    final TableColumn[] hideColumns = new TableColumn[5];
    hideColumns[0] = similarityTable.getColumn(QUERY_COL);
    hideColumns[1] = similarityTable.getColumn(SUBJECT_COL);
    hideColumns[2] = similarityTable.getColumn(SCORE_COL);
    hideColumns[3] = similarityTable.getColumn(OVERLAP_COL);
    hideColumns[4] = similarityTable.getColumn(METHOD_COL);

    for (int i = 0; i < hideColumns.length; i++) {
      hideColumns[i].setMinWidth(0);
      hideColumns[i].setMaxWidth(0);
    }

    infoLevelButton.addActionListener(
        new ActionListener() {
          private boolean show = true;

          public void actionPerformed(ActionEvent e) {
            // change the column size
            for (int i = 0; i < hideColumns.length; i++) {
              if (show)
                packColumn(getTable(), getColumnIndex((String) hideColumns[i].getHeaderValue()), 2);
              else {
                hideColumns[i].setMinWidth(0);
                hideColumns[i].setMaxWidth(0);
              }
            }
            show = !show;

            if (infoLevelButton.getText().equals("Details"))
              infoLevelButton.setText("Hide Details");
            else infoLevelButton.setText("Details");
          }
        });

    TableModel tableModel = getTable().getModel();
    // remove button column
    TableColumn col = getTable().getColumn(REMOVE_BUTTON_COL);
    col.setMinWidth(35);
    col.setMaxWidth(40);
    col.setPreferredWidth(40);

    final SimilarityRenderer renderer = new SimilarityRenderer();

    for (int columnIndex = 0; columnIndex < tableModel.getColumnCount(); columnIndex++) {
      col = getTable().getColumnModel().getColumn(columnIndex);
      col.setCellRenderer(renderer);
      col.setCellEditor(new CellEditing(new JTextField()));
    }

    col = getTable().getColumn(HIT_COL);
    col.setCellEditor(
        new LinkEditor(new JCheckBox(), (DefaultTableModel) getTable().getModel(), null));

    col = getTable().getColumn(HIT_DBXREF_COL);
    col.setCellEditor(
        new LinkEditor(new JCheckBox(), (DefaultTableModel) getTable().getModel(), null));

    // remove JButton column
    col = getTable().getColumn(REMOVE_BUTTON_COL);
    col.setCellEditor(
        new ButtonEditor(new JCheckBox(), (DefaultTableModel) getTable().getModel(), "X", doc));
  }
  /**
   * Build a vector of the row data
   *
   * @param similarityString
   * @return
   */
  private Vector getRowData(String similarityString, final Vector tableData) {
    Vector row = new Vector(NUMBER_COLUMNS);
    row.setSize(NUMBER_COLUMNS);

    if (similarityString.startsWith("\"")) similarityString = similarityString.substring(1);
    if (similarityString.endsWith("\""))
      similarityString = similarityString.substring(0, similarityString.length() - 1);

    StringVector sim = StringVector.getStrings(similarityString, ";");

    // organism
    if (sim.size() >= 3) {
      int columnIndex = tableData.indexOf(ORGANISM_COL);
      row.setElementAt(((String) sim.get(2)).trim(), columnIndex);
    }

    // hit
    if (sim.size() >= 2) {
      int columnIndex = tableData.indexOf(HIT_COL);

      String hit = ((String) sim.get(1)).trim();

      if (hit.startsWith("with=")) hit = hit.substring(5);

      final String hits[] = hit.split(" ");

      row.setElementAt(hits[0], columnIndex);

      if (hits.length > 1) {
        // dbxref
        columnIndex = tableData.indexOf(HIT_DBXREF_COL);

        if (hits[1].startsWith("(") && hits[1].endsWith(")"))
          hits[1] = hits[1].substring(1, hits[1].length() - 1);

        row.setElementAt(hits[1], columnIndex);
      }
    }

    // description
    if (sim.size() >= 4) {
      int columnIndex = tableData.indexOf(DESCRIPTION_COL);
      row.setElementAt(((String) sim.get(3)).trim(), columnIndex);
    }

    // e-value
    String evalueString;
    if (!(evalueString = getField("E()=", similarityString)).equals("")) {
      int columnIndex = tableData.indexOf(EVALUE_COL);
      row.setElementAt(evalueString, columnIndex);
    }

    // length
    String lenString;
    if (!(lenString = getField("length=", similarityString).trim()).equals("")) {
      int columnIndex = tableData.indexOf(LENGTH_COL);
      row.setElementAt(lenString, columnIndex);
    } else if (!(lenString = getField("length", similarityString).trim()).equals("")) {
      int columnIndex = tableData.indexOf(LENGTH_COL);
      row.setElementAt(lenString, columnIndex);
    }

    String ungappedId;
    if (!(ungappedId = getField("ungapped id", similarityString)).equals("")) {
      int columnIndex = tableData.indexOf(ID_COL);
      row.setElementAt(ungappedId, columnIndex);
    }

    String query;
    if (!(query = getField("query", similarityString).trim()).equals("")) {
      int columnIndex = tableData.indexOf(QUERY_COL);
      row.setElementAt(query, columnIndex);
    }

    String subject;
    if (!(subject = getField("subject", similarityString).trim()).equals("")) {
      int columnIndex = tableData.indexOf(SUBJECT_COL);
      row.setElementAt(subject, columnIndex);
    }

    String score;
    if (!(score = getField("score=", similarityString)).equals("")) {
      int columnIndex = tableData.indexOf(SCORE_COL);
      row.setElementAt(score, columnIndex);
    }

    String overlap;
    if (!(overlap = getField("overlap=", similarityString)).equals("")) {
      int columnIndex = tableData.indexOf(OVERLAP_COL);
      row.setElementAt(overlap, columnIndex);
    } else if (similarityString.indexOf("overlap;") > -1) {
      overlap = null;
      for (int i = 0; i < sim.size(); i++) {
        String val = (String) sim.get(i);
        if (val.endsWith("overlap")) {
          overlap = val;
          break;
        }
      }
      if (overlap != null) {
        int columnIndex = tableData.indexOf(OVERLAP_COL);
        row.setElementAt(overlap, columnIndex);
      }
    }

    int columnIndex = tableData.indexOf(METHOD_COL);
    row.setElementAt(((String) sim.get(0)).trim(), columnIndex);
    return row;
  }