Clean up error handling to make things slightly friendlier on an initial install.
[cfb.git] / prod / net / jaekl / cfb / analyze / HtmlReport.java
1 package net.jaekl.cfb.analyze;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.PrintWriter;
6
7 import net.jaekl.cfb.CfbBundle;
8 import net.jaekl.cfb.store.Location;
9 import net.jaekl.cfb.util.Command;
10 import net.jaekl.cfb.xml.BugInstance;
11 import net.jaekl.cfb.xml.messages.BugPattern;
12 import net.jaekl.cfb.xml.messages.MessageCollection;
13
14 public class HtmlReport {
15         CfbBundle m_bundle;
16         Delta m_delta;
17         MessageCollection m_msgColl;
18         
19         public HtmlReport(CfbBundle bundle, MessageCollection msgColl, Delta delta)
20         {
21                 m_bundle = bundle;
22                 m_delta = delta;
23                 m_msgColl = msgColl;
24         }
25         
26         public Delta getDelta() { return m_delta; }
27         
28         public void write(File output) throws IOException
29         {
30                 try ( PrintWriter pw = new PrintWriter(output, Command.UTF_8) )
31                 {
32                         write(pw);
33                         pw.flush();
34                 }
35         }
36         
37         void write(PrintWriter pw) 
38         {
39                 startPage(pw);
40         }
41         
42         void startPage(PrintWriter pw) 
43         {
44                 writeHeader(pw);
45                 pw.println("  <BODY>");
46                 writeBody(pw);
47                 pw.println("  </BODY>");
48                 pw.println("</HTML>");
49         }
50         
51         String trans(String key, Object... arguments) {
52                 return m_bundle.get(key, arguments);
53         }
54         
55         void writeBody(PrintWriter pw)
56         {
57                 writeSummary(pw);
58                 writeBugs(pw, CfbBundle.NEW_BUGS,   m_delta.getNew());
59                 writeBugs(pw, CfbBundle.FIXED_BUGS, m_delta.getFixed());
60                 writeBugs(pw, CfbBundle.OLD_BUGS,   m_delta.getCommon());
61         }
62         
63         void writeBugLocations(PrintWriter pw, BugInstance bug)
64         {
65                 for (Location loc : bug.getLocations()) {
66                         StringBuffer sb = new StringBuffer();
67                         
68                         if (null != loc) {
69                                 if (null != loc.getClassName()) {
70                                         sb.append(loc.getClassName());
71                                 }
72                                 if ((null != loc.getMethodName()) && (loc.getMethodName().length() > 0)) {
73                                         sb.append(".").append(loc.getMethodName()).append("()");
74                                 }
75                                 int start = loc.getStart();
76                                 int end = loc.getEnd();
77                                 if (start > 0) {
78                                         sb.append(":").append("" + start);
79                                         if ((end > 0) && (end > start)) {
80                                                 sb.append("-").append("" + end);
81                                         }
82                                 }
83                                 
84                                 if (null != loc.getMethodRole()) {
85                                         sb.append(" (" + loc.getMethodRole() + ")");
86                                 }
87                         }
88                         
89                         pw.println("        <TR><TD COLSPAN=\"2\" CLASS=\"Loc\">" + sb.toString() + "</TD></TR>");                                      
90                 }
91         }
92         
93         void writeBugs(PrintWriter pw, String key, BugInstance[] bugs)
94         {
95                 if (null == bugs || bugs.length < 1) {
96                         return;
97                 }
98                 
99                 writeSectionHeading(pw, trans(key));
100                 
101                 for (BugInstance bug : bugs) {
102                         BugPattern pattern = m_msgColl.getPattern(bug.getType());
103                         
104                         pw.println("    <P>");
105                         pw.println("      <TABLE CLASS=\"Bug\">");
106                         pw.println("        <TR>");
107                         pw.println("          <TD WIDTH=\"20%\">" + bug.getCategory() + "</TD>");
108                         pw.println("          <TD>" + bug.getType() + "</TD>");
109                         pw.println("        </TR>");
110                         writeBugLocations(pw, bug);
111                         pw.println("        <TR><TD COLSPAN=\"2\"><B>" + pattern.getShort() + "</B></TD></TR>");
112                         pw.println("        <TR>");
113                         pw.println("          <TD COLSPAN=\"2\">" + pattern.getDetails() + "</TD>");
114                         pw.println("        </TR>");
115                         pw.println("      </TABLE>");
116                         pw.println("    </P>");
117                         pw.println("    <HR/>");
118                 }
119         }
120         
121         void writeHeader(PrintWriter pw)
122         {
123                 String title = trans(CfbBundle.CFB_REPORT);
124                 
125                 pw.println("<HTML>");
126                 pw.println("  <HEAD>");
127                 pw.println("    <META CHARSET=\"UTF-8\"/>");
128                 pw.println("    <TITLE>" + title + "</TITLE>");
129                 writeStyle(pw);
130                 pw.println("  </HEAD>");
131         }
132         
133         void writeSectionHeading(PrintWriter pw, String heading)
134         {
135                 pw.println("    <P CLASS=\"SectionHead\">");
136                 pw.println("      <TABLE WIDTH=\"100%\"><TR><TD>" + heading + "</TD></TR></TABLE>");
137                 pw.println("    </P>");
138         }
139         
140         void writeSummary(PrintWriter pw)
141         {
142                 final String SEP = ":&nbsp;&nbsp;";
143                 
144                 String earlierVersion = "";
145                 if (null != m_delta.getEarlier()) {
146                         earlierVersion = m_delta.getEarlier().constructVersionText(m_bundle);
147                 }
148                 
149                 writeSectionHeading(pw, trans(CfbBundle.CFB_REPORT));
150                 pw.println("    <P>");
151                 pw.println("      <TABLE>");
152                 pw.println("        <TR>");
153                 pw.println("          <TD CLASS=\"CategoryName\">" + trans(CfbBundle.NEW_VERSION) + SEP + "</TD>");
154                 pw.println("          <TD CLASS=\"CategoryValue\">" + m_delta.getLater().constructVersionText(m_bundle) + "</TD>");
155                 pw.println("        </TR>");
156                 pw.println("        <TR>");
157                 pw.println("          <TD CLASS=\"CategoryName\">" + trans(CfbBundle.OLD_VERSION) + SEP + "</TD>");
158                 pw.println("          <TD CLASS=\"CategoryValue\">" + earlierVersion + "</TD>");
159                 pw.println("        </TR>");
160                 pw.println("        <TR><TD>&nbsp;</TD></TR>");
161                 pw.println("        <TR>");
162                 pw.println("          <TD CLASS=\"CategoryName\">" + trans(CfbBundle.NEW_BUGS) + SEP + "</TD>");
163                 pw.println("          <TD CLASS=\"CategoryValue\">" + trans(CfbBundle.NUM_BUGS, m_delta.getNumNew()) + "</TD>");
164                 pw.println("        </TR>");
165                 pw.println("        <TR>");
166                 pw.println("          <TD CLASS=\"CategoryName\">" + trans(CfbBundle.FIXED_BUGS) + SEP + "</TD>");
167                 pw.println("          <TD CLASS=\"CategoryValue\">" + trans(CfbBundle.NUM_BUGS, m_delta.getNumFixed()) + "</TD>");
168                 pw.println("        </TR>");
169                 pw.println("        <TR>");
170                 pw.println("          <TD CLASS=\"CategoryName\">" + trans(CfbBundle.OLD_BUGS) + SEP + "</TD>");
171                 pw.println("          <TD CLASS=\"CategoryValue\">" + trans(CfbBundle.NUM_BUGS_OLD, m_delta.getNumCommon()) + "</TD>");
172                 pw.println("        </TR>");
173                 pw.println("      </TABLE>");
174                 pw.println("    </P>");
175         }
176         
177         void writeStyle(PrintWriter pw)
178         {
179                 pw.println("    <STYLE>");
180                 pw.println("                   body { background-color: #F0F0FF; }");
181             pw.println("    .CategoryName  { text-align: right; }");
182             pw.println("    .CategoryValue { text-align: left; }");
183                 pw.println("    .Loc           { font-family: monospace; }");
184             pw.println("    .SectionHead   td { background-color: #0000FF; color: #FFFFFF; font-size: 1.25em; font-weight: bold; }");
185                 pw.println("    </STYLE>");
186         }
187 }