void printBodyCoverage(MethodCoverage mc) {
      MethodInfo mi = mc.getMethodInfo();
      Instruction[] code = mi.getInstructions();
      BitSet cov = mc.getExecutedInsn();
      int i, start = -1;

      BitSet handlers = mc.getHandlers();

      if (excludeHandlers) {
        cov.andNot(handlers);
      }

      for (i = 0; i < code.length; i++) {
        if (!cov.get(i)) { // not covered
          if (start == -1) {
            start = i;
          }
        } else { // covered
          if (start != -1) {
            printSourceRange(code, handlers, start, i - 1, "");
            start = -1;
          }
        }
      }
      if (start != -1) {
        printSourceRange(code, handlers, start, i - 1, "");
      }

      // now print the missing branches
      BitSet branches = mc.getBranches();
      lastStart = -1; // reset in case condition and branch are in same line
      for (i = 0; i < code.length; i++) {
        if (branches.get(i)) {
          String prefix = "";
          BitSet bTrue = mc.branchTrue;
          BitSet bFalse = mc.branchFalse;
          if (bTrue != null) { // means we have condition bit sets
            boolean cTrue = bTrue.get(i);
            boolean cFalse = bFalse.get(i);
            if (cTrue) {
              prefix = cFalse ? "" : "F "; // covered or false missing
            } else {
              prefix = cFalse ? "T " : "N "; // true or both missing
            }
          } else {
            prefix = "N "; // not covered at all
          }

          if (prefix != null) {
            printSourceRange(code, handlers, i, i, prefix);
          }
        }
      }
    }
  public void instructionExecuted(JVM vm) {
    Instruction insn = vm.getLastInstruction();
    MethodCoverage mc = getMethodCoverage(vm);

    if (mc != null) {
      mc.setExecuted(vm.getLastThreadInfo(), insn);

      if (showRequirements) {
        if (insn.getPosition() == 0) { // first insn in method, check for Requirements
          AnnotationInfo ai = getRequirementsAnnotation(mc.getMethodInfo());
          if (ai != null) {
            String[] ids = ai.getValueAsStringArray();
            updateRequirementsCoverage(ids, mc);
          }
        }
      }
    }
  }
    void printMethodCoverages(ClassCoverage cc) {
      String space = "  ";
      boolean result = true;

      if (cc.methods == null) {
        return;
      }

      ArrayList<Map.Entry<MethodInfo, MethodCoverage>> mthEntries =
          Misc.createSortedEntryList(
              cc.methods,
              new Comparator<Map.Entry<MethodInfo, MethodCoverage>>() {

                public int compare(
                    Map.Entry<MethodInfo, MethodCoverage> o1,
                    Map.Entry<MethodInfo, MethodCoverage> o2) {
                  int a = o2.getValue().getCoveredInsn().percent();
                  int b = o1.getValue().getCoveredInsn().percent();

                  if (a == b) {
                    return o2.getKey().getUniqueName().compareTo(o1.getKey().getUniqueName());
                  } else {
                    return a - b;
                  }
                }
              });

      Coverage emptyCoverage = new Coverage(0, 0);

      for (Map.Entry<MethodInfo, MethodCoverage> e : mthEntries) {
        MethodCoverage mc = e.getValue();
        MethodInfo mi = mc.getMethodInfo();
        Coverage insnCoverage = mc.getCoveredInsn();
        Coverage lineCoverage = mc.getCoveredLines();
        Coverage branchCoverage = mc.getCoveredBranches();

        result = result && insnCoverage.isFullyCovered();

        pw.print(space);
        printCoverage(insnCoverage);

        pw.print(space);
        printCoverage(lineCoverage);

        pw.print(space);
        printCoverage(mc.getCoveredBasicBlocks());

        pw.print(space);
        printCoverage(branchCoverage);

        pw.print(space);
        printCoverage(emptyCoverage);

        pw.print(space);
        pw.print(mi.getLongName());
        pw.println();

        if (showMethodBodies
            && (!insnCoverage.isFullyCovered() || !branchCoverage.isFullyCovered())) {
          printBodyCoverage(mc);
        }
      }
    }
    void printRequirementsCoverage() {
      HashMap<String, Integer> reqMethods = getGlobalRequirementsMethods();

      String space = "  ";
      Coverage bbAll = new Coverage(0, 0);
      Coverage insnAll = new Coverage(0, 0);
      Coverage branchAll = new Coverage(0, 0);
      Coverage mthAll = new Coverage(0, 0);
      Coverage reqAll = new Coverage(0, 0);

      reqAll.total = reqMethods.size();
      mthAll.total = computeTotalRequirementsMethods(reqMethods);

      pw.println();
      pw.println();
      pw.println(
          "--------------------------------- requirements coverage -----------------------------------");
      pw.println(
          "bytecode            basic-block         branch              methods             requirement");
      pw.println(
          "-------------------------------------------------------------------------------------------");

      for (String id : Misc.getSortedKeyStrings(reqMethods)) {

        Coverage bbCoverage = new Coverage(0, 0);
        Coverage insnCoverage = new Coverage(0, 0);
        Coverage branchCoverage = new Coverage(0, 0);
        Coverage reqMth = new Coverage(reqMethods.get(id), 0);

        if (requirements != null && requirements.containsKey(id)) {
          reqAll.covered++;
          for (MethodCoverage mc : requirements.get(id)) {
            insnCoverage.add(mc.getCoveredInsn());
            bbCoverage.add(mc.getCoveredBasicBlocks());
            branchCoverage.add(mc.getCoveredBranches());

            mthAll.covered++;
            reqMth.covered++;
          }

          printCoverage(insnCoverage);
          pw.print(space);
          printCoverage(bbCoverage);
          pw.print(space);
          printCoverage(branchCoverage);
          pw.print(space);
          printCoverage(reqMth);
          pw.print("\"" + id + "\"");

          pw.println();

          if (showMethods) {
            for (MethodCoverage mc : requirements.get(id)) {

              pw.print(space);
              printCoverage(mc.getCoveredInsn());
              pw.print(space);
              printCoverage(mc.getCoveredBasicBlocks());
              pw.print(space);
              printCoverage(mc.getCoveredBranches());
              pw.print(space);

              pw.print(mc.getMethodInfo().getFullName());
              pw.println();
            }
          }
        } else { // requirement not covered
          pw.print(" -                   -                   -                  ");

          printCoverage(reqMth);
          pw.print("\"" + id + "\"");
          pw.println();
        }

        insnAll.add(insnCoverage);
        bbAll.add(bbCoverage);
        branchAll.add(branchCoverage);
      }

      pw.println();
      pw.println(
          "------------------------------------------------------------------------------------------");

      printCoverage(insnAll);
      pw.print(space);
      printCoverage(bbAll);
      pw.print(space);
      printCoverage(branchAll);
      pw.print(space);
      printCoverage(mthAll);
      pw.print(space);
      printCoverage(reqAll);
      pw.print(" total");

      pw.println();
    }
    void printRequirementsCoverage() {
      HashMap<String, Integer> reqMethods = getGlobalRequirementsMethods();

      Coverage bbAll = new Coverage(0, 0);
      Coverage insnAll = new Coverage(0, 0);
      Coverage branchAll = new Coverage(0, 0);
      Coverage mthAll = new Coverage(0, 0);
      Coverage reqAll = new Coverage(0, 0);

      reqAll.total = reqMethods.size();
      mthAll.total = computeTotalRequirementsMethods(reqMethods);

      pw.println("      <p><b>Requirements Coverage</b></p>");
      pw.println("      <table>");
      pw.println(
          "         <tr><th colspan=\"4\">Instructions</th><th colspan=\"4\">Basic Block</th><th colspan=\"4\">Branch</th><th colspan=\"4\">Methods</th><th colspan=\"4\">Requirement</th></tr>");

      for (String id : Misc.getSortedKeyStrings(reqMethods)) {

        Coverage bbCoverage = new Coverage(0, 0);
        Coverage insnCoverage = new Coverage(0, 0);
        Coverage branchCoverage = new Coverage(0, 0);
        Coverage reqMth = new Coverage(reqMethods.get(id), 0);

        if (requirements != null && requirements.containsKey(id)) {
          reqAll.covered++;
          for (MethodCoverage mc : requirements.get(id)) {
            insnCoverage.add(mc.getCoveredInsn());
            bbCoverage.add(mc.getCoveredBasicBlocks());
            branchCoverage.add(mc.getCoveredBranches());

            mthAll.covered++;
            reqMth.covered++;
          }

          pw.print("         <tr>");

          printCoverage(insnCoverage);
          printCoverage(bbCoverage);
          printCoverage(branchCoverage);
          printCoverage(reqMth);
          pw.print("\"" + id + "\"");

          pw.print("</tr>");

          pw.println();

          if (showMethods) {
            for (MethodCoverage mc : requirements.get(id)) {

              pw.print("         <tr>");

              printCoverage(mc.getCoveredInsn());
              printCoverage(mc.getCoveredBasicBlocks());
              printCoverage(mc.getCoveredBranches());

              pw.print("<td align=\"left\" colspan=\"4\" style=\"padding-right: 10px;\">");

              pw.print(mc.getMethodInfo().getFullName());

              pw.print("</tr>");

              pw.println();
            }
          }
        } else { // requirement not covered
          pw.print(
              "         <tr><td colspan=\"4\"></td><td colspan=\"4\"></td><td colspan=\"4\"></td>");

          printCoverage(reqMth);
          pw.print("\"" + id + "\"");

          pw.print("</tr>");

          pw.println();
        }

        insnAll.add(insnCoverage);
        bbAll.add(bbCoverage);
        branchAll.add(branchCoverage);
      }

      pw.print("         <tr>");

      printCoverage(insnAll);
      printCoverage(bbAll);
      printCoverage(branchAll);
      printCoverage(mthAll);
      printCoverage(reqAll);
      pw.print(" total");

      pw.println("</tr>");
      pw.println("      </table>");
    }
    void printMethodCoverages(ClassCoverage cc) {
      String classNameTree = "cc-" + cc.className.replace('.', '-') + '-';
      int line, lineNumbers[];
      boolean result = true;

      if (cc.methods == null) {
        return;
      }

      ArrayList<Map.Entry<MethodInfo, MethodCoverage>> mthEntries =
          Misc.createSortedEntryList(
              cc.methods,
              new Comparator<Map.Entry<MethodInfo, MethodCoverage>>() {

                public int compare(
                    Map.Entry<MethodInfo, MethodCoverage> o1,
                    Map.Entry<MethodInfo, MethodCoverage> o2) {
                  int a = o2.getValue().getCoveredInsn().percent();
                  int b = o1.getValue().getCoveredInsn().percent();

                  if (a == b) {
                    return o2.getKey().getUniqueName().compareTo(o1.getKey().getUniqueName());
                  } else {
                    return a - b;
                  }
                }
              });

      for (Map.Entry<MethodInfo, MethodCoverage> e : mthEntries) {
        MethodCoverage mc = e.getValue();
        MethodInfo mi = mc.getMethodInfo();
        Coverage insnCoverage = mc.getCoveredInsn();
        Coverage lineCoverage = mc.getCoveredLines();
        Coverage branchCoverage = mc.getCoveredBranches();

        result = result && insnCoverage.isFullyCovered();

        HTMLPublisher.writeTableTreeNodeBegin(
            pw, classNameTree + HTMLPublisher.escape(mi.getLongName()));
        pw.print("            <td class=\"firstCol\">");

        lineNumbers = mi.getLineNumbers();
        if ((lineNumbers != null) && (lineNumbers.length > 0)) {
          line = lineNumbers[0];
        } else {
          line = 0;
        }

        ((HTMLPublisher) publisher).writeSourceAnchor(pw, mi.getSourceFileName(), line);

        pw.print(HTMLPublisher.escape(mi.getLongName()));
        pw.println("</a></td>");

        pw.print("            ");

        printCoverage(insnCoverage);
        printCoverage(lineCoverage);
        printCoverage(mc.getCoveredBasicBlocks());
        printCoverage(branchCoverage);

        pw.println();
        HTMLPublisher.writeTableTreeNodeEnd(pw);
      }
    }