Ticket #17268: clear_ignored_errors_v24.2.patch
File clear_ignored_errors_v24.2.patch, 26.4 KB (added by , 5 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; … … 18 17 import java.util.Collections; 19 18 import java.util.EnumMap; 20 19 import java.util.HashMap; 20 import java.util.Iterator; 21 21 import java.util.List; 22 22 import java.util.Map; 23 import java.util.Map.Entry; 23 24 import java.util.SortedMap; 24 25 import java.util.TreeMap; 25 26 import java.util.TreeSet; … … 88 89 /** Grid detail, multiplier of east,north values for valuable cell sizing */ 89 90 private static double griddetail; 90 91 91 private static final Collection<String> ignoredErrors = new TreeSet<>(); 92 92 private static final SortedMap<String, String> ignoredErrors = new TreeMap<>(); 93 93 /** 94 94 * All registered tests 95 95 */ … … 169 169 public static void initialize() { 170 170 checkValidatorDir(); 171 171 initializeGridDetail(); 172 loadIgnoredErrors(); //FIXME: load only when needed172 loadIgnoredErrors(); 173 173 } 174 174 175 175 /** … … 204 204 private static void loadIgnoredErrors() { 205 205 ignoredErrors.clear(); 206 206 if (ValidatorPrefHelper.PREF_USE_IGNORE.get()) { 207 Config.getPref().getListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST).forEach(ignoredErrors::putAll); 207 208 Path path = Paths.get(getValidatorDir()).resolve("ignorederrors"); 208 209 try { 209 210 if (path.toFile().exists()) { 210 211 try { 211 ignoredErrors.addAll(Files.readAllLines(path, StandardCharsets.UTF_8)); 212 TreeSet<String> treeSet = new TreeSet<>(); 213 treeSet.addAll(Files.readAllLines(path, StandardCharsets.UTF_8)); 214 treeSet.forEach(ignore -> ignoredErrors.putIfAbsent(ignore, "")); 215 216 saveIgnoredErrors(); 217 Files.deleteIfExists(path); 218 219 cleanupIgnoredErrors(); 212 220 } catch (FileNotFoundException e) { 213 221 Logging.debug(Logging.getErrorMessage(e)); 214 222 } catch (IOException e) { … … 228 236 * @see TestError#getIgnoreSubGroup() 229 237 */ 230 238 public static void addIgnoredError(String s) { 231 ignoredErrors.add(s);239 addIgnoredError(s, ""); 232 240 } 233 241 234 242 /** 243 * Adds an ignored error 244 * @param s The ignore group / sub group name 245 * @param description What the error actually is 246 * @see TestError#getIgnoreGroup() 247 * @see TestError#getIgnoreSubGroup() 248 */ 249 public static void addIgnoredError(String s, String description) { 250 if (description == null) description = ""; 251 252 ignoredErrors.put(s, description); 253 if (s.split(":(r|w|n)_[0-9]+($|:)").length == 1) { 254 cleanupIgnoredErrors(); 255 } 256 } 257 258 /** 259 * make sure that we don't keep single entries for a "group ignore" 260 */ 261 private static void cleanupIgnoredErrors() { 262 if (ignoredErrors.size() > 1) { 263 List<String> toRemove = new ArrayList<>(); 264 265 Iterator<Entry<String, String>> iter = ignoredErrors.entrySet().iterator(); 266 Entry<String, String> last = iter.next(); 267 while (iter.hasNext()) { 268 Entry<String, String> entry = iter.next(); 269 if (entry.getKey().startsWith(last.getKey())) { 270 toRemove.add(entry.getKey()); 271 } else { 272 last = entry; 273 } 274 } 275 toRemove.forEach(ignoredErrors::remove); 276 } 277 } 278 279 /** 235 280 * Check if a error should be ignored 236 281 * @param s The ignore group / sub group name 237 282 * @return <code>true</code> to ignore that error 238 283 */ 239 284 public static boolean hasIgnoredError(String s) { 240 return ignoredErrors.contains (s);285 return ignoredErrors.containsKey(s); 241 286 } 242 287 243 288 /** 244 * Saves the names of the ignored errors to a file 289 * Get the list of all ignored errors 290 * @return The <code>Collection<String></code> of errors that are ignored 245 291 */ 292 public static SortedMap<String, String> getIgnoredErrors() { 293 return ignoredErrors; 294 } 295 296 /** 297 * Reset the error list by deleting {@code validator.ignorelist} 298 */ 299 public static void resetErrorList() { 300 saveIgnoredErrors(); 301 backupErrorList(); 302 Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, null); 303 OsmValidator.initialize(); 304 } 305 306 /** 307 * Restore the error list by copying {@code validator.ignorelist.bak} to 308 * {@code validator.ignorelist} 309 */ 310 public static void restoreErrorList() { 311 saveIgnoredErrors(); 312 List<Map<String, String>> tlist = Config.getPref().getListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST_BACKUP); 313 backupErrorList(); 314 Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, tlist); 315 OsmValidator.initialize(); 316 } 317 318 private static void backupErrorList() { 319 List<Map<String, String>> tlist = Config.getPref().getListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, null); 320 Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST_BACKUP, tlist); 321 } 322 323 /** 324 * Saves the names of the ignored errors to a preference 325 */ 246 326 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); 327 cleanupIgnoredErrors(); 328 List<Map<String, String>> list = new ArrayList<>(); 329 list.add(ignoredErrors); 330 int i = 0; 331 while (i < list.size()) { 332 if (list.get(i) == null || list.get(i).isEmpty()) { 333 list.remove(i); 334 continue; 250 335 } 251 } catch (IOException e) { 252 Logging.error(e); 336 i++; 253 337 } 338 if (list.isEmpty()) list = null; 339 Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, list); 254 340 } 255 341 256 342 /** -
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.Enumeration; 14 import java.util.HashMap; 15 import java.util.List; 16 import java.util.Locale; 17 import java.util.Map; 18 import java.util.Map.Entry; 19 import java.util.TreeMap; 20 21 import javax.swing.AbstractAction; 22 import javax.swing.ImageIcon; 23 import javax.swing.JMenuItem; 24 import javax.swing.JOptionPane; 25 import javax.swing.JPanel; 26 import javax.swing.JPopupMenu; 27 import javax.swing.JScrollPane; 28 import javax.swing.JTree; 29 import javax.swing.tree.DefaultMutableTreeNode; 30 import javax.swing.tree.TreeModel; 31 import javax.swing.tree.TreeNode; 32 import javax.swing.tree.TreePath; 33 34 import org.openstreetmap.josm.actions.ValidateAction; 35 import org.openstreetmap.josm.data.validation.OsmValidator; 36 import org.openstreetmap.josm.data.validation.TestError; 37 import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil; 38 import org.openstreetmap.josm.gui.ExtendedDialog; 39 import org.openstreetmap.josm.gui.MainApplication; 40 import org.openstreetmap.josm.gui.MapFrame; 41 import org.openstreetmap.josm.gui.util.GuiHelper; 42 import org.openstreetmap.josm.tools.GBC; 43 import org.openstreetmap.josm.tools.ImageProvider; 44 import org.openstreetmap.josm.tools.Logging; 45 46 47 /** 48 * A management window for the validator's ignorelist 49 * @author Taylor Smock 50 * @since xxx 51 */ 52 public class ValidatorListManagementDialog extends ExtendedDialog { 53 enum BUTTONS { 54 OK(0, tr("OK"), new ImageProvider("ok")), 55 CLEAR(1, tr("Clear All"), new ImageProvider("dialogs", "fix")), 56 RESTORE(2, tr("Restore"), new ImageProvider("copy")), 57 CANCEL(3, tr("Cancel"), new ImageProvider("cancel")); 58 59 private int index; 60 private String name; 61 private ImageIcon icon; 62 63 BUTTONS(int index, String name, ImageProvider image) { 64 this.index = index; 65 this.name = name; 66 this.icon = image.getResource().getImageIcon(); 67 } 68 69 public ImageIcon getImageIcon() { 70 return icon; 71 } 72 73 public int getIndex() { 74 return index; 75 } 76 77 public String getName() { 78 return name; 79 } 80 } 81 82 private static final String[] BUTTON_TEXTS = {BUTTONS.OK.getName(), BUTTONS.CLEAR.getName(), 83 BUTTONS.RESTORE.getName(), BUTTONS.CANCEL.getName() 84 }; 85 86 private static final ImageIcon[] BUTTON_IMAGES = {BUTTONS.OK.getImageIcon(), BUTTONS.CLEAR.getImageIcon(), 87 BUTTONS.RESTORE.getImageIcon(), BUTTONS.CANCEL.getImageIcon() 88 }; 89 90 private final JPanel panel = new JPanel(new GridBagLayout()); 91 92 private final JTree ignoreErrors; 93 94 private final String type; 95 96 /** 97 * Create a new {@link ValidatorListManagementDialog} 98 * @param type The type of list to create (first letter may or may not be 99 * capitalized, it is put into all lowercase after building the title) 100 */ 101 public ValidatorListManagementDialog(String type) { 102 super(MainApplication.getMainFrame(), tr("Validator {0} List Management", type), BUTTON_TEXTS, false); 103 this.type = type.toLowerCase(Locale.ENGLISH); 104 setButtonIcons(BUTTON_IMAGES); 105 106 ignoreErrors = buildList(); 107 JScrollPane scroll = GuiHelper.embedInVerticalScrollPane(ignoreErrors); 108 109 panel.add(scroll, GBC.eol().fill(GBC.BOTH).anchor(GBC.CENTER)); 110 setContent(panel); 111 setDefaultButton(1); 112 setupDialog(); 113 showDialog(); 114 } 115 116 @Override 117 public void buttonAction(int buttonIndex, ActionEvent evt) { 118 // Currently OK/Cancel buttons do nothing 119 final int answer; 120 if (buttonIndex == BUTTONS.RESTORE.getIndex()) { 121 dispose(); 122 answer = rerunValidatorPrompt(); 123 if (answer == JOptionPane.YES_OPTION || answer == JOptionPane.NO_OPTION) { 124 OsmValidator.restoreErrorList(); 125 } 126 } else if (buttonIndex == BUTTONS.CLEAR.getIndex()) { 127 dispose(); 128 answer = rerunValidatorPrompt(); 129 if (answer == JOptionPane.YES_OPTION || answer == JOptionPane.NO_OPTION) { 130 OsmValidator.resetErrorList(); 131 } 132 } else if (buttonIndex == BUTTONS.OK.getIndex()) { 133 Map<String, String> errors = OsmValidator.getIgnoredErrors(); 134 Map<String, String> tree = buildIgnore(ignoreErrors); 135 if (!errors.equals(tree)) { 136 answer = rerunValidatorPrompt(); 137 if (answer == JOptionPane.YES_OPTION || answer == JOptionPane.NO_OPTION) { 138 OsmValidator.resetErrorList(); 139 Logging.setLogLevel(Logging.LEVEL_DEBUG); 140 Logging.debug("Starting to rebuild the error list of size {0}", tree.size()); 141 tree.forEach((ignore, description) -> { 142 Logging.debug("Adding {0} with description {1}", ignore, description); 143 OsmValidator.addIgnoredError(ignore, description); 144 }); 145 OsmValidator.saveIgnoredErrors(); 146 OsmValidator.initialize(); 147 } 148 } 149 dispose(); 150 } else { 151 super.buttonAction(buttonIndex, evt); 152 } 153 } 154 155 /** 156 * Build a {@code HashMap} from a tree of ignored errors 157 * @param tree The JTree of ignored errors 158 * @return A {@code HashMap} of the ignored errors for comparison 159 */ 160 public Map<String, String> buildIgnore(JTree tree) { 161 TreeModel model = tree.getModel(); 162 DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); 163 return buildIgnore(model, root); 164 } 165 166 private static Map<String, String> buildIgnore(TreeModel model, DefaultMutableTreeNode node) { 167 Logging.setLogLevel(Logging.LEVEL_DEBUG); 168 HashMap<String, String> rHashMap = new HashMap<>(); 169 170 String osmids = node.getUserObject().toString(); 171 String description = ""; 172 173 if (!model.getRoot().equals(node)) description = ((DefaultMutableTreeNode) node.getParent()).getUserObject().toString(); 174 if (!osmids.matches("^[0-9]+_.*")) osmids = ""; 175 176 for (int i = 0; i < model.getChildCount(node); i++) { 177 DefaultMutableTreeNode child = (DefaultMutableTreeNode) model.getChild(node, i); 178 if (model.getChildCount(child) == 0) { 179 String ignoreName = child.getUserObject().toString(); 180 if (ignoreName.matches("^(r|w|n)_.*")) { 181 osmids += ":" + child.getUserObject().toString(); 182 } else if (ignoreName.matches("^[0-9]+_.*")) { 183 rHashMap.put(ignoreName, description); 184 } 185 } else { 186 rHashMap.putAll(buildIgnore(model, child)); 187 } 188 } 189 if (!osmids.isEmpty() && osmids.indexOf(':') != 0) rHashMap.put(osmids, description); 190 return rHashMap; 191 } 192 193 private static DefaultMutableTreeNode inTree(DefaultMutableTreeNode root, String name) { 194 @SuppressWarnings("unchecked") 195 Enumeration<TreeNode> trunks = root.children(); 196 while (trunks.hasMoreElements()) { 197 TreeNode ttrunk = trunks.nextElement(); 198 if (ttrunk instanceof DefaultMutableTreeNode) { 199 DefaultMutableTreeNode trunk = (DefaultMutableTreeNode) ttrunk; 200 if (name.equals(trunk.getUserObject())) { 201 return trunk; 202 } 203 } 204 } 205 return new DefaultMutableTreeNode(name); 206 } 207 208 /** 209 * Build a JTree with a list 210 * @return <type>list as a {@code JTree} 211 */ 212 public JTree buildList() { 213 TreeMap<String, String> map = new TreeMap<>(); 214 if ("ignore".equals(type)) { 215 Map<String, String> tmap; 216 tmap = OsmValidator.getIgnoredErrors(); 217 if (tmap.isEmpty()) { 218 OsmValidator.initialize(); 219 tmap = OsmValidator.getIgnoredErrors(); 220 } 221 map.putAll(tmap); 222 } else { 223 Logging.error(tr("Cannot understand the following type: {0}", type)); 224 return null; 225 } 226 DefaultMutableTreeNode root = new DefaultMutableTreeNode(tr("{0} list", type)); 227 228 for (Entry<String, String> e: map.entrySet()) { 229 String key = e.getKey(); 230 String value = e.getValue(); 231 String[] osmobjects = key.split(":(r|w|n)_"); 232 DefaultMutableTreeNode trunk; 233 DefaultMutableTreeNode branch; 234 235 if (value != null && !value.isEmpty()) { 236 trunk = inTree(root, value); 237 branch = inTree(trunk, osmobjects[0]); 238 trunk.add(branch); 239 } else { 240 trunk = inTree(root, osmobjects[0]); 241 branch = trunk; 242 } 243 for (int i = 1; i < osmobjects.length; i++) { 244 String osmid = osmobjects[i]; 245 int index = key.indexOf(osmid); 246 char type = key.charAt(index - 2); 247 DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(type + "_" + osmid); 248 branch.add(leaf); 249 } 250 root.add(trunk); 251 } 252 JTree tree = new JTree(root); 253 tree.setRootVisible(false); 254 tree.setShowsRootHandles(true); 255 tree.addMouseListener(new MouseAdapter() { 256 @Override 257 public void mousePressed(MouseEvent e) { 258 process(e); 259 } 260 261 @Override 262 public void mouseReleased(MouseEvent e) { 263 process(e); 264 } 265 266 private void process(MouseEvent e) { 267 if (e.isPopupTrigger()) { 268 TreePath[] paths = tree.getSelectionPaths(); 269 if (paths == null) return; 270 Rectangle bounds = tree.getUI().getPathBounds(tree, paths[0]); 271 if (bounds != null) { 272 JPopupMenu menu = new JPopupMenu(); 273 JMenuItem delete = new JMenuItem(new AbstractAction(tr("Delete")) { 274 @Override 275 public void actionPerformed(ActionEvent e1) { 276 deleteAction(tree, paths); 277 } 278 }); 279 menu.add(delete); 280 menu.show(e.getComponent(), e.getX(), e.getY()); 281 } 282 } 283 } 284 }); 285 286 tree.addKeyListener(new KeyListener() { 287 288 @Override 289 public void keyTyped(KeyEvent e) { 290 // Do nothing 291 } 292 293 @Override 294 public void keyPressed(KeyEvent e) { 295 // Do nothing 296 } 297 298 @Override 299 public void keyReleased(KeyEvent e) { 300 TreePath[] paths = tree.getSelectionPaths(); 301 if (e.getKeyCode() == KeyEvent.VK_DELETE && paths != null) { 302 deleteAction(tree, paths); 303 } 304 } 305 }); 306 return tree; 307 } 308 309 private void deleteAction(JTree tree, TreePath[] paths) { 310 for (TreePath path : paths) { 311 tree.clearSelection(); 312 tree.addSelectionPath(path); 313 DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 314 DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent(); 315 node.removeAllChildren(); 316 while (node.getChildCount() == 0) { 317 node.removeFromParent(); 318 node = parent; 319 if (parent.isRoot()) break; 320 parent = (DefaultMutableTreeNode) node.getParent(); 321 } 322 } 323 tree.updateUI(); 324 } 325 326 327 /** 328 * Prompt to rerun the validator when the ignore list changes 329 * @return {@code JOptionPane.YES_OPTION}, {@code JOptionPane.NO_OPTION}, 330 * or {@code JOptionPane.CANCEL_OPTION} 331 */ 332 public int rerunValidatorPrompt() { 333 MapFrame map = MainApplication.getMap(); 334 List<TestError> errors = map.validatorDialog.tree.getErrors(); 335 ValidateAction validateAction = ValidatorDialog.validateAction; 336 if (!validateAction.isEnabled() || errors == null || errors.isEmpty()) return JOptionPane.NO_OPTION; 337 final int answer = ConditionalOptionPaneUtil.showOptionDialog( 338 "rerun_validation_when_ignorelist_changed", 339 MainApplication.getMainFrame(), 340 tr("{0}Should the validation be rerun?{1}", "<hmtl><h3>", "</h3></html>"), 341 tr("Ignored error filter changed"), 342 JOptionPane.YES_NO_CANCEL_OPTION, 343 JOptionPane.QUESTION_MESSAGE, 344 null, 345 null); 346 if (answer == JOptionPane.YES_OPTION) { 347 validateAction.doValidate(true); 348 } 349 return answer; 350 } 351 } -
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");