source: josm/trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java@ 6563

Last change on this file since 6563 was 6563, checked in by simon04, 10 years ago

fix #9487 - validator: remove useless NodesWithSameName test

  • Property svn:eol-style set to native
File size: 12.3 KB
Line 
1// License: GPL. See LICENSE file for details.
2package org.openstreetmap.josm.data.validation;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.BufferedReader;
7import java.io.File;
8import java.io.FileNotFoundException;
9import java.io.FileReader;
10import java.io.FileWriter;
11import java.io.IOException;
12import java.io.PrintWriter;
13import java.util.ArrayList;
14import java.util.Arrays;
15import java.util.Collection;
16import java.util.HashMap;
17import java.util.Map;
18import java.util.TreeSet;
19import java.util.regex.Matcher;
20import java.util.regex.Pattern;
21
22import javax.swing.JOptionPane;
23
24import org.openstreetmap.josm.Main;
25import org.openstreetmap.josm.actions.ValidateAction;
26import org.openstreetmap.josm.data.validation.tests.Addresses;
27import org.openstreetmap.josm.data.validation.tests.BarriersEntrances;
28import org.openstreetmap.josm.data.validation.tests.BuildingInBuilding;
29import org.openstreetmap.josm.data.validation.tests.Coastlines;
30import org.openstreetmap.josm.data.validation.tests.CrossingWays;
31import org.openstreetmap.josm.data.validation.tests.DuplicateNode;
32import org.openstreetmap.josm.data.validation.tests.DuplicateRelation;
33import org.openstreetmap.josm.data.validation.tests.DuplicateWay;
34import org.openstreetmap.josm.data.validation.tests.DuplicatedWayNodes;
35import org.openstreetmap.josm.data.validation.tests.Highways;
36import org.openstreetmap.josm.data.validation.tests.MapCSSTagChecker;
37import org.openstreetmap.josm.data.validation.tests.MultipolygonTest;
38import org.openstreetmap.josm.data.validation.tests.NameMismatch;
39import org.openstreetmap.josm.data.validation.tests.NodesDuplicatingWayTags;
40import org.openstreetmap.josm.data.validation.tests.OpeningHourTest;
41import org.openstreetmap.josm.data.validation.tests.OverlappingAreas;
42import org.openstreetmap.josm.data.validation.tests.OverlappingWays;
43import org.openstreetmap.josm.data.validation.tests.PowerLines;
44import org.openstreetmap.josm.data.validation.tests.RelationChecker;
45import org.openstreetmap.josm.data.validation.tests.SelfIntersectingWay;
46import org.openstreetmap.josm.data.validation.tests.SimilarNamedWays;
47import org.openstreetmap.josm.data.validation.tests.TagChecker;
48import org.openstreetmap.josm.data.validation.tests.TurnrestrictionTest;
49import org.openstreetmap.josm.data.validation.tests.UnclosedWays;
50import org.openstreetmap.josm.data.validation.tests.UnconnectedWays;
51import org.openstreetmap.josm.data.validation.tests.UntaggedNode;
52import org.openstreetmap.josm.data.validation.tests.UntaggedWay;
53import org.openstreetmap.josm.data.validation.tests.WayConnectedToArea;
54import org.openstreetmap.josm.data.validation.tests.WronglyOrderedWays;
55import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
56import org.openstreetmap.josm.gui.layer.Layer;
57import org.openstreetmap.josm.gui.layer.OsmDataLayer;
58import org.openstreetmap.josm.gui.layer.ValidatorLayer;
59import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
60import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
61import org.openstreetmap.josm.tools.Utils;
62
63/**
64 * A OSM data validator.
65 *
66 * @author Francisco R. Santos <frsantos@gmail.com>
67 */
68public class OsmValidator implements LayerChangeListener {
69
70 public static ValidatorLayer errorLayer = null;
71
72 /** The validate action */
73 public ValidateAction validateAction = new ValidateAction();
74
75 /** Grid detail, multiplier of east,north values for valuable cell sizing */
76 public static double griddetail;
77
78 public static final Collection<String> ignoredErrors = new TreeSet<String>();
79
80 /**
81 * All available tests
82 * TODO: is there any way to find out automatically all available tests?
83 */
84 @SuppressWarnings("unchecked")
85 private static final Class<Test>[] allAvailableTests = new Class[] {
86 DuplicateNode.class, // ID 1 .. 99
87 OverlappingWays.class, // ID 101 .. 199
88 UntaggedNode.class, // ID 201 .. 299
89 UntaggedWay.class, // ID 301 .. 399
90 SelfIntersectingWay.class, // ID 401 .. 499
91 DuplicatedWayNodes.class, // ID 501 .. 599
92 CrossingWays.class, // ID 601 .. 699
93 SimilarNamedWays.class, // ID 701 .. 799
94 Coastlines.class, // ID 901 .. 999
95 WronglyOrderedWays.class, // ID 1001 .. 1099
96 UnclosedWays.class, // ID 1101 .. 1199
97 TagChecker.class, // ID 1201 .. 1299
98 UnconnectedWays.UnconnectedHighways.class, // ID 1301 .. 1399
99 UnconnectedWays.UnconnectedRailways.class, // ID 1301 .. 1399
100 UnconnectedWays.UnconnectedWaterways.class, // ID 1301 .. 1399
101 UnconnectedWays.UnconnectedNaturalOrLanduse.class, // ID 1301 .. 1399
102 UnconnectedWays.UnconnectedPower.class, // ID 1301 .. 1399
103 DuplicateWay.class, // ID 1401 .. 1499
104 NameMismatch.class, // ID 1501 .. 1599
105 MultipolygonTest.class, // ID 1601 .. 1699
106 RelationChecker.class, // ID 1701 .. 1799
107 TurnrestrictionTest.class, // ID 1801 .. 1899
108 DuplicateRelation.class, // ID 1901 .. 1999
109 BuildingInBuilding.class, // ID 2001 .. 2099
110 OverlappingAreas.class, // ID 2201 .. 2299
111 WayConnectedToArea.class, // ID 2301 .. 2399
112 NodesDuplicatingWayTags.class, // ID 2401 .. 2499
113 PowerLines.class, // ID 2501 .. 2599
114 Addresses.class, // ID 2601 .. 2699
115 Highways.class, // ID 2701 .. 2799
116 BarriersEntrances.class, // ID 2801 .. 2899
117 OpeningHourTest.class, // 2901 .. 2999
118 MapCSSTagChecker.class, // 3000 .. 3099
119 };
120
121 private static Map<String, Test> allTestsMap;
122 static {
123 allTestsMap = new HashMap<String, Test>();
124 for (Class<Test> testClass : allAvailableTests) {
125 try {
126 allTestsMap.put(testClass.getSimpleName(), testClass.newInstance());
127 } catch (Exception e) {
128 Main.error(e);
129 continue;
130 }
131 }
132 }
133
134 /**
135 * Constructs a new {@code OsmValidator}.
136 */
137 public OsmValidator() {
138 checkValidatorDir();
139 initializeGridDetail();
140 initializeTests(getTests());
141 loadIgnoredErrors(); //FIXME: load only when needed
142 }
143
144 /**
145 * Returns the plugin's directory of the plugin
146 *
147 * @return The directory of the plugin
148 */
149 public static String getValidatorDir() {
150 return Main.pref.getPreferencesDir() + "validator/";
151 }
152
153 /**
154 * Check if plugin directory exists (store ignored errors file)
155 */
156 private void checkValidatorDir() {
157 try {
158 File pathDir = new File(getValidatorDir());
159 if (!pathDir.exists()) {
160 pathDir.mkdirs();
161 }
162 } catch (Exception e){
163 e.printStackTrace();
164 }
165 }
166
167 private void loadIgnoredErrors() {
168 ignoredErrors.clear();
169 if (Main.pref.getBoolean(ValidatorPreference.PREF_USE_IGNORE, true)) {
170 BufferedReader in = null;
171 try {
172 in = new BufferedReader(new FileReader(getValidatorDir() + "ignorederrors"));
173 for (String line = in.readLine(); line != null; line = in.readLine()) {
174 ignoredErrors.add(line);
175 }
176 } catch (final FileNotFoundException e) {
177 // Ignore
178 } catch (final IOException e) {
179 e.printStackTrace();
180 } finally {
181 Utils.close(in);
182 }
183 }
184 }
185
186 public static void addIgnoredError(String s) {
187 ignoredErrors.add(s);
188 }
189
190 public static boolean hasIgnoredError(String s) {
191 return ignoredErrors.contains(s);
192 }
193
194 public static void saveIgnoredErrors() {
195 PrintWriter out = null;
196 try {
197 out = new PrintWriter(new FileWriter(getValidatorDir() + "ignorederrors"), false);
198 for (String e : ignoredErrors) {
199 out.println(e);
200 }
201 } catch (IOException e) {
202 e.printStackTrace();
203 } finally {
204 Utils.close(out);
205 }
206 }
207
208 public static void initializeErrorLayer() {
209 if (!Main.pref.getBoolean(ValidatorPreference.PREF_LAYER, true))
210 return;
211 if (errorLayer == null) {
212 errorLayer = new ValidatorLayer();
213 Main.main.addLayer(errorLayer);
214 }
215 }
216
217 /**
218 * Gets a map from simple names to all tests.
219 * @return A map of all tests, indexed by the simple name of their Java class
220 */
221 public static Map<String, Test> getAllTestsMap() {
222 applyPrefs(allTestsMap, false);
223 applyPrefs(allTestsMap, true);
224 return new HashMap<String, Test>(allTestsMap);
225 }
226
227 private static void applyPrefs(Map<String, Test> tests, boolean beforeUpload) {
228 Pattern regexp = Pattern.compile("(\\w+)=(true|false),?");
229 Matcher m = regexp.matcher(Main.pref.get(beforeUpload ? ValidatorPreference.PREF_TESTS_BEFORE_UPLOAD
230 : ValidatorPreference.PREF_TESTS));
231 int pos = 0;
232 while (m.find(pos)) {
233 String testName = m.group(1);
234 Test test = tests.get(testName);
235 if (test != null) {
236 boolean enabled = Boolean.valueOf(m.group(2));
237 if (beforeUpload) {
238 test.testBeforeUpload = enabled;
239 } else {
240 test.enabled = enabled;
241 }
242 }
243 pos = m.end();
244 }
245 }
246
247 public static Collection<Test> getTests() {
248 return getAllTestsMap().values();
249 }
250
251 public static Collection<Test> getEnabledTests(boolean beforeUpload) {
252 Collection<Test> enabledTests = getTests();
253 for (Test t : new ArrayList<Test>(enabledTests)) {
254 if (beforeUpload ? t.testBeforeUpload : t.enabled) {
255 continue;
256 }
257 enabledTests.remove(t);
258 }
259 return enabledTests;
260 }
261
262 /**
263 * Gets the list of all available test classes
264 *
265 * @return An array of the test classes
266 */
267 public static Class<Test>[] getAllAvailableTests() {
268 return Arrays.copyOf(allAvailableTests, allAvailableTests.length);
269 }
270
271 /**
272 * Initialize grid details based on current projection system. Values based on
273 * the original value fixed for EPSG:4326 (10000) using heuristics (that is, test&error
274 * until most bugs were discovered while keeping the processing time reasonable)
275 */
276 public void initializeGridDetail() {
277 String code = Main.getProjection().toCode();
278 if (Arrays.asList(ProjectionPreference.wgs84.allCodes()).contains(code)) {
279 OsmValidator.griddetail = 10000;
280 } else if (Arrays.asList(ProjectionPreference.mercator.allCodes()).contains(code)) {
281 OsmValidator.griddetail = 0.01;
282 } else if (Arrays.asList(ProjectionPreference.lambert.allCodes()).contains(code)) {
283 OsmValidator.griddetail = 0.1;
284 } else {
285 OsmValidator.griddetail = 1.0;
286 }
287 }
288
289 /**
290 * Initializes all tests
291 * @param allTests The tests to initialize
292 */
293 public static void initializeTests(Collection<Test> allTests) {
294 for (Test test : allTests) {
295 try {
296 if (test.enabled) {
297 test.initialize();
298 }
299 } catch (Exception e) {
300 e.printStackTrace();
301 JOptionPane.showMessageDialog(Main.parent,
302 tr("Error initializing test {0}:\n {1}", test.getClass()
303 .getSimpleName(), e),
304 tr("Error"),
305 JOptionPane.ERROR_MESSAGE);
306 }
307 }
308 }
309
310 /* -------------------------------------------------------------------------- */
311 /* interface LayerChangeListener */
312 /* -------------------------------------------------------------------------- */
313 @Override
314 public void activeLayerChange(Layer oldLayer, Layer newLayer) {
315 }
316
317 @Override
318 public void layerAdded(Layer newLayer) {
319 }
320
321 @Override
322 public void layerRemoved(Layer oldLayer) {
323 if (oldLayer == errorLayer) {
324 errorLayer = null;
325 return;
326 }
327 if (Main.map.mapView.getLayersOfType(OsmDataLayer.class).isEmpty()) {
328 if (errorLayer != null) {
329 Main.main.removeLayer(errorLayer);
330 }
331 }
332 }
333}
Note: See TracBrowser for help on using the repository browser.