source: josm/trunk/src/org/openstreetmap/josm/io/ValidatorErrorWriter.java@ 14397

Last change on this file since 14397 was 12699, checked in by Don-vip, 7 years ago

see #14704 - fix xml tag

File size: 6.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io;
3
4import java.io.BufferedWriter;
5import java.io.OutputStream;
6import java.io.OutputStreamWriter;
7import java.io.PrintWriter;
8import java.nio.charset.StandardCharsets;
9import java.util.ArrayList;
10import java.util.Collection;
11import java.util.Date;
12import java.util.HashMap;
13import java.util.List;
14import java.util.Map;
15import java.util.Map.Entry;
16import java.util.Set;
17import java.util.TreeSet;
18import java.util.stream.Collectors;
19
20import org.openstreetmap.josm.command.AddPrimitivesCommand;
21import org.openstreetmap.josm.command.ChangePropertyCommand;
22import org.openstreetmap.josm.command.ChangePropertyKeyCommand;
23import org.openstreetmap.josm.command.Command;
24import org.openstreetmap.josm.command.DeleteCommand;
25import org.openstreetmap.josm.data.coor.LatLon;
26import org.openstreetmap.josm.data.osm.OsmPrimitive;
27import org.openstreetmap.josm.data.validation.OsmValidator;
28import org.openstreetmap.josm.data.validation.Severity;
29import org.openstreetmap.josm.data.validation.Test;
30import org.openstreetmap.josm.data.validation.TestError;
31import org.openstreetmap.josm.tools.LanguageInfo;
32import org.openstreetmap.josm.tools.Logging;
33import org.openstreetmap.josm.tools.date.DateUtils;
34
35/**
36 * Class to write a collection of validator errors out to XML.
37 * The format is inspired by the
38 * <a href="https://wiki.openstreetmap.org/wiki/Osmose#Issues_file_format">Osmose API issues file format</a>
39 * @since 12667
40 */
41public class ValidatorErrorWriter extends XmlWriter {
42
43 /**
44 * Constructs a new {@code ValidatorErrorWriter} that will write to the given {@link PrintWriter}.
45 * @param out PrintWriter to write XML to
46 */
47 public ValidatorErrorWriter(PrintWriter out) {
48 super(out);
49 }
50
51 /**
52 * Constructs a new {@code ValidatorErrorWriter} that will write to a given {@link OutputStream}.
53 * @param out OutputStream to write XML to
54 */
55 public ValidatorErrorWriter(OutputStream out) {
56 super(new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8))));
57 }
58
59 /**
60 * Write validator errors to designated output target
61 * @param validationErrors Test error collection to write
62 */
63 public void write(Collection<TestError> validationErrors) {
64 Set<Test> analysers = validationErrors.stream().map(TestError::getTester).collect(Collectors.toCollection(TreeSet::new));
65 String timestamp = DateUtils.fromDate(new Date());
66
67 out.println("<?xml version='1.0' encoding='UTF-8'?>");
68 out.println("<analysers generator='JOSM' timestamp='"+timestamp+"'>");
69
70 OsmWriter osmWriter = OsmWriterFactory.createOsmWriter(out, true, OsmChangeBuilder.DEFAULT_API_VERSION);
71 String lang = LanguageInfo.getJOSMLocaleCode();
72
73 for (Test test : analysers) {
74 out.println(" <analyser timestamp='"+timestamp+"' name='"+XmlWriter.encode(test.getName())+"'>");
75 // Build map of test error classes for the current test
76 Map<ErrorClass, List<TestError>> map = new HashMap<>();
77 for (Entry<Severity, Map<String, Map<String, List<TestError>>>> e1 :
78 OsmValidator.getErrorsBySeverityMessageDescription(validationErrors, e -> e.getTester() == test).entrySet()) {
79 for (Entry<String, Map<String, List<TestError>>> e2 : e1.getValue().entrySet()) {
80 ErrorClass errorClass = new ErrorClass(e1.getKey(), e2.getKey());
81 List<TestError> list = map.get(errorClass);
82 if (list == null) {
83 list = new ArrayList<>();
84 map.put(errorClass, list);
85 }
86 e2.getValue().values().stream().forEach(list::addAll);
87 }
88 }
89 // Write classes
90 for (ErrorClass ec : map.keySet()) {
91 out.println(" <class id='"+ec.id+"' level='"+ec.severity.getLevel()+"'>");
92 out.println(" <classtext lang='"+XmlWriter.encode(lang)+"' title='"+XmlWriter.encode(ec.message)+"'/>");
93 out.println(" </class>");
94 }
95
96 // Write errors
97 for (Entry<ErrorClass, List<TestError>> entry : map.entrySet()) {
98 for (TestError error : entry.getValue()) {
99 LatLon ll = error.getPrimitives().iterator().next().getBBox().getCenter();
100 out.println(" <error class='"+entry.getKey().id+"'>");
101 out.print(" <location");
102 osmWriter.writeLatLon(ll);
103 out.println("/>");
104 for (OsmPrimitive p : error.getPrimitives()) {
105 p.accept(osmWriter);
106 }
107 out.println(" <text lang='"+XmlWriter.encode(lang)+"' value='"+XmlWriter.encode(error.getDescription())+"'/>");
108 if (error.isFixable()) {
109 out.println(" <fixes>");
110 Command fix = error.getFix();
111 if (fix instanceof AddPrimitivesCommand) {
112 Logging.info("TODO: {0}", fix);
113 } else if (fix instanceof DeleteCommand) {
114 Logging.info("TODO: {0}", fix);
115 } else if (fix instanceof ChangePropertyCommand) {
116 Logging.info("TODO: {0}", fix);
117 } else if (fix instanceof ChangePropertyKeyCommand) {
118 Logging.info("TODO: {0}", fix);
119 } else {
120 Logging.warn("Unsupported command type: {0}", fix);
121 }
122 out.println(" </fixes>");
123 }
124 out.println(" </error>");
125 }
126 }
127
128 out.println(" </analyser>");
129 }
130
131 out.println("</analysers>");
132 out.flush();
133 }
134
135 private static class ErrorClass {
136 static int idCounter;
137 final Severity severity;
138 final String message;
139 final int id;
140
141 ErrorClass(Severity severity, String message) {
142 this.severity = severity;
143 this.message = message;
144 this.id = ++idCounter;
145 }
146 }
147}
Note: See TracBrowser for help on using the repository browser.