Ticket #17268: clear_ignored_errors_v25.patch
File clear_ignored_errors_v25.patch, 26.9 KB (added by , 6 years ago) |
---|
-
src/org/openstreetmap/josm/data/preferences/sources/ValidatorPrefHelper.java
44 44 /** The preferences for ignored severity other */ 45 45 public static final BooleanProperty PREF_OTHER = new BooleanProperty(PREFIX + ".other", false); 46 46 47 /** The preferences key for the ignorelist */ 48 public static final String PREF_IGNORELIST = PREFIX + ".ignorelist"; 49 50 /** The preferences key for the ignorelist backup */ 51 public static final String PREF_IGNORELIST_BACKUP = PREFIX + ".ignorelist.bak"; 52 53 /** The preferences key for whether or not the ignorelist backup should be cleared on start */ 54 public static final BooleanProperty PREF_IGNORELIST_KEEP_BACKUP = new BooleanProperty(PREFIX + ".ignorelist.bak.keep", false); 55 47 56 /** 48 57 * The preferences key for enabling the permanent filtering 49 58 * of the displayed errors in the tree regarding the current selection -
src/org/openstreetmap/josm/data/validation/OsmValidator.java
7 7 import java.io.File; 8 8 import java.io.FileNotFoundException; 9 9 import java.io.IOException; 10 import java.io.PrintWriter;11 10 import java.nio.charset.StandardCharsets; 12 11 import java.nio.file.Files; 13 12 import java.nio.file.Path; … … 17 16 import java.util.Collection; 18 17 import java.util.Collections; 19 18 import java.util.EnumMap; 19 import java.util.Enumeration; 20 20 import java.util.HashMap; 21 import java.util.Iterator; 21 22 import java.util.List; 22 23 import java.util.Map; 24 import java.util.Map.Entry; 23 25 import java.util.SortedMap; 24 26 import java.util.TreeMap; 25 27 import java.util.TreeSet; … … 27 29 import java.util.stream.Collectors; 28 30 29 31 import javax.swing.JOptionPane; 32 import javax.swing.JTree; 33 import javax.swing.tree.DefaultMutableTreeNode; 34 import javax.swing.tree.TreeModel; 35 import javax.swing.tree.TreeNode; 30 36 31 37 import org.openstreetmap.josm.data.preferences.sources.ValidatorPrefHelper; 32 38 import org.openstreetmap.josm.data.projection.ProjectionRegistry; … … 88 94 /** Grid detail, multiplier of east,north values for valuable cell sizing */ 89 95 private static double griddetail; 90 96 91 private static final Collection<String> ignoredErrors = new TreeSet<>(); 92 97 private static final SortedMap<String, String> ignoredErrors = new TreeMap<>(); 93 98 /** 94 99 * All registered tests 95 100 */ … … 169 174 public static void initialize() { 170 175 checkValidatorDir(); 171 176 initializeGridDetail(); 172 loadIgnoredErrors(); //FIXME: load only when needed177 loadIgnoredErrors(); 173 178 } 174 179 175 180 /** … … 204 209 private static void loadIgnoredErrors() { 205 210 ignoredErrors.clear(); 206 211 if (ValidatorPrefHelper.PREF_USE_IGNORE.get()) { 212 Config.getPref().getListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST).forEach(ignoredErrors::putAll); 207 213 Path path = Paths.get(getValidatorDir()).resolve("ignorederrors"); 208 214 try { 209 215 if (path.toFile().exists()) { 210 216 try { 211 ignoredErrors.addAll(Files.readAllLines(path, StandardCharsets.UTF_8)); 217 TreeSet<String> treeSet = new TreeSet<>(); 218 treeSet.addAll(Files.readAllLines(path, StandardCharsets.UTF_8)); 219 treeSet.forEach(ignore -> ignoredErrors.putIfAbsent(ignore, "")); 220 221 saveIgnoredErrors(); 222 Files.deleteIfExists(path); 223 212 224 } catch (FileNotFoundException e) { 213 225 Logging.debug(Logging.getErrorMessage(e)); 214 226 } catch (IOException e) { … … 228 240 * @see TestError#getIgnoreSubGroup() 229 241 */ 230 242 public static void addIgnoredError(String s) { 231 ignoredErrors.add(s);243 addIgnoredError(s, ""); 232 244 } 233 245 234 246 /** 247 * Adds an ignored error 248 * @param s The ignore group / sub group name 249 * @param description What the error actually is 250 * @see TestError#getIgnoreGroup() 251 * @see TestError#getIgnoreSubGroup() 252 */ 253 public static void addIgnoredError(String s, String description) { 254 if (description == null) description = ""; 255 256 ignoredErrors.put(s, description); 257 if (s.split(":(r|w|n)_[0-9]+($|:)").length == 1) { 258 cleanupIgnoredErrors(); 259 } 260 } 261 262 /** 263 * Make sure that we don't keep single entries for a "group ignore" or 264 * multiple different entries for the single entries that are in the same group. 265 */ 266 private static void cleanupIgnoredErrors() { 267 if (ignoredErrors.size() > 1) { 268 List<String> toRemove = new ArrayList<>(); 269 270 Iterator<Entry<String, String>> iter = ignoredErrors.entrySet().iterator(); 271 Entry<String, String> last = iter.next(); 272 while (iter.hasNext()) { 273 Entry<String, String> entry = iter.next(); 274 if (entry.getKey().startsWith(last.getKey())) { 275 toRemove.add(entry.getKey()); 276 } else { 277 last = entry; 278 } 279 } 280 toRemove.forEach(ignoredErrors::remove); 281 Map<String, String> tmap = buildIgnore(buildJTreeList()); 282 if (tmap != null && !tmap.isEmpty()) { 283 ignoredErrors.clear(); 284 ignoredErrors.putAll(tmap); 285 } 286 } 287 } 288 289 /** 235 290 * Check if a error should be ignored 236 291 * @param s The ignore group / sub group name 237 292 * @return <code>true</code> to ignore that error 238 293 */ 239 294 public static boolean hasIgnoredError(String s) { 240 return ignoredErrors.contains (s);295 return ignoredErrors.containsKey(s); 241 296 } 242 297 243 298 /** 244 * Saves the names of the ignored errors to a file 299 * Get the list of all ignored errors 300 * @return The <code>Collection<String></code> of errors that are ignored 245 301 */ 302 public static SortedMap<String, String> getIgnoredErrors() { 303 return ignoredErrors; 304 } 305 306 /** 307 * Build a JTree with a list 308 * @return <type>list as a {@code JTree} 309 */ 310 public static JTree buildJTreeList() { 311 DefaultMutableTreeNode root = new DefaultMutableTreeNode(tr("Ignore list")); 312 313 for (Entry<String, String> e: ignoredErrors.entrySet()) { 314 String key = e.getKey(); 315 String value = e.getValue(); 316 String[] osmobjects = key.split(":(r|w|n)_"); 317 DefaultMutableTreeNode trunk; 318 DefaultMutableTreeNode branch; 319 320 if (value != null && !value.isEmpty()) { 321 trunk = inTree(root, value); 322 branch = inTree(trunk, osmobjects[0]); 323 trunk.add(branch); 324 } else { 325 trunk = inTree(root, osmobjects[0]); 326 branch = trunk; 327 } 328 for (int i = 1; i < osmobjects.length; i++) { 329 String osmid = osmobjects[i]; 330 int index = key.indexOf(osmid); 331 char type = key.charAt(index - 2); 332 DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(type + "_" + osmid); 333 branch.add(leaf); 334 } 335 root.add(trunk); 336 } 337 return new JTree(root); 338 } 339 340 private static DefaultMutableTreeNode inTree(DefaultMutableTreeNode root, String name) { 341 @SuppressWarnings("unchecked") 342 Enumeration<TreeNode> trunks = root.children(); 343 while (trunks.hasMoreElements()) { 344 TreeNode ttrunk = trunks.nextElement(); 345 if (ttrunk instanceof DefaultMutableTreeNode) { 346 DefaultMutableTreeNode trunk = (DefaultMutableTreeNode) ttrunk; 347 if (name.equals(trunk.getUserObject())) { 348 return trunk; 349 } 350 } 351 } 352 return new DefaultMutableTreeNode(name); 353 } 354 355 /** 356 * Build a {@code HashMap} from a tree of ignored errors 357 * @param tree The JTree of ignored errors 358 * @return A {@code HashMap} of the ignored errors for comparison 359 */ 360 public static Map<String, String> buildIgnore(JTree tree) { 361 TreeModel model = tree.getModel(); 362 DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); 363 return buildIgnore(model, root); 364 } 365 366 private static Map<String, String> buildIgnore(TreeModel model, DefaultMutableTreeNode node) { 367 Logging.setLogLevel(Logging.LEVEL_DEBUG); 368 HashMap<String, String> rHashMap = new HashMap<>(); 369 370 String osmids = node.getUserObject().toString(); 371 String description = ""; 372 373 if (!model.getRoot().equals(node)) description = ((DefaultMutableTreeNode) node.getParent()).getUserObject().toString(); 374 if (!osmids.matches("^[0-9]+_.*")) osmids = ""; 375 376 for (int i = 0; i < model.getChildCount(node); i++) { 377 DefaultMutableTreeNode child = (DefaultMutableTreeNode) model.getChild(node, i); 378 if (model.getChildCount(child) == 0) { 379 String ignoreName = child.getUserObject().toString(); 380 if (ignoreName.matches("^(r|w|n)_.*")) { 381 osmids += ":" + child.getUserObject().toString(); 382 } else if (ignoreName.matches("^[0-9]+_.*")) { 383 rHashMap.put(ignoreName, description); 384 } 385 } else { 386 rHashMap.putAll(buildIgnore(model, child)); 387 } 388 } 389 if (!osmids.isEmpty() && osmids.indexOf(':') != 0) rHashMap.put(osmids, description); 390 return rHashMap; 391 } 392 393 /** 394 * Reset the error list by deleting {@code validator.ignorelist} 395 */ 396 public static void resetErrorList() { 397 saveIgnoredErrors(); 398 backupErrorList(); 399 Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, null); 400 OsmValidator.initialize(); 401 } 402 403 /** 404 * Restore the error list by copying {@code validator.ignorelist.bak} to 405 * {@code validator.ignorelist} 406 */ 407 public static void restoreErrorList() { 408 saveIgnoredErrors(); 409 List<Map<String, String>> tlist = Config.getPref().getListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST_BACKUP); 410 backupErrorList(); 411 Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, tlist); 412 OsmValidator.initialize(); 413 } 414 415 private static void backupErrorList() { 416 List<Map<String, String>> tlist = Config.getPref().getListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, null); 417 Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST_BACKUP, tlist); 418 } 419 420 /** 421 * Saves the names of the ignored errors to a preference 422 */ 246 423 public static void saveIgnoredErrors() { 247 try (PrintWriter out = new PrintWriter(new File(getValidatorDir(), "ignorederrors"), StandardCharsets.UTF_8.name())) { 248 for (String e : ignoredErrors) { 249 out.println(e); 424 cleanupIgnoredErrors(); 425 List<Map<String, String>> list = new ArrayList<>(); 426 list.add(ignoredErrors); 427 int i = 0; 428 while (i < list.size()) { 429 if (list.get(i) == null || list.get(i).isEmpty()) { 430 list.remove(i); 431 continue; 250 432 } 251 } catch (IOException e) { 252 Logging.error(e); 433 i++; 253 434 } 435 if (list.isEmpty()) list = null; 436 Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, list); 254 437 } 255 438 256 439 /** -
src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java
63 63 import org.openstreetmap.josm.tools.ImageProvider; 64 64 import org.openstreetmap.josm.tools.InputMapUtils; 65 65 import org.openstreetmap.josm.tools.JosmRuntimeException; 66 import org.openstreetmap.josm.tools.Pair; 66 67 import org.openstreetmap.josm.tools.Shortcut; 67 68 import org.xml.sax.SAXException; 68 69 … … 85 86 private final SideButton fixButton; 86 87 /** The ignore button */ 87 88 private final SideButton ignoreButton; 89 /** The reset ignorelist button */ 90 private final SideButton ignorelistManagement; 88 91 /** The select button */ 89 92 private final SideButton selectButton; 90 93 /** The lookup button */ … … 174 177 }); 175 178 ignoreButton.setEnabled(false); 176 179 buttons.add(ignoreButton); 180 181 if (!ValidatorPrefHelper.PREF_IGNORELIST_KEEP_BACKUP.get()) { 182 // Clear the backup ignore list 183 Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST_BACKUP, null); 184 } 185 ignorelistManagement = new SideButton(new AbstractAction() { 186 { 187 putValue(NAME, tr("Manage Ignore")); 188 putValue(SHORT_DESCRIPTION, tr("Manage the ignore list")); 189 new ImageProvider("dialogs", "fix").getResource().attachImageIcon(this, true); 190 } 191 192 @Override 193 public void actionPerformed(ActionEvent e) { 194 ValidatorListManagementDialog dialog = new ValidatorListManagementDialog("Ignore"); 195 if (dialog.getValue() == 1) { 196 // TODO save 197 } 198 } 199 }); 200 buttons.add(ignorelistManagement); 177 201 } else { 178 202 ignoreButton = null; 203 ignorelistManagement = null; 179 204 } 205 180 206 createLayout(tree, true, buttons); 181 207 } 182 208 … … 245 271 246 272 Object mainNodeInfo = node.getUserObject(); 247 273 if (!(mainNodeInfo instanceof TestError)) { 248 Set< String> state = new HashSet<>();274 Set<Pair<String, String>> state = new HashSet<>(); 249 275 // ask if the whole set should be ignored 250 276 if (asked == JOptionPane.DEFAULT_OPTION) { 251 277 String[] a = new String[] {tr("Whole group"), tr("Single elements"), tr("Nothing")}; … … 257 283 ValidatorTreePanel.visitTestErrors(node, err -> { 258 284 err.setIgnored(true); 259 285 changed.set(true); 260 state.add(n ode.getDepth() == 1 ? err.getIgnoreSubGroup() : err.getIgnoreGroup());286 state.add(new Pair<>(node.getDepth() == 1 ? err.getIgnoreSubGroup() : err.getIgnoreGroup(), err.getMessage())); 261 287 }, processedNodes); 262 for ( Strings : state) {263 OsmValidator.addIgnoredError(s );288 for (Pair<String, String> s : state) { 289 OsmValidator.addIgnoredError(s.a, s.b); 264 290 } 265 291 continue; 266 292 } else if (asked == JOptionPane.CANCEL_OPTION || asked == JOptionPane.CLOSED_OPTION) { … … 271 297 ValidatorTreePanel.visitTestErrors(node, error -> { 272 298 String state = error.getIgnoreState(); 273 299 if (state != null) { 274 OsmValidator.addIgnoredError(state );300 OsmValidator.addIgnoredError(state, error.getMessage()); 275 301 } 276 302 changed.set(true); 277 303 error.setIgnored(true); … … 287 313 /** 288 314 * Sets the selection of the map to the current selected items. 289 315 */ 290 @SuppressWarnings("unchecked")291 316 private void setSelectedItems() { 292 317 DataSet ds = MainApplication.getLayerManager().getActiveDataSet(); 293 318 if (tree == null || ds == null) -
src/org/openstreetmap/josm/gui/dialogs/ValidatorListManagementDialog.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.dialogs; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.awt.GridBagLayout; 7 import java.awt.Rectangle; 8 import java.awt.event.ActionEvent; 9 import java.awt.event.KeyEvent; 10 import java.awt.event.KeyListener; 11 import java.awt.event.MouseAdapter; 12 import java.awt.event.MouseEvent; 13 import java.util.List; 14 import java.util.Locale; 15 import java.util.Map; 16 17 import javax.swing.AbstractAction; 18 import javax.swing.ImageIcon; 19 import javax.swing.JMenuItem; 20 import javax.swing.JOptionPane; 21 import javax.swing.JPanel; 22 import javax.swing.JPopupMenu; 23 import javax.swing.JScrollPane; 24 import javax.swing.JTree; 25 import javax.swing.tree.DefaultMutableTreeNode; 26 import javax.swing.tree.TreePath; 27 28 import org.openstreetmap.josm.actions.ValidateAction; 29 import org.openstreetmap.josm.data.validation.OsmValidator; 30 import org.openstreetmap.josm.data.validation.TestError; 31 import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil; 32 import org.openstreetmap.josm.gui.ExtendedDialog; 33 import org.openstreetmap.josm.gui.MainApplication; 34 import org.openstreetmap.josm.gui.MapFrame; 35 import org.openstreetmap.josm.gui.util.GuiHelper; 36 import org.openstreetmap.josm.tools.GBC; 37 import org.openstreetmap.josm.tools.ImageProvider; 38 import org.openstreetmap.josm.tools.Logging; 39 40 41 /** 42 * A management window for the validator's ignorelist 43 * @author Taylor Smock 44 * @since xxx 45 */ 46 public class ValidatorListManagementDialog extends ExtendedDialog { 47 enum BUTTONS { 48 OK(0, tr("OK"), new ImageProvider("ok")), 49 CLEAR(1, tr("Clear All"), new ImageProvider("dialogs", "fix")), 50 RESTORE(2, tr("Restore"), new ImageProvider("copy")), 51 CANCEL(3, tr("Cancel"), new ImageProvider("cancel")); 52 53 private int index; 54 private String name; 55 private ImageIcon icon; 56 57 BUTTONS(int index, String name, ImageProvider image) { 58 this.index = index; 59 this.name = name; 60 this.icon = image.getResource().getImageIcon(); 61 } 62 63 public ImageIcon getImageIcon() { 64 return icon; 65 } 66 67 public int getIndex() { 68 return index; 69 } 70 71 public String getName() { 72 return name; 73 } 74 } 75 76 private static final String[] BUTTON_TEXTS = {BUTTONS.OK.getName(), BUTTONS.CLEAR.getName(), 77 BUTTONS.RESTORE.getName(), BUTTONS.CANCEL.getName() 78 }; 79 80 private static final ImageIcon[] BUTTON_IMAGES = {BUTTONS.OK.getImageIcon(), BUTTONS.CLEAR.getImageIcon(), 81 BUTTONS.RESTORE.getImageIcon(), BUTTONS.CANCEL.getImageIcon() 82 }; 83 84 private final JPanel panel = new JPanel(new GridBagLayout()); 85 86 private final JTree ignoreErrors; 87 88 private final String type; 89 90 /** 91 * Create a new {@link ValidatorListManagementDialog} 92 * @param type The type of list to create (first letter may or may not be 93 * capitalized, it is put into all lowercase after building the title) 94 */ 95 public ValidatorListManagementDialog(String type) { 96 super(MainApplication.getMainFrame(), tr("Validator {0} List Management", type), BUTTON_TEXTS, false); 97 this.type = type.toLowerCase(Locale.ENGLISH); 98 setButtonIcons(BUTTON_IMAGES); 99 100 ignoreErrors = buildList(); 101 JScrollPane scroll = GuiHelper.embedInVerticalScrollPane(ignoreErrors); 102 103 panel.add(scroll, GBC.eol().fill(GBC.BOTH).anchor(GBC.CENTER)); 104 setContent(panel); 105 setDefaultButton(1); 106 setupDialog(); 107 showDialog(); 108 } 109 110 @Override 111 public void buttonAction(int buttonIndex, ActionEvent evt) { 112 // Currently OK/Cancel buttons do nothing 113 final int answer; 114 if (buttonIndex == BUTTONS.RESTORE.getIndex()) { 115 dispose(); 116 answer = rerunValidatorPrompt(); 117 if (answer == JOptionPane.YES_OPTION || answer == JOptionPane.NO_OPTION) { 118 OsmValidator.restoreErrorList(); 119 } 120 } else if (buttonIndex == BUTTONS.CLEAR.getIndex()) { 121 dispose(); 122 answer = rerunValidatorPrompt(); 123 if (answer == JOptionPane.YES_OPTION || answer == JOptionPane.NO_OPTION) { 124 OsmValidator.resetErrorList(); 125 } 126 } else if (buttonIndex == BUTTONS.OK.getIndex()) { 127 Map<String, String> errors = OsmValidator.getIgnoredErrors(); 128 Map<String, String> tree = OsmValidator.buildIgnore(ignoreErrors); 129 if (!errors.equals(tree)) { 130 answer = rerunValidatorPrompt(); 131 if (answer == JOptionPane.YES_OPTION || answer == JOptionPane.NO_OPTION) { 132 OsmValidator.resetErrorList(); 133 Logging.setLogLevel(Logging.LEVEL_DEBUG); 134 Logging.debug("Starting to rebuild the error list of size {0}", tree.size()); 135 tree.forEach((ignore, description) -> { 136 Logging.debug("Adding {0} with description {1}", ignore, description); 137 OsmValidator.addIgnoredError(ignore, description); 138 }); 139 OsmValidator.saveIgnoredErrors(); 140 OsmValidator.initialize(); 141 } 142 } 143 dispose(); 144 } else { 145 super.buttonAction(buttonIndex, evt); 146 } 147 } 148 149 /** 150 * Build a JTree with a list 151 * @return <type>list as a {@code JTree} 152 */ 153 public JTree buildList() { 154 JTree tree; 155 156 if ("ignore".equals(type)) { 157 tree = OsmValidator.buildJTreeList(); 158 } else { 159 Logging.error(tr("Cannot understand the following type: {0}", type)); 160 return null; 161 } 162 tree.setRootVisible(false); 163 tree.setShowsRootHandles(true); 164 tree.addMouseListener(new MouseAdapter() { 165 @Override 166 public void mousePressed(MouseEvent e) { 167 process(e); 168 } 169 170 @Override 171 public void mouseReleased(MouseEvent e) { 172 process(e); 173 } 174 175 private void process(MouseEvent e) { 176 if (e.isPopupTrigger()) { 177 TreePath[] paths = tree.getSelectionPaths(); 178 if (paths == null) return; 179 Rectangle bounds = tree.getUI().getPathBounds(tree, paths[0]); 180 if (bounds != null) { 181 JPopupMenu menu = new JPopupMenu(); 182 JMenuItem delete = new JMenuItem(new AbstractAction(tr("Delete")) { 183 @Override 184 public void actionPerformed(ActionEvent e1) { 185 deleteAction(tree, paths); 186 } 187 }); 188 menu.add(delete); 189 menu.show(e.getComponent(), e.getX(), e.getY()); 190 } 191 } 192 } 193 }); 194 195 tree.addKeyListener(new KeyListener() { 196 197 @Override 198 public void keyTyped(KeyEvent e) { 199 // Do nothing 200 } 201 202 @Override 203 public void keyPressed(KeyEvent e) { 204 // Do nothing 205 } 206 207 @Override 208 public void keyReleased(KeyEvent e) { 209 TreePath[] paths = tree.getSelectionPaths(); 210 if (e.getKeyCode() == KeyEvent.VK_DELETE && paths != null) { 211 deleteAction(tree, paths); 212 } 213 } 214 }); 215 return tree; 216 } 217 218 private void deleteAction(JTree tree, TreePath[] paths) { 219 for (TreePath path : paths) { 220 tree.clearSelection(); 221 tree.addSelectionPath(path); 222 DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 223 DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent(); 224 node.removeAllChildren(); 225 while (node.getChildCount() == 0) { 226 node.removeFromParent(); 227 node = parent; 228 if (parent == null || parent.isRoot()) break; 229 parent = (DefaultMutableTreeNode) node.getParent(); 230 } 231 } 232 tree.updateUI(); 233 } 234 235 236 /** 237 * Prompt to rerun the validator when the ignore list changes 238 * @return {@code JOptionPane.YES_OPTION}, {@code JOptionPane.NO_OPTION}, 239 * or {@code JOptionPane.CANCEL_OPTION} 240 */ 241 public int rerunValidatorPrompt() { 242 MapFrame map = MainApplication.getMap(); 243 List<TestError> errors = map.validatorDialog.tree.getErrors(); 244 ValidateAction validateAction = ValidatorDialog.validateAction; 245 if (!validateAction.isEnabled() || errors == null || errors.isEmpty()) return JOptionPane.NO_OPTION; 246 final int answer = ConditionalOptionPaneUtil.showOptionDialog( 247 "rerun_validation_when_ignorelist_changed", 248 MainApplication.getMainFrame(), 249 tr("{0}Should the validation be rerun?{1}", "<hmtl><h3>", "</h3></html>"), 250 tr("Ignored error filter changed"), 251 JOptionPane.YES_NO_CANCEL_OPTION, 252 JOptionPane.QUESTION_MESSAGE, 253 null, 254 null); 255 if (answer == JOptionPane.YES_OPTION) { 256 validateAction.doValidate(true); 257 } 258 return answer; 259 } 260 } -
src/org/openstreetmap/josm/spi/preferences/MapListSetting.java
6 6 import java.util.LinkedHashMap; 7 7 import java.util.List; 8 8 import java.util.Map; 9 import java.util.SortedMap; 9 10 10 11 /** 11 12 * Setting containing a {@link List} of {@link Map}s of {@link String} values. … … 40 41 if (value.contains(null)) 41 42 throw new IllegalArgumentException("Error: Null as list element in preference setting"); 42 43 for (Map<String, String> map : value) { 43 if ( map.containsKey(null))44 if (!(map instanceof SortedMap) && map.containsKey(null)) 44 45 throw new IllegalArgumentException("Error: Null as map key in preference setting"); 45 46 if (map.containsValue(null)) 46 47 throw new IllegalArgumentException("Error: Null as map value in preference setting");