001 package net.sourceforge.pmd.lang.dfa.report;
002
003 import net.sourceforge.pmd.RuleViolation;
004 import net.sourceforge.pmd.PMD;
005
006 import java.io.BufferedWriter;
007 import java.io.File;
008 import java.io.FileWriter;
009 import java.io.IOException;
010
011 /**
012 * @author raik
013 * <p/>
014 * * Uses the generated result tree instead of the result list. The visitor
015 * * traverses the tree and creates several html files. The "package view" file
016 * * (index.html) displays an overview of packgages, classes and the number of
017 * * rule violations they contain. All the other html files represent a class
018 * * and show detailed information about the violations.
019 */
020 public class ReportHTMLPrintVisitor extends ReportVisitor {
021
022 @SuppressWarnings("PMD.AvoidStringBufferField")
023 private StringBuffer packageBuf = new StringBuffer();
024 @SuppressWarnings("PMD.AvoidStringBufferField")
025 private StringBuffer classBuf = new StringBuffer();
026 private int length;
027 private String baseDir;
028
029 private static final String FILE_SEPARATOR = System.getProperty("file.separator");
030
031 public ReportHTMLPrintVisitor(String baseDir) {
032 this.baseDir = baseDir;
033 }
034
035 /**
036 * Writes the buffer to file.
037 */
038 private void write(String filename, StringBuffer buf) throws IOException {
039 BufferedWriter bw = new BufferedWriter(new FileWriter(new File(baseDir + FILE_SEPARATOR + filename)));
040 bw.write(buf.toString(), 0, buf.length());
041 bw.close();
042 }
043
044 /**
045 * Generates a html table with violation information.
046 */
047 private String displayRuleViolation(RuleViolation vio) {
048
049 StringBuffer sb = new StringBuffer(200);
050 sb.append("<table border=\"0\">");
051 sb.append("<tr><td><b>Rule:</b></td><td>").append(vio.getRule().getName()).append("</td></tr>");
052 sb.append("<tr><td><b>Description:</b></td><td>").append(vio.getDescription()).append("</td></tr>");
053
054 if (vio.getVariableName().length() > 0) {
055 sb.append("<tr><td><b>Variable:</b></td><td>").append(vio.getVariableName()).append("</td></tr>");
056 }
057
058 if (vio.getEndLine() > 0) {
059 sb.append("<tr><td><b>Line:</b></td><td>").append(vio.getEndLine()).append(" and ").append(vio.getBeginLine()).append("</td></tr>");
060 } else {
061 sb.append("<tr><td><b>Line:</b></td><td>").append(vio.getBeginLine()).append("</td></tr>");
062 }
063
064 sb.append("</table>");
065 return sb.toString();
066 }
067
068 /**
069 * The visit method (Visitor Pattern). There are 3 types of ReportNodes:
070 * RuleViolation - contains a RuleViolation, Class - represents a class and
071 * contains the name of the class, Package - represents a package and
072 * contains the name(s) of the package.
073 */
074 public void visit(AbstractReportNode node) {
075
076 /*
077 * The first node of result tree.
078 */
079 if (node.getParent() == null) {
080 this.packageBuf.insert(0,
081 "<html>" +
082 " <head>" +
083 " <title>PMD</title>" +
084 " </head>" +
085 " <body>" + PMD.EOL +
086 "<h2>Package View</h2>" +
087 "<table border=\"1\" align=\"center\" cellspacing=\"0\" cellpadding=\"3\">" +
088 " <tr>" + PMD.EOL +
089 "<th>Package</th>" +
090 "<th>Class</th>" +
091 "<th>#</th>" +
092 " </tr>" + PMD.EOL);
093
094 this.length = this.packageBuf.length();
095 }
096
097
098 super.visit(node);
099
100
101 if (node instanceof ViolationNode) {
102 ViolationNode vnode = (ViolationNode) node;
103 vnode.getParent().addNumberOfViolation(1);
104 RuleViolation vio = vnode.getRuleViolation();
105 classBuf.append("<tr>" +
106 " <td>" + vio.getMethodName() + "</td>" +
107 " <td>" + this.displayRuleViolation(vio) + "</td>" +
108 "</tr>");
109 }
110 if (node instanceof ClassNode) {
111 ClassNode cnode = (ClassNode) node;
112 String str = cnode.getClassName();
113
114 classBuf.insert(0,
115 "<html><head><title>PMD - " + str + "</title></head><body>" + PMD.EOL +
116 "<h2>Class View</h2>" +
117 "<h3 align=\"center\">Class: " + str + "</h3>" +
118 "<table border=\"\" align=\"center\" cellspacing=\"0\" cellpadding=\"3\">" +
119 " <tr>" + PMD.EOL +
120 "<th>Method</th>" +
121 "<th>Violation</th>" +
122 " </tr>" + PMD.EOL);
123
124 classBuf.append("</table>" +
125 " </body>" +
126 "</html>");
127
128
129 try {
130 this.write(str + ".html", classBuf);
131 } catch (Exception e) {
132 throw new RuntimeException("Error while writing HTML report: " + e.getMessage());
133 }
134 classBuf = new StringBuffer();
135
136
137 this.packageBuf.insert(this.length,
138 "<tr>" +
139 " <td>-</td>" +
140 " <td><a href=\"" + str + ".html\">" + str + "</a></td>" +
141 " <td>" + node.getNumberOfViolations() + "</td>" +
142 "</tr>" + PMD.EOL);
143 node.getParent().addNumberOfViolation(node.getNumberOfViolations());
144 }
145 if (node instanceof PackageNode) {
146 PackageNode pnode = (PackageNode) node;
147 String str;
148
149 // rootNode
150 if (node.getParent() == null) {
151 str = "Aggregate";
152 } else { // all the other nodes
153 str = pnode.getPackageName();
154 node.getParent().addNumberOfViolation(node.getNumberOfViolations());
155 }
156
157 this.packageBuf.insert(this.length,
158 "<tr><td><b>" + str + "</b></td>" +
159 " <td>-</td>" +
160 " <td>" + node.getNumberOfViolations() + "</td>" +
161 "</tr>" + PMD.EOL);
162 }
163 // The first node of result tree.
164 if (node.getParent() == null) {
165 this.packageBuf.append("</table> </body></html>");
166 try {
167 this.write("index.html", this.packageBuf);
168 } catch (Exception e) {
169 throw new RuntimeException("Error while writing HTML report: " + e.getMessage());
170 }
171 }
172 }
173 }
|