- Timestamp:
- 2015-05-31T17:06:27+02:00 (9 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/validation/FixableTestError.java
r8378 r8435 14 14 protected final Command fix; 15 15 16 /** 17 * Constructs a new {@code FixableTestError} for a single primitive. 18 * @param tester The tester 19 * @param severity The severity of this error 20 * @param message The error message 21 * @param code The test error reference code 22 * @param primitive The affected primitive 23 * @param fix The command used to fix the error 24 */ 16 25 public FixableTestError(Test tester, Severity severity, String message, int code, OsmPrimitive primitive, Command fix) { 17 26 super(tester, severity, message, code, primitive); … … 19 28 } 20 29 21 public FixableTestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives, Command fix) { 30 /** 31 * Constructs a new {@code FixableTestError} for multiple primitives. 32 * @param tester The tester 33 * @param severity The severity of this error 34 * @param message The error message 35 * @param code The test error reference code 36 * @param primitives The affected primitives 37 * @param fix The command used to fix the error 38 */ 39 public FixableTestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives, 40 Command fix) { 22 41 super(tester, severity, message, code, primitives); 23 42 this.fix = fix; 24 43 } 25 44 26 public FixableTestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives, Collection<?> highlighted, Command fix) { 45 /** 46 * Constructs a new {@code FixableTestError} for multiple primitives. 47 * @param tester The tester 48 * @param severity The severity of this error 49 * @param message The error message 50 * @param code The test error reference code 51 * @param primitives The affected primitives 52 * @param highlighted OSM primitives to highlight 53 * @param fix The command used to fix the error 54 */ 55 public FixableTestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives, 56 Collection<?> highlighted, Command fix) { 27 57 super(tester, severity, message, code, primitives, highlighted); 28 58 this.fix = fix; 29 59 } 30 60 31 public FixableTestError(Test tester, Severity severity, String message, String description, String description_en, int code, OsmPrimitive primitive, Command fix) { 32 super(tester, severity, message, description, description_en, code, primitive); 61 /** 62 * Constructs a new {@code FixableTestError} for a single primitive. 63 * @param tester The tester 64 * @param severity The severity of this error 65 * @param message The error message 66 * @param description The translated description 67 * @param descriptionEn The English description 68 * @param code The test error reference code 69 * @param primitive The affected primitive 70 * @param fix The command used to fix the error 71 */ 72 public FixableTestError(Test tester, Severity severity, String message, String description, String descriptionEn, int code, 73 OsmPrimitive primitive, Command fix) { 74 super(tester, severity, message, description, descriptionEn, code, primitive); 33 75 this.fix = fix; 34 76 } 35 77 36 public FixableTestError(Test tester, Severity severity, String message, String description, String description_en, int code, Collection<? extends OsmPrimitive> primitives, Command fix) { 37 super(tester, severity, message, description, description_en, code, primitives); 78 /** 79 * Constructs a new {@code FixableTestError} for multiple primitives. 80 * @param tester The tester 81 * @param severity The severity of this error 82 * @param message The error message 83 * @param description The translated description 84 * @param descriptionEn The English description 85 * @param code The test error reference code 86 * @param primitives The affected primitives 87 * @param fix The command used to fix the error 88 */ 89 public FixableTestError(Test tester, Severity severity, String message, String description, String descriptionEn, int code, 90 Collection<? extends OsmPrimitive> primitives, Command fix) { 91 super(tester, severity, message, description, descriptionEn, code, primitives); 38 92 this.fix = fix; 39 93 } 40 94 41 public FixableTestError(Test tester, Severity severity, String message, String description, String description_en, int code, Collection<? extends OsmPrimitive> primitives, Collection<?> highlighted, Command fix) { 42 super(tester, severity, message, description, description_en, code, primitives, highlighted); 95 /** 96 * Constructs a new {@code FixableTestError} for multiple primitives. 97 * @param tester The tester 98 * @param severity The severity of this error 99 * @param message The error message 100 * @param description The translated description 101 * @param descriptionEn The English description 102 * @param code The test error reference code 103 * @param primitives The affected primitives 104 * @param highlighted OSM primitives to highlight 105 * @param fix The command used to fix the error 106 */ 107 public FixableTestError(Test tester, Severity severity, String message, String description, String descriptionEn, int code, 108 Collection<? extends OsmPrimitive> primitives, Collection<?> highlighted, Command fix) { 109 super(tester, severity, message, description, descriptionEn, code, primitives, highlighted); 43 110 this.fix = fix; 44 111 } -
trunk/src/org/openstreetmap/josm/data/validation/TestError.java
r8390 r8435 57 57 * @param severity The severity of this error 58 58 * @param message The error message 59 * @param description The translated description 60 * @param descriptionEn The English description 59 61 * @param primitives The affected primitives 60 62 * @param code The test error reference code 61 */ 62 public TestError(Test tester, Severity severity, String message, String description, String description_en, 63 * @param highlighted OSM primitives to highlight 64 */ 65 public TestError(Test tester, Severity severity, String message, String description, String descriptionEn, 63 66 int code, Collection<? extends OsmPrimitive> primitives, Collection<?> highlighted) { 64 67 this.tester = tester; … … 66 69 this.message = message; 67 70 this.description = description; 68 this.descriptionEn = description _en;71 this.descriptionEn = descriptionEn; 69 72 this.primitives = primitives; 70 73 this.highlighted = highlighted; … … 72 75 } 73 76 77 /** 78 * Constructs a new {@code TestError} without description. 79 * @param tester The tester 80 * @param severity The severity of this error 81 * @param message The error message 82 * @param primitives The affected primitives 83 * @param code The test error reference code 84 * @param highlighted OSM primitives to highlight 85 */ 74 86 public TestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives, 75 87 Collection<?> highlighted) { … … 77 89 } 78 90 79 public TestError(Test tester, Severity severity, String message, String description, String description_en, 91 /** 92 * Constructs a new {@code TestError}. 93 * @param tester The tester 94 * @param severity The severity of this error 95 * @param message The error message 96 * @param description The translated description 97 * @param descriptionEn The English description 98 * @param primitives The affected primitives 99 * @param code The test error reference code 100 */ 101 public TestError(Test tester, Severity severity, String message, String description, String descriptionEn, 80 102 int code, Collection<? extends OsmPrimitive> primitives) { 81 this(tester, severity, message, description, description_en, code, primitives, primitives); 82 } 83 103 this(tester, severity, message, description, descriptionEn, code, primitives, primitives); 104 } 105 106 /** 107 * Constructs a new {@code TestError} without description. 108 * @param tester The tester 109 * @param severity The severity of this error 110 * @param message The error message 111 * @param primitives The affected primitives 112 * @param code The test error reference code 113 */ 84 114 public TestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives) { 85 115 this(tester, severity, message, null, null, code, primitives, primitives); 86 116 } 87 117 118 /** 119 * Constructs a new {@code TestError} without description, for a single primitive. 120 * @param tester The tester 121 * @param severity The severity of this error 122 * @param message The error message 123 * @param primitive The affected primitive 124 * @param code The test error reference code 125 */ 88 126 public TestError(Test tester, Severity severity, String message, int code, OsmPrimitive primitive) { 89 127 this(tester, severity, message, null, null, code, Collections.singletonList(primitive), Collections … … 91 129 } 92 130 93 public TestError(Test tester, Severity severity, String message, String description, String description_en, 131 /** 132 * Constructs a new {@code TestError} for a single primitive. 133 * @param tester The tester 134 * @param severity The severity of this error 135 * @param message The error message 136 * @param description The translated description 137 * @param descriptionEn The English description 138 * @param primitive The affected primitive 139 * @param code The test error reference code 140 */ 141 public TestError(Test tester, Severity severity, String message, String description, String descriptionEn, 94 142 int code, OsmPrimitive primitive) { 95 this(tester, severity, message, description, description _en, code, Collections.singletonList(primitive));143 this(tester, severity, message, description, descriptionEn, code, Collections.singletonList(primitive)); 96 144 } 97 145 -
trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java
r8404 r8435 39 39 import org.openstreetmap.josm.data.osm.OsmUtils; 40 40 import org.openstreetmap.josm.data.osm.Tag; 41 import org.openstreetmap.josm.data.validation.FixableTestError; 41 42 import org.openstreetmap.josm.data.validation.Severity; 42 import org.openstreetmap.josm.data.validation.Test ;43 import org.openstreetmap.josm.data.validation.Test.TagTest; 43 44 import org.openstreetmap.josm.data.validation.TestError; 44 45 import org.openstreetmap.josm.data.validation.util.Entities; … … 56 57 import org.openstreetmap.josm.tools.GBC; 57 58 import org.openstreetmap.josm.tools.MultiMap; 59 import org.openstreetmap.josm.tools.Utils; 58 60 59 61 /** … … 61 63 * 62 64 * @author frsantos 65 * @since 3669 63 66 */ 64 public class TagChecker extends Test.TagTest { 65 66 /** The default data file of tagchecker rules */ 67 //public static final String DATA_FILE = "resource://data/validator/tagchecker.cfg"; 67 public class TagChecker extends TagTest { 68 68 69 /** The config file of ignored tags */ 69 70 public static final String IGNORE_FILE = "resource://data/validator/ignoretags.cfg"; … … 125 126 protected static final int LOW_CHAR_VALUE = 1210; 126 127 protected static final int LOW_CHAR_KEY = 1211; 128 protected static final int MISSPELLED_VALUE = 1212; 127 129 /** 1250 and up is used by tagcheck */ 128 130 … … 324 326 for (CheckerData d : checkerData) { 325 327 if (d.match(p, keys)) { 326 errors.add( 327 d.getDescription(), d.getDescriptionOrig(), d.getCode(), p) 328 errors.add(new TestError(this, d.getSeverity(), tr("Suspicious tag/value combinations"), 329 d.getDescription(), d.getDescriptionOrig(), d.getCode(), p)); 328 330 withErrors.put(p, "TC"); 329 331 } … … 336 338 String value = prop.getValue(); 337 339 if (checkValues && (containsLow(value)) && !withErrors.contains(p, "ICV")) { 338 errors.add( 339 tr(s, key), MessageFormat.format(s, key), LOW_CHAR_VALUE, p) 340 errors.add(new TestError(this, Severity.WARNING, tr("Tag value contains character with code less than 0x20"), 341 tr(s, key), MessageFormat.format(s, key), LOW_CHAR_VALUE, p)); 340 342 withErrors.put(p, "ICV"); 341 343 } 342 344 if (checkKeys && (containsLow(key)) && !withErrors.contains(p, "ICK")) { 343 errors.add( 344 tr(s, key), MessageFormat.format(s, key), LOW_CHAR_KEY, p) 345 errors.add(new TestError(this, Severity.WARNING, tr("Tag key contains character with code less than 0x20"), 346 tr(s, key), MessageFormat.format(s, key), LOW_CHAR_KEY, p)); 345 347 withErrors.put(p, "ICK"); 346 348 } 347 349 if (checkValues && (value!=null && value.length() > 255) && !withErrors.contains(p, "LV")) { 348 errors.add( 349 tr(s, key), MessageFormat.format(s, key), LONG_VALUE, p) 350 errors.add(new TestError(this, Severity.ERROR, tr("Tag value longer than allowed"), 351 tr(s, key), MessageFormat.format(s, key), LONG_VALUE, p)); 350 352 withErrors.put(p, "LV"); 351 353 } 352 354 if (checkKeys && (key!=null && key.length() > 255) && !withErrors.contains(p, "LK")) { 353 errors.add( 354 tr(s, key), MessageFormat.format(s, key), LONG_KEY, p) 355 errors.add(new TestError(this, Severity.ERROR, tr("Tag key longer than allowed"), 356 tr(s, key), MessageFormat.format(s, key), LONG_KEY, p)); 355 357 withErrors.put(p, "LK"); 356 358 } 357 359 if (checkValues && (value==null || value.trim().isEmpty()) && !withErrors.contains(p, "EV")) { 358 errors.add( 359 tr(s, key), MessageFormat.format(s, key), EMPTY_VALUES, p) 360 errors.add(new TestError(this, Severity.WARNING, tr("Tags with empty values"), 361 tr(s, key), MessageFormat.format(s, key), EMPTY_VALUES, p)); 360 362 withErrors.put(p, "EV"); 361 363 } 362 364 if (checkKeys && spellCheckKeyData.containsKey(key) && !withErrors.contains(p, "IPK")) { 363 errors.add( 364 tr(s, key), MessageFormat.format(s, key), INVALID_KEY, p) 365 errors.add(new TestError(this, Severity.WARNING, tr("Invalid property key"), 366 tr(s, key), MessageFormat.format(s, key), INVALID_KEY, p)); 365 367 withErrors.put(p, "IPK"); 366 368 } 367 369 if (checkKeys && key != null && key.indexOf(' ') >= 0 && !withErrors.contains(p, "IPK")) { 368 errors.add( 369 tr(s, key), MessageFormat.format(s, key), INVALID_KEY_SPACE, p) 370 errors.add(new TestError(this, Severity.WARNING, tr("Invalid white space in property key"), 371 tr(s, key), MessageFormat.format(s, key), INVALID_KEY_SPACE, p)); 370 372 withErrors.put(p, "IPK"); 371 373 } 372 374 if (checkValues && value != null && (value.startsWith(" ") || value.endsWith(" ")) && !withErrors.contains(p, "SPACE")) { 373 errors.add( 374 tr(s, key), MessageFormat.format(s, key), INVALID_SPACE, p) 375 errors.add(new TestError(this, Severity.WARNING, tr("Property values start or end with white space"), 376 tr(s, key), MessageFormat.format(s, key), INVALID_SPACE, p)); 375 377 withErrors.put(p, "SPACE"); 376 378 } 377 379 if (checkValues && value != null && !value.equals(entities.unescape(value)) && !withErrors.contains(p, "HTML")) { 378 errors.add( 379 tr(s, key), MessageFormat.format(s, key), INVALID_HTML, p) 380 errors.add(new TestError(this, Severity.OTHER, tr("Property values contain HTML entity"), 381 tr(s, key), MessageFormat.format(s, key), INVALID_HTML, p)); 380 382 withErrors.put(p, "HTML"); 381 383 } … … 413 415 if (!keyInPresets) { 414 416 String i = marktr("Key ''{0}'' not in presets."); 415 errors.add( 416 tr(i, key), MessageFormat.format(i, key), INVALID_VALUE, p) 417 errors.add(new TestError(this, Severity.OTHER, tr("Presets do not contain property key"), 418 tr(i, key), MessageFormat.format(i, key), INVALID_VALUE, p)); 417 419 withErrors.put(p, "UPK"); 418 420 } else if (!tagInPresets) { 419 String i = marktr("Value ''{0}'' for key ''{1}'' not in presets."); 420 errors.add( new TestError(this, Severity.OTHER, tr("Presets do not contain property value"), 421 tr(i, prop.getValue(), key), MessageFormat.format(i, prop.getValue(), key), INVALID_VALUE, p) ); 422 withErrors.put(p, "UPV"); 421 // try to fix common typos and check again if value is still unknown 422 String fixedValue = prettifyValue(prop.getValue()); 423 if (values != null && values.contains(fixedValue)) { 424 // misspelled preset value 425 String i = marktr("Value ''{0}'' for key ''{1}'' looks like ''{2}}."); 426 errors.add(new FixableTestError(this, Severity.WARNING, tr("Misspelled property value"), 427 tr(i, prop.getValue(), key, fixedValue), MessageFormat.format(i, prop.getValue(), fixedValue), 428 MISSPELLED_VALUE, p, new ChangePropertyCommand(p, key, fixedValue))); 429 withErrors.put(p, "WPV"); 430 } else { 431 // unknown preset value 432 String i = marktr("Value ''{0}'' for key ''{1}'' not in presets."); 433 errors.add(new TestError(this, Severity.OTHER, tr("Presets do not contain property value"), 434 tr(i, prop.getValue(), key), MessageFormat.format(i, prop.getValue(), key), INVALID_VALUE, p)); 435 withErrors.put(p, "UPV"); 436 } 423 437 } 424 438 } … … 435 449 } 436 450 } 451 } 452 453 private static String prettifyValue(String value) { 454 // convert to lower case, replace ' ' or '-' with '_' 455 value = value.toLowerCase(Locale.ENGLISH).replace('-', '_').replace(' ', '_'); 456 // remove trailing or leading special chars 457 return Utils.strip(value, "-_;:,"); 437 458 } 438 459 … … 554 575 List<Command> commands = new ArrayList<>(50); 555 576 556 Collection<? extends OsmPrimitive> primitives = testError.getPrimitives(); 557 for (OsmPrimitive p : primitives) { 558 Map<String, String> tags = p.getKeys(); 559 if (tags == null || tags.isEmpty()) { 560 continue; 561 } 562 563 for (Entry<String, String> prop: tags.entrySet()) { 564 String key = prop.getKey(); 565 String value = prop.getValue(); 566 if (value == null || value.trim().isEmpty()) { 567 commands.add(new ChangePropertyCommand(p, key, null)); 568 } else if (value.startsWith(" ") || value.endsWith(" ")) { 569 commands.add(new ChangePropertyCommand(p, key, Tag.removeWhiteSpaces(value))); 570 } else if (key.startsWith(" ") || key.endsWith(" ")) { 571 commands.add(new ChangePropertyKeyCommand(p, key, Tag.removeWhiteSpaces(key))); 572 } else { 573 String evalue = entities.unescape(value); 574 if (!evalue.equals(value)) { 575 commands.add(new ChangePropertyCommand(p, key, evalue)); 577 if (testError instanceof FixableTestError) { 578 commands.add(testError.getFix()); 579 } else { 580 Collection<? extends OsmPrimitive> primitives = testError.getPrimitives(); 581 for (OsmPrimitive p : primitives) { 582 Map<String, String> tags = p.getKeys(); 583 if (tags == null || tags.isEmpty()) { 584 continue; 585 } 586 587 for (Entry<String, String> prop: tags.entrySet()) { 588 String key = prop.getKey(); 589 String value = prop.getValue(); 590 if (value == null || value.trim().isEmpty()) { 591 commands.add(new ChangePropertyCommand(p, key, null)); 592 } else if (value.startsWith(" ") || value.endsWith(" ")) { 593 commands.add(new ChangePropertyCommand(p, key, Tag.removeWhiteSpaces(value))); 594 } else if (key.startsWith(" ") || key.endsWith(" ")) { 595 commands.add(new ChangePropertyKeyCommand(p, key, Tag.removeWhiteSpaces(key))); 576 596 } else { 577 String replacementKey = spellCheckKeyData.get(key); 578 if (replacementKey != null) { 579 commands.add(new ChangePropertyKeyCommand(p, key, replacementKey)); 597 String evalue = entities.unescape(value); 598 if (!evalue.equals(value)) { 599 commands.add(new ChangePropertyCommand(p, key, evalue)); 600 } else { 601 String replacementKey = spellCheckKeyData.get(key); 602 if (replacementKey != null) { 603 commands.add(new ChangePropertyKeyCommand(p, key, replacementKey)); 604 } 580 605 } 581 606 } … … 596 621 if (testError.getTester() instanceof TagChecker) { 597 622 int code = testError.getCode(); 598 return code == INVALID_KEY || code == EMPTY_VALUES || code == INVALID_SPACE || code == INVALID_KEY_SPACE || code == INVALID_HTML; 623 return code == INVALID_KEY || code == EMPTY_VALUES || code == INVALID_SPACE || 624 code == INVALID_KEY_SPACE || code == INVALID_HTML || code == MISSPELLED_VALUE; 599 625 } 600 626 -
trunk/src/org/openstreetmap/josm/tools/Utils.java
r8429 r8435 40 40 import java.util.Collection; 41 41 import java.util.Collections; 42 import java.util.HashSet; 42 43 import java.util.Iterator; 43 44 import java.util.List; 44 45 import java.util.Locale; 46 import java.util.Set; 45 47 import java.util.concurrent.ExecutorService; 46 48 import java.util.concurrent.Executors; … … 899 901 * @since 5772 900 902 */ 901 public static String strip(String str) { 903 public static String strip(final String str) { 904 return strip(str, null); 905 } 906 907 /** 908 * An alternative to {@link String#trim()} to effectively remove all leading and trailing white characters, including Unicode ones. 909 * @param str The string to strip 910 * @param skipChars additional characters to skip 911 * @return <code>str</code>, without leading and trailing characters, according to 912 * {@link Character#isWhitespace(char)}, {@link Character#isSpaceChar(char)} and skipChars. 913 * @since 8435 914 */ 915 public static String strip(final String str, final String skipChars) { 902 916 if (str == null || str.isEmpty()) { 903 917 return str; 904 918 } 905 int start = 0, end = str.length(); 906 boolean leadingWhite = true; 907 while (leadingWhite && start < end) { 919 // create set with chars to skip 920 Set<Character> skipSet = new HashSet<>(); 921 // '\u200B' (ZERO WIDTH SPACE character) needs to be handled manually because of change in Unicode 6.0 (Java 7, see #8918) 922 skipSet.add('\u200B'); 923 // same for '\uFEFF' (ZERO WIDTH NO-BREAK SPACE) 924 skipSet.add('\uFEFF'); 925 if (skipChars != null) { 926 for (char c : skipChars.toCharArray()) { 927 skipSet.add(c); 928 } 929 } 930 int start = 0; 931 int end = str.length(); 932 boolean leadingSkipChar = true; 933 while (leadingSkipChar && start < end) { 908 934 char c = str.charAt(start); 909 // '\u200B' (ZERO WIDTH SPACE character) needs to be handled manually because of change in Unicode 6.0 (Java 7, see #8918) 910 // same for '\uFEFF' (ZERO WIDTH NO-BREAK SPACE) 911 leadingWhite = (Character.isWhitespace(c) || Character.isSpaceChar(c) || c == '\u200B' || c == '\uFEFF'); 912 if (leadingWhite) { 935 leadingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || skipSet.contains(c); 936 if (leadingSkipChar) { 913 937 start++; 914 938 } 915 939 } 916 boolean trailing White= true;917 while (trailing White&& end > start+1) {940 boolean trailingSkipChar = true; 941 while (trailingSkipChar && end > start+1) { 918 942 char c = str.charAt(end-1); 919 trailing White = (Character.isWhitespace(c) || Character.isSpaceChar(c) || c == '\u200B' || c == '\uFEFF');920 if (trailing White) {943 trailingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || skipSet.contains(c); 944 if (trailingSkipChar) { 921 945 end--; 922 946 }
Note:
See TracChangeset
for help on using the changeset viewer.