/**
   * Maps database (SO) keys to EMBl keys. It will add any extra qualifiers found in the 3rd column
   * of DATABASE_MAP_KEYS.
   *
   * @param key
   * @return
   */
  private Key map(final Key key, final QualifierVector qualifiers) {
    if (DATABASE_MAP_KEYS == null) initDatabaseMappings();
    for (int i = 0; i < DATABASE_MAP_KEYS.length; i++) {
      if (key.getKeyString().equals(DATABASE_MAP_KEYS[i][0])) {
        Key mappedKey = new Key((String) DATABASE_MAP_KEYS[i][1]);
        if (DATABASE_MAP_KEYS[i][2] != null) {

          Qualifier newQualifier = (Qualifier) DATABASE_MAP_KEYS[i][2];
          if (!getEntryInformation().isValidQualifier(mappedKey, newQualifier.getName())) {
            try {
              final int nvalues;
              if (newQualifier.getValues() == null) nvalues = 0;
              else nvalues = newQualifier.getValues().size();

              final int type;
              if (nvalues == 0) type = QualifierInfo.NO_VALUE;
              else type = QualifierInfo.QUOTED_TEXT;
              getEntryInformation()
                  .addQualifierInfo(
                      new QualifierInfo(newQualifier.getName(), type, null, null, false));
            } catch (QualifierInfoException e) {
            }
          }

          qualifiers.addQualifierValues(newQualifier);
        }

        return mappedKey;
      }
    }
    return key;
  }
  /**
   * 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);
  }
  /**
   * Change the name of a qualifier
   *
   * @param qualifiers
   * @param oldName
   * @param newName
   */
  private void changeQualifierName(
      QualifierVector qualifiers, final String oldName, final String newName) {
    QualifierVector tmpQualifiers = new QualifierVector();
    for (int i = 0; i < qualifiers.size(); i++) {
      Qualifier qualifier = (Qualifier) qualifiers.elementAt(i);
      if (!qualifier.getName().equals(oldName)) {
        tmpQualifiers.addElement(qualifier);
        continue;
      }

      Qualifier newQualifier = new Qualifier(newName, qualifier.getValues());
      tmpQualifiers.addQualifierValues(newQualifier);
    }
    qualifiers.removeAllElements();

    for (int i = 0; i < tmpQualifiers.size(); i++)
      qualifiers.addElement(tmpQualifiers.elementAt(i));
  }
  /**
   * 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);
    }
  }