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 }