blob: 8c3f68b4d2d836fe309d7955f2c281c0e27bea48 [file] [log] [blame]
Stuart McCullochf3173222012-06-07 21:57:32 +00001package aQute.libg.reporter;
2
3import java.lang.reflect.*;
4import java.util.*;
5import java.util.regex.*;
6
7import aQute.libg.generics.*;
Stuart McCulloch1a890552012-06-29 19:23:09 +00008import aQute.service.reporter.*;
Stuart McCullochf3173222012-06-07 21:57:32 +00009
10/**
11 * Mainly used for testing where reporters are needed.
Stuart McCullochf3173222012-06-07 21:57:32 +000012 */
Stuart McCulloch42151ee2012-07-16 13:43:38 +000013public class ReporterAdapter implements Reporter, Report, Runnable {
Stuart McCullochf3173222012-06-07 21:57:32 +000014 final List<String> errors = new ArrayList<String>();
15 final List<String> warnings = new ArrayList<String>();
Stuart McCulloch1a890552012-06-29 19:23:09 +000016 final List<LocationImpl> locations = new ArrayList<LocationImpl>();
17
18 static class LocationImpl extends Location implements SetLocation {
19
20
21
22 public LocationImpl(String e) {
23 // TODO Auto-generated constructor stub
24 }
25
26 public SetLocation file(String file) {
27 this.file = file;
28 return this;
29 }
30
31 public SetLocation header(String header) {
32 this.header = header;
33 return this;
34 }
35
36 public SetLocation context(String context) {
37 this.context = context;
38 return this;
39 }
40
41 public SetLocation method(String methodName) {
42 this.methodName = methodName;
43 return this;
44 }
45
46 public SetLocation line(int line) {
47 this.line = line;
48 return this;
49 }
50
51 public SetLocation reference(String reference) {
52 this.reference = reference;
53 return this;
54 }
55
56 }
57
Stuart McCullochf3173222012-06-07 21:57:32 +000058 final Formatter out;
59 boolean trace;
60 boolean pedantic;
61 boolean exceptions;
Stuart McCulloch1a890552012-06-29 19:23:09 +000062
Stuart McCullochf3173222012-06-07 21:57:32 +000063 /**
64 * @return the exceptions
65 */
66 public boolean isExceptions() {
67 return exceptions;
68 }
69
70 /**
71 * @param exceptions
72 * the exceptions to set
73 */
74 public void setExceptions(boolean exceptions) {
75 this.exceptions = exceptions;
76 }
77
78 /**
79 * @return the out
80 */
81 public Formatter getOut() {
82 return out;
83 }
84
85 /**
86 * @return the trace
87 */
88 public boolean isTrace() {
89 return trace;
90 }
91
92 /**
93 * @param pedantic
94 * the pedantic to set
95 */
96 public void setPedantic(boolean pedantic) {
97 this.pedantic = pedantic;
98 }
99
100 public ReporterAdapter() {
101 out = null;
102 }
103
104 public ReporterAdapter(Appendable app) {
105 out = new Formatter(app);
106 }
107
Stuart McCulloch1a890552012-06-29 19:23:09 +0000108 public SetLocation error(String s, Object... args) {
Stuart McCullochf3173222012-06-07 21:57:32 +0000109 String e = String.format(s, args);
110 errors.add(e);
111 trace("ERROR: %s", e);
Stuart McCulloch1a890552012-06-29 19:23:09 +0000112 return location(e);
Stuart McCullochf3173222012-06-07 21:57:32 +0000113 }
114
Stuart McCulloch1a890552012-06-29 19:23:09 +0000115 public SetLocation exception(Throwable t, String s, Object... args) {
Stuart McCulloch99fd9a72012-07-24 21:37:47 +0000116 StackTraceElement[] stackTrace = t.getStackTrace();
117 String method = stackTrace[0].getMethodName();
118 String cname = stackTrace[0].getClassName();
119 String e = String.format("["+shorten(cname) +"."+method+"] " +s, args);
Stuart McCullochf3173222012-06-07 21:57:32 +0000120 errors.add(e);
121 trace("ERROR: %s", e);
122 if (isExceptions() || isTrace())
Stuart McCulloch4482c702012-06-15 13:27:53 +0000123 if (t instanceof InvocationTargetException)
Stuart McCullochf3173222012-06-07 21:57:32 +0000124 t.getCause().printStackTrace(System.err);
125 else
126 t.printStackTrace(System.err);
Stuart McCulloch1a890552012-06-29 19:23:09 +0000127 return location(e);
Stuart McCullochf3173222012-06-07 21:57:32 +0000128 }
129
Stuart McCulloch99fd9a72012-07-24 21:37:47 +0000130 private String shorten(String cname) {
131 int index = cname.lastIndexOf('$');
132 if ( index < 0)
133 index = cname.lastIndexOf('.');
134
135 return cname.substring(index+1);
136 }
137
Stuart McCulloch1a890552012-06-29 19:23:09 +0000138 public SetLocation warning(String s, Object... args) {
Stuart McCullochf3173222012-06-07 21:57:32 +0000139 String e = String.format(s, args);
140 warnings.add(e);
141 trace("warning: %s", e);
Stuart McCulloch1a890552012-06-29 19:23:09 +0000142 return location(e);
Stuart McCullochf3173222012-06-07 21:57:32 +0000143 }
144
Stuart McCulloch1a890552012-06-29 19:23:09 +0000145 private SetLocation location(String e) {
146 LocationImpl loc = new LocationImpl(e);
147 locations.add( loc );
148 return loc;
149 }
150
151 public void progress(float progress, String s, Object... args) {
Stuart McCullochf3173222012-06-07 21:57:32 +0000152 if (out != null) {
153 out.format(s, args);
Stuart McCulloch54229442012-07-12 22:12:58 +0000154 if (!s.endsWith(String.format("%n")))
155 out.format("%n");
Stuart McCullochf3173222012-06-07 21:57:32 +0000156 }
157 }
158
159 public void trace(String s, Object... args) {
160 if (trace && out != null) {
Stuart McCulloch54229442012-07-12 22:12:58 +0000161 out.format("# " + s + "%n", args);
Stuart McCullochf3173222012-06-07 21:57:32 +0000162 out.flush();
163 }
164 }
165
166 public List<String> getWarnings() {
167 return warnings;
168 }
169
170 public List<String> getErrors() {
171 return errors;
172 }
173
174 public boolean isPedantic() {
175 return false;
176 }
177
178 public void setTrace(boolean b) {
179 this.trace = b;
180 }
181
182 public boolean isOk() {
183 return errors.isEmpty();
184 }
185
186 public boolean isPerfect() {
187 return isOk() && warnings.isEmpty();
188 }
189
190 public boolean check(String... pattern) {
191 Set<String> missed = Create.set();
192
193 if (pattern != null) {
194 for (String p : pattern) {
195 boolean match = false;
196 Pattern pat = Pattern.compile(p);
197 for (Iterator<String> i = errors.iterator(); i.hasNext();) {
198 if (pat.matcher(i.next()).find()) {
199 i.remove();
200 match = true;
201 }
202 }
203 for (Iterator<String> i = warnings.iterator(); i.hasNext();) {
204 if (pat.matcher(i.next()).find()) {
205 i.remove();
206 match = true;
207 }
208 }
209 if (!match)
210 missed.add(p);
211
212 }
213 }
214 if (missed.isEmpty() && isPerfect())
215 return true;
216
217 if (!missed.isEmpty())
Stuart McCulloch42151ee2012-07-16 13:43:38 +0000218 System.err.println("Missed the following patterns in the warnings or errors: " + missed);
Stuart McCullochf3173222012-06-07 21:57:32 +0000219
Stuart McCulloch42151ee2012-07-16 13:43:38 +0000220 report(System.err);
Stuart McCullochf3173222012-06-07 21:57:32 +0000221 return false;
222 }
223
224 /**
225 * Report the errors and warnings
226 */
227
228 public void report(Appendable out) {
229 Formatter f = new Formatter(out);
230 report("Error", getErrors(), f);
231 report("Warning", getWarnings(), f);
232 f.flush();
233 }
234
235 void report(String title, Collection<String> list, Formatter f) {
236 if (list.isEmpty())
237 return;
Stuart McCulloch54229442012-07-12 22:12:58 +0000238 f.format(title + (list.size() > 1 ? "s" : "") + "%n");
Stuart McCulloch4482c702012-06-15 13:27:53 +0000239 int n = 0;
Stuart McCullochf3173222012-06-07 21:57:32 +0000240 for (String s : list) {
Stuart McCulloch54229442012-07-12 22:12:58 +0000241 f.format("%3s. %s%n", n++, s);
Stuart McCullochf3173222012-06-07 21:57:32 +0000242 }
243 }
244
Stuart McCulloch1a890552012-06-29 19:23:09 +0000245 public boolean getInfo(Report other) {
246 return getInfo(other,null);
247 }
248 public boolean getInfo(Report other, String prefix) {
Stuart McCulloch2a0afd62012-09-06 18:28:06 +0000249 addErrors(prefix, other.getErrors());
250 addWarnings(prefix, other.getWarnings());
251 return other.isOk();
Stuart McCulloch1a890552012-06-29 19:23:09 +0000252 }
253
254 public Location getLocation(String msg) {
255 for ( LocationImpl loc : locations ) {
256 if ((loc.message != null) && loc.message.equals(msg))
257 return loc;
258 }
259 return null;
260 }
261
Stuart McCulloch42151ee2012-07-16 13:43:38 +0000262 /**
263 * Handy routine that can be extended by subclasses
264 * so they can run inside the context
265 */
266 public void run() {
267 throw new UnsupportedOperationException("Must be implemented by subclass");
268 }
269
270 /**
271 * Return a messages object bound to this adapter
272 */
273
274 public <T> T getMessages(Class<T> c) {
275 return ReporterMessages.base(this, c);
276 }
Stuart McCulloch2a0afd62012-09-06 18:28:06 +0000277
278 /**
279 * Add a number of errors
280 */
281
282 public void addErrors( String prefix, Collection<String> errors) {
283 if ( prefix == null)
284 prefix = "";
285 else
286 prefix = prefix + ": ";
287 for ( String s: errors) {
288 this.errors.add( prefix + s);
289 }
290 }
291 /**
292 * Add a number of warnings
293 */
294
295 public void addWarnings( String prefix, Collection<String> warnings) {
296 if ( prefix == null)
297 prefix = "";
298 else
299 prefix = prefix + ": ";
300 for ( String s: warnings) {
301 this.warnings.add( prefix + s);
302 }
303 }
Stuart McCullochf3173222012-06-07 21:57:32 +0000304}