source: josm/trunk/src/org/openstreetmap/josm/actions/ValidateAction.java@ 14599

Last change on this file since 14599 was 14599, checked in by GerdP, 5 years ago

fix #17035: Validator: Improve progress monitor (17035-progress-monitor-v2.patch)

  • Each test can enable a counter that shows "{0} of {1} elements done" for the tested OSM elements. The counter is increased in steps of 1000. For now this is only enabled for MapCSSTagChecker.
  • Don't show the name of the last executed test while postprocessing the results of all tests.
  • Property svn:eol-style set to native
File size: 7.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.awt.event.KeyEvent;
8import java.io.IOException;
9import java.util.ArrayList;
10import java.util.Collection;
11import java.util.List;
12import java.util.Optional;
13
14import org.openstreetmap.josm.data.osm.OsmPrimitive;
15import org.openstreetmap.josm.data.preferences.sources.ValidatorPrefHelper;
16import org.openstreetmap.josm.data.validation.OsmValidator;
17import org.openstreetmap.josm.data.validation.Test;
18import org.openstreetmap.josm.data.validation.TestError;
19import org.openstreetmap.josm.data.validation.util.AggregatePrimitivesVisitor;
20import org.openstreetmap.josm.gui.MainApplication;
21import org.openstreetmap.josm.gui.MapFrame;
22import org.openstreetmap.josm.gui.PleaseWaitRunnable;
23import org.openstreetmap.josm.gui.layer.ValidatorLayer;
24import org.openstreetmap.josm.gui.util.GuiHelper;
25import org.openstreetmap.josm.io.OsmTransferException;
26import org.openstreetmap.josm.tools.Shortcut;
27import org.xml.sax.SAXException;
28
29/**
30 * The action that does the validate thing.
31 * <p>
32 * This action iterates through all active tests and give them the data, so that
33 * each one can test it.
34 *
35 * @author frsantos
36 */
37public class ValidateAction extends JosmAction {
38
39 /** Last selection used to validate */
40 private transient Collection<OsmPrimitive> lastSelection;
41
42 /**
43 * Constructor
44 */
45 public ValidateAction() {
46 super(tr("Validation"), "dialogs/validator", tr("Performs the data validation"),
47 Shortcut.registerShortcut("tools:validate", tr("Tool: {0}", tr("Validation")),
48 KeyEvent.VK_V, Shortcut.SHIFT), true);
49 }
50
51 @Override
52 public void actionPerformed(ActionEvent ev) {
53 doValidate(true);
54 }
55
56 /**
57 * Does the validation.
58 * <p>
59 * If getSelectedItems is true, the selected items (or all items, if no one
60 * is selected) are validated. If it is false, last selected items are revalidated
61 *
62 * @param getSelectedItems If selected or last selected items must be validated
63 */
64 public void doValidate(boolean getSelectedItems) {
65 MapFrame map = MainApplication.getMap();
66 if (map == null || !map.isVisible())
67 return;
68
69 OsmValidator.initializeTests();
70 OsmValidator.initializeErrorLayer();
71
72 Collection<Test> tests = OsmValidator.getEnabledTests(false);
73 if (tests.isEmpty())
74 return;
75
76 Collection<OsmPrimitive> selection;
77 if (getSelectedItems) {
78 selection = getLayerManager().getActiveDataSet().getAllSelected();
79 if (selection.isEmpty()) {
80 selection = getLayerManager().getActiveDataSet().allNonDeletedPrimitives();
81 lastSelection = null;
82 } else {
83 AggregatePrimitivesVisitor v = new AggregatePrimitivesVisitor();
84 selection = v.visit(selection);
85 lastSelection = selection;
86 }
87 } else {
88 selection = Optional.ofNullable(lastSelection).orElseGet(
89 () -> getLayerManager().getActiveDataSet().allNonDeletedPrimitives());
90 }
91
92 MainApplication.worker.submit(new ValidationTask(tests, selection, lastSelection));
93 }
94
95 @Override
96 public void updateEnabledState() {
97 setEnabled(getLayerManager().getActiveDataSet() != null);
98 }
99
100 @Override
101 public void destroy() {
102 // Hack - this action should stay forever because it could be added to toolbar
103 // Do not call super.destroy() here
104 lastSelection = null;
105 }
106
107 /**
108 * Asynchronous task for running a collection of tests against a collection of primitives
109 */
110 static class ValidationTask extends PleaseWaitRunnable {
111 private Collection<Test> tests;
112 private final Collection<OsmPrimitive> validatedPrimitives;
113 private final Collection<OsmPrimitive> formerValidatedPrimitives;
114 private boolean canceled;
115 private List<TestError> errors;
116
117 /**
118 * Constructs a new {@code ValidationTask}
119 * @param tests the tests to run
120 * @param validatedPrimitives the collection of primitives to validate.
121 * @param formerValidatedPrimitives the last collection of primitives being validates. May be null.
122 */
123 ValidationTask(Collection<Test> tests, Collection<OsmPrimitive> validatedPrimitives,
124 Collection<OsmPrimitive> formerValidatedPrimitives) {
125 super(tr("Validating"), false /*don't ignore exceptions */);
126 this.validatedPrimitives = validatedPrimitives;
127 this.formerValidatedPrimitives = formerValidatedPrimitives;
128 this.tests = tests;
129 }
130
131 @Override
132 protected void cancel() {
133 this.canceled = true;
134 }
135
136 @Override
137 protected void finish() {
138 if (canceled) return;
139
140 // update GUI on Swing EDT
141 //
142 GuiHelper.runInEDT(() -> {
143 MapFrame map = MainApplication.getMap();
144 map.validatorDialog.tree.setErrors(errors);
145 map.validatorDialog.unfurlDialog();
146 //FIXME: nicer way to find / invalidate the corresponding error layer
147 MainApplication.getLayerManager().getLayersOfType(ValidatorLayer.class).forEach(ValidatorLayer::invalidate);
148 });
149 }
150
151 @Override
152 protected void realRun() throws SAXException, IOException,
153 OsmTransferException {
154 if (tests == null || tests.isEmpty())
155 return;
156 errors = new ArrayList<>(200);
157 getProgressMonitor().setTicksCount(tests.size() * validatedPrimitives.size());
158 int testCounter = 0;
159 for (Test test : tests) {
160 if (canceled)
161 return;
162 testCounter++;
163 getProgressMonitor().setCustomText(tr("Test {0}/{1}: Starting {2}", testCounter, tests.size(), test.getName()));
164 test.setPartialSelection(formerValidatedPrimitives != null);
165 test.startTest(getProgressMonitor().createSubTaskMonitor(validatedPrimitives.size(), false));
166 test.visit(validatedPrimitives);
167 test.endTest();
168 errors.addAll(test.getErrors());
169 test.clear();
170 }
171 tests = null;
172 if (ValidatorPrefHelper.PREF_USE_IGNORE.get()) {
173 getProgressMonitor().setCustomText("");
174 getProgressMonitor().subTask(tr("Updating ignored errors ..."));
175 for (TestError error : errors) {
176 if (canceled) return;
177 List<String> s = new ArrayList<>();
178 s.add(error.getIgnoreState());
179 s.add(error.getIgnoreGroup());
180 s.add(error.getIgnoreSubGroup());
181 for (String state : s) {
182 if (state != null && OsmValidator.hasIgnoredError(state)) {
183 error.setIgnored(true);
184 }
185 }
186 }
187 }
188 }
189 }
190}
Note: See TracBrowser for help on using the repository browser.