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

Last change on this file since 3923 was 3923, checked in by bastiK, 13 years ago

fixed #6007 - runs out of memory on validater cross ways check (TODO: initializeGridDetail hack needs proper implementation)

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