View Javadoc

    1   package net.sourceforge.pmd.lang.dfa.report;
    2
    3   import net.sourceforge.pmd.RuleViolation;
    4   import net.sourceforge.pmd.PMD;
    5   import net.sourceforge.pmd.util.IOUtil;
    6   import net.sourceforge.pmd.util.StringUtil;
    7
    8   import java.io.BufferedWriter;
    9   import java.io.File;
    10  import java.io.FileWriter;
    11  import java.io.IOException;
    12
    13  /**
    14   * @author raik
    15   *         <p/>
    16   *         * Uses the generated result tree instead of the result list. The visitor
    17   *         * traverses the tree and creates several html files. The "package view" file
    18   *         * (index.html) displays an overview of packages, classes and the number of
    19   *         * rule violations they contain. All the other html files represent a class
    20   *         * and show detailed information about the violations.
    21   */
    22  public class ReportHTMLPrintVisitor extends ReportVisitor {
    23
    24      @SuppressWarnings("PMD.AvoidStringBufferField")
    25      private StringBuilder packageBuf = new StringBuilder();
    26      @SuppressWarnings("PMD.AvoidStringBufferField")
    27      private StringBuilder classBuf = new StringBuilder();
    28      private int length;
    29      private String baseDir;
    30
    31      private static final String FILE_SEPARATOR = System.getProperty("file.separator");
    32
    33      public ReportHTMLPrintVisitor(String baseDir) {
    34          this.baseDir = baseDir;
    35      }
    36
    37      /**
    38       * Writes the buffer to file.
    39       */
    40      private void write(String filename, StringBuilder buf) throws IOException {
    41          BufferedWriter bw = new BufferedWriter(new FileWriter(new File(baseDir + FILE_SEPARATOR + filename)));
    42          bw.write(buf.toString(), 0, buf.length());
    43          IOUtil.closeQuietly(bw);
    44      }
    45
    46      /**
    47       * Generates a html table with violation information.
    48       */
    49      private String displayRuleViolation(RuleViolation vio) {
    50
    51      	StringBuilder sb = new StringBuilder(200);
    52          sb.append("<table border=\"0\">");
    53          renderViolationRow(sb, "Rule:", vio.getRule().getName());
    54          renderViolationRow(sb, "Description:", vio.getDescription());
    55
    56          if (StringUtil.isNotEmpty(vio.getVariableName())) {
    57          	renderViolationRow(sb, "Variable:", vio.getVariableName());
    58          }
    59
    60          if (vio.getEndLine() > 0) {
    61          	renderViolationRow(sb, "Line:", vio.getEndLine() + " and " + vio.getBeginLine());
    62          } else {
    63          	renderViolationRow(sb, "Line:", Integer.toString(vio.getBeginLine()));
    64          }
    65
    66          sb.append("</table>");
    67          return sb.toString();
    68      }
    69
    70      // TODO - join the 21st century, include CSS attributes :)
    71      private void renderViolationRow(StringBuilder sb, String fieldName, String fieldData) {
    72      	sb.append("<tr><td><b>").append(fieldName).append("</b></td><td>").append(fieldData).append("</td></tr>");
    73      }
    74
    75      /**
    76       * The visit method (Visitor Pattern). There are 3 types of ReportNodes:
    77       * RuleViolation - contains a RuleViolation, Class - represents a class and
    78       * contains the name of the class, Package - represents a package and
    79       * contains the name(s) of the package.
    80       */
    81      public void visit(AbstractReportNode node) {
    82
    83          /*
    84           * The first node of result tree.
    85           */
    86          if (node.getParent() == null) {
    87              packageBuf.insert(0,
    88                      "<html>" +
    89                      " <head>" +
    90                      "   <title>PMD</title>" +
    91                      " </head>" +
    92                      " <body>" + PMD.EOL +
    93                      "<h2>Package View</h2>" +
    94                      "<table border=\"1\" align=\"center\" cellspacing=\"0\" cellpadding=\"3\">" +
    95                      " <tr>" + PMD.EOL +
    96                      "<th>Package</th>" +
    97                      "<th>Class</th>" +
    98                      "<th>#</th>" +
    99                      " </tr>" + PMD.EOL);
    100
    101             length = packageBuf.length();
    102         }
    103
    104         super.visit(node);
    105
    106         if (node instanceof ViolationNode) {
    107             renderViolation((ViolationNode)node);
    108         }
    109         if (node instanceof ClassNode) {
    110             renderClass((ClassNode)node);
    111         }
    112         if (node instanceof PackageNode) {
    113             renderPackage((PackageNode)node);
    114         }
    115
    116         // The first node of result tree.
    117         if (node.getParent() == null) {
    118             packageBuf.append("</table> </body></html>");
    119             try {
    120                 write("index.html", packageBuf);
    121             } catch (Exception e) {
    122                 throw new RuntimeException("Error while writing HTML report: " + e.getMessage());
    123             }
    124         }
    125     }
    126
    127 	private void renderViolation(ViolationNode vnode) {
    128
    129 		vnode.getParent().addNumberOfViolation(1);
    130 		RuleViolation vio = vnode.getRuleViolation();
    131 		classBuf.append("<tr>" +
    132 		        " <td>" + vio.getMethodName() + "</td>" +
    133 		        " <td>" + this.displayRuleViolation(vio) + "</td>" +
    134 		        "</tr>");
    135 	}
    136
    137 	private void renderPackage(PackageNode pnode) {
    138
    139 		String str;
    140
    141 		// rootNode
    142 		if (pnode.getParent() == null) {
    143 		    str = "Aggregate";
    144 		} else {           // all the other nodes
    145 		    str = pnode.getPackageName();
    146 		    pnode.getParent().addNumberOfViolation(pnode.getNumberOfViolations());
    147 		}
    148
    149 		packageBuf.insert(length,
    150 		        "<tr><td><b>" + str + "</b></td>" +
    151 		        " <td>-</td>" +
    152 		        " <td>" + pnode.getNumberOfViolations() + "</td>" +
    153 		        "</tr>" + PMD.EOL);
    154 	}
    155
    156 	private void renderClass(ClassNode cnode) {
    157
    158 		String str = cnode.getClassName();
    159
    160 		classBuf.insert(0,
    161 		        "<html><head><title>PMD - " + str + "</title></head><body>" + PMD.EOL +
    162 		        "<h2>Class View</h2>" +
    163 		        "<h3 align=\"center\">Class: " + str + "</h3>" +
    164 		        "<table border=\"\" align=\"center\" cellspacing=\"0\" cellpadding=\"3\">" +
    165 		        " <tr>" + PMD.EOL +
    166 		        "<th>Method</th>" +
    167 		        "<th>Violation</th>" +
    168 		        " </tr>" + PMD.EOL);
    169
    170 		classBuf.append("</table>" +
    171 		        " </body>" +
    172 		        "</html>");
    173
    174
    175 		try {
    176 		    write(str + ".html", classBuf);
    177 		} catch (Exception e) {
    178 		    throw new RuntimeException("Error while writing HTML report: " + e.getMessage());
    179 		}
    180 		classBuf = new StringBuilder();
    181
    182 		packageBuf.insert(this.length,
    183 		        "<tr>" +
    184 		        " <td>-</td>" +
    185 		        " <td><a href=\"" + str + ".html\">" + str + "</a></td>" +
    186 		        " <td>" + cnode.getNumberOfViolations() + "</td>" +
    187 		        "</tr>" + PMD.EOL);
    188 		cnode.getParent().addNumberOfViolation(cnode.getNumberOfViolations());
    189 	}
    190 }