/**
   * this is what a Mapper does
   *
   * @param keyin
   * @param valuein
   * @return iterator over mapped key values
   */
  @Nonnull
  @Override
  public Iterable<KeyValueObject<String, String>> mapValues(
      @Nonnull final String annotation, @Nonnull final String sequence) {

    List<KeyValueObject<String, String>> holder = new ArrayList<KeyValueObject<String, String>>();

    IPeptideDigester digester = getDigester();
    IProtein prot = Protein.getProtein(annotation, annotation, sequence, null);

    // do a boolean for a peptide belonging to a decoy protein, but use the public isDecoy
    // boolean/method in Protein class

    boolean isDecoy = prot.isDecoy();

    IPolypeptide[] pps = digester.digest(prot);
    PeptideModification[] modifications1 = getModifications();
    for (int i = 0; i < pps.length; i++) {
      IPolypeptide pp = pps[i];

      if (!pp.isValid()) continue;

      // hadoop write intermediate seq finder
      writePeptide(pp, holder);

      //   if(isDecoy)
      //       continue; // skip the rest of the loop

      // if it is decoy, don't add modifications to it
      if (!isDecoy || isGenerateDecoysForModifiedPeptides()) {
        //  generate modified peptides and add to the output
        IModifiedPeptide[] modifications =
            ModifiedPolypeptide.buildModifications(pp, modifications1);
        for (int m = 0; m < modifications.length; m++) {
          IModifiedPeptide modification = modifications[m];
          writePeptide(modification, holder);
        }
      }
    }

    boolean semiTryptic = digester.isSemiTryptic();
    if (semiTryptic) {
      IPolypeptide[] semipps = digester.addSemiCleavages(prot);
      for (int j = 0; j < semipps.length; j++) {
        IPolypeptide semipp = semipps[j];
        if (!semipp.isValid()) continue;
        writePeptide(semipp, holder);
        IModifiedPeptide[] modifications =
            ModifiedPolypeptide.buildModifications(semipp, modifications1);
        for (int k = 0; k < modifications.length; k++) {
          IModifiedPeptide modification = modifications[k];
          writePeptide(modification, holder);
        }
      }
    }
    return holder;
  }
  public void appendProteins(Appendable out) {
    try {
      List<String> proteins = new ArrayList<String>(proteinToHits.keySet());
      Collections.sort(proteins);
      for (String protein : proteins) {
        Set<IdentifiedPSM> pps = proteinToHits.get(protein);
        List<IdentifiedPSM> psms = new ArrayList<IdentifiedPSM>(pps);
        Collections.sort(psms);

        out.append(protein);
        for (IdentifiedPSM psm : psms) {
          out.append("\t");
          IPolypeptide unModified = psm.getPeptide(); // .getUnModified();
          out.append(unModified.toString());
          out.append("\t");
          out.append(psm.getId());
        }
        out.append("\n");
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  protected void writePeptide(IPolypeptide pp, List<KeyValueObject<String, String>> holder) {
    long numberFragments = getAndIncrementFragmentIndex();

    String str = pp.toString();
    holder.add(new KeyValueObject<String, String>(str, pp.toString()));
  }
  public void setDecoy(boolean isso) {
    if (m_Peptide == null) return;
    if (m_Peptide.isDecoy() == isso) return;

    if (isso) m_Peptide = m_Peptide.asDecoy();
  }
 public boolean isDecoy() {
   if (m_Peptide != null) return m_Peptide.isDecoy();
   else return false;
 }