1 /***
2 * Copyright 2009 Martin Vysny.
3 *
4 * This file is part of WebVM.
5 *
6 * WebVM is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * WebVM is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with WebVM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 package sk.baka.webvm.analyzer;
20
21 import java.io.Serializable;
22 import java.util.Collection;
23 import java.util.HashMap;
24 import java.util.Map;
25 import sk.baka.webvm.Problems;
26
27 /***
28 * Describes a potential problem.
29 * @author Martin Vysny
30 */
31 public final class ProblemReport implements Serializable {
32
33 private static final long serialVersionUID = 1L;
34 /***
35 * Checks if this really is a problem. true if this might be a serious problem, false if everything is OK or this is only a minor issue.
36 */
37 public final boolean isProblem;
38 /***
39 * description of the problem class, not null
40 */
41 public final String desc;
42 /***
43 * The problem 'class', not null.
44 */
45 public final String pclass;
46 /***
47 * The 'diagnosis' of the problem.
48 */
49 public final String diagnosis;
50
51 /***
52 * Creates new instance.
53 * @param isProblem true if this might be a serious problem, false if everything is OK or this is only a minor issue.
54 * @param diagnosis diagnosis of the problem, or something like OK if everything is okay. not null
55 * @param pclass the problem class, not null
56 * @param desc description of the problem class, not null
57 */
58 public ProblemReport(final boolean isProblem, final String pclass, final String diagnosis, final String desc) {
59 this.isProblem = isProblem;
60 this.pclass = pclass;
61 this.diagnosis = diagnosis;
62 this.desc = desc;
63 }
64 /***
65 * When this object was created.
66 */
67 public final long created = System.currentTimeMillis();
68
69 /***
70 * Checks if there is at least one real problem.
71 * @param problems the list of problems
72 * @return true if there is a problem, false otherwise.
73 */
74 public static boolean isProblem(final Collection<? extends ProblemReport> problems) {
75 for (final ProblemReport p : problems) {
76 if (p.isProblem) {
77 return true;
78 }
79 }
80 return false;
81 }
82
83 /***
84 * Formats the problem reports in the form of CLASS: DESC\nCLASS: DESC ...
85 * @param problems the problem reports to format.
86 * @return all problem reports.
87 * @param lineSeparator the new-line separator.
88 */
89 public static String toString(final Collection<? extends ProblemReport> problems, final String lineSeparator) {
90 final StringBuilder sb = new StringBuilder();
91 boolean first = true;
92 for (final ProblemReport r : problems) {
93 if (first) {
94 first = false;
95 } else {
96 sb.append(lineSeparator);
97 }
98 sb.append(r.toString());
99 }
100 return sb.toString();
101 }
102
103 /***
104 * Formats the problem reports in the form of a HTML table.
105 * @param problems the problem reports to format.
106 * @return all problem reports.
107 */
108 public static String toHtml(final Collection<? extends ProblemReport> problems) {
109 final StringBuilder sb = new StringBuilder();
110 sb.append("<table border=\"1\"><thead><tr><th>Problem type</th><th>Status</th><th>Diagnosis</th></tr></thead>\n");
111 for (final ProblemReport r : problems) {
112 sb.append("<tr><td>");
113 sb.append(r.pclass);
114 sb.append("</td><td bgcolor=\"#");
115 sb.append(r.isProblem ? Problems.LIGHT_RED : Problems.DARK_GREEN);
116 sb.append("\">");
117 sb.append(r.isProblem ? "WARN" : "OK");
118 sb.append("</td><td><pre>");
119 sb.append(r.diagnosis);
120 sb.append("</pre></td></tr>\n");
121 }
122 return sb.toString();
123 }
124
125 /***
126 * XML-escapes given text.
127 * @param text the text to escape
128 * @return text with &amp;, &lt; etc.
129 */
130 public static final String escape(final String text) {
131 String result = text.replace("&", "&");
132 result = result.replace("<", "<");
133 result = result.replace(">", ">");
134 return result;
135 }
136
137 @Override
138 public boolean equals(Object obj) {
139 if (obj == null) {
140 return false;
141 }
142 if (getClass() != obj.getClass()) {
143 return false;
144 }
145 final ProblemReport other = (ProblemReport) obj;
146 if (this.isProblem != other.isProblem) {
147 return false;
148 }
149 if (!this.pclass.equals(other.pclass)) {
150 return false;
151 }
152 if ((this.diagnosis == null) ? (other.diagnosis != null) : !this.diagnosis.equals(other.diagnosis)) {
153 return false;
154 }
155 return true;
156 }
157
158 @Override
159 public int hashCode() {
160 int hash = 7;
161 hash = 59 * hash + (this.isProblem ? 1 : 0);
162 hash = 59 * hash + this.pclass.hashCode();
163 hash = 59 * hash + (this.diagnosis != null ? this.diagnosis.hashCode() : 0);
164 return hash;
165 }
166
167 @Override
168 public String toString() {
169 return (isProblem ? "WARN" : "OK ") + ": " + pclass + ": " + diagnosis;
170 }
171
172 private static Map<String, ProblemReport> toMap(final Iterable<? extends ProblemReport> reports, final boolean filterProblems) {
173 final Map<String, ProblemReport> result = new HashMap<String, ProblemReport>();
174 for (final ProblemReport r : reports) {
175 if (filterProblems && !r.isProblem) {
176 continue;
177 }
178 result.put(r.pclass, r);
179 }
180 return result;
181 }
182
183 /***
184 * Checks if two problem reports are equal. Reports are equal when same classes are problematic and all problematic reports share the same description.
185 * @param reports1 first report set.
186 * @param reports2 second report set.
187 * @return true if report sets are equal, false otherwise.
188 */
189 public static boolean equals(final Collection<? extends ProblemReport> reports1, final Collection<? extends ProblemReport> reports2) {
190 final Map<String, ProblemReport> r1 = toMap(reports1, true);
191 final Map<String, ProblemReport> r2 = toMap(reports2, true);
192 if (!r1.keySet().equals(r2.keySet())) {
193 return false;
194 }
195 for (final String pclass : r1.keySet()) {
196 if (!r1.get(pclass).diagnosis.equals(r2.get(pclass).diagnosis)) {
197 return false;
198 }
199 }
200 return true;
201 }
202 }