Ignore:
Timestamp:
2015-05-31T17:06:27+02:00 (9 years ago)
Author:
Don-vip
Message:

fix #11498 - Warn about obvious misspelled tag values (modified patch by mdk) + javadoc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java

    r8404 r8435  
    3939import org.openstreetmap.josm.data.osm.OsmUtils;
    4040import org.openstreetmap.josm.data.osm.Tag;
     41import org.openstreetmap.josm.data.validation.FixableTestError;
    4142import org.openstreetmap.josm.data.validation.Severity;
    42 import org.openstreetmap.josm.data.validation.Test;
     43import org.openstreetmap.josm.data.validation.Test.TagTest;
    4344import org.openstreetmap.josm.data.validation.TestError;
    4445import org.openstreetmap.josm.data.validation.util.Entities;
     
    5657import org.openstreetmap.josm.tools.GBC;
    5758import org.openstreetmap.josm.tools.MultiMap;
     59import org.openstreetmap.josm.tools.Utils;
    5860
    5961/**
     
    6163 *
    6264 * @author frsantos
     65 * @since 3669
    6366 */
    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";
     67public class TagChecker extends TagTest {
     68
    6869    /** The config file of ignored tags */
    6970    public static final String IGNORE_FILE = "resource://data/validator/ignoretags.cfg";
     
    125126    protected static final int LOW_CHAR_VALUE    = 1210;
    126127    protected static final int LOW_CHAR_KEY      = 1211;
     128    protected static final int MISSPELLED_VALUE  = 1212;
    127129    /** 1250 and up is used by tagcheck */
    128130
     
    324326            for (CheckerData d : checkerData) {
    325327                if (d.match(p, keys)) {
    326                     errors.add( new TestError(this, d.getSeverity(), tr("Suspicious tag/value combinations"),
    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));
    328330                    withErrors.put(p, "TC");
    329331                }
     
    336338            String value = prop.getValue();
    337339            if (checkValues && (containsLow(value)) && !withErrors.contains(p, "ICV")) {
    338                 errors.add( new TestError(this, Severity.WARNING, tr("Tag value contains character with code less than 0x20"),
    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));
    340342                withErrors.put(p, "ICV");
    341343            }
    342344            if (checkKeys && (containsLow(key)) && !withErrors.contains(p, "ICK")) {
    343                 errors.add( new TestError(this, Severity.WARNING, tr("Tag key contains character with code less than 0x20"),
    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));
    345347                withErrors.put(p, "ICK");
    346348            }
    347349            if (checkValues && (value!=null && value.length() > 255) && !withErrors.contains(p, "LV")) {
    348                 errors.add( new TestError(this, Severity.ERROR, tr("Tag value longer than allowed"),
    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));
    350352                withErrors.put(p, "LV");
    351353            }
    352354            if (checkKeys && (key!=null && key.length() > 255) && !withErrors.contains(p, "LK")) {
    353                 errors.add( new TestError(this, Severity.ERROR, tr("Tag key longer than allowed"),
    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));
    355357                withErrors.put(p, "LK");
    356358            }
    357359            if (checkValues && (value==null || value.trim().isEmpty()) && !withErrors.contains(p, "EV")) {
    358                 errors.add( new TestError(this, Severity.WARNING, tr("Tags with empty values"),
    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));
    360362                withErrors.put(p, "EV");
    361363            }
    362364            if (checkKeys && spellCheckKeyData.containsKey(key) && !withErrors.contains(p, "IPK")) {
    363                 errors.add( new TestError(this, Severity.WARNING, tr("Invalid property key"),
    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));
    365367                withErrors.put(p, "IPK");
    366368            }
    367369            if (checkKeys && key != null && key.indexOf(' ') >= 0 && !withErrors.contains(p, "IPK")) {
    368                 errors.add( new TestError(this, Severity.WARNING, tr("Invalid white space in property key"),
    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));
    370372                withErrors.put(p, "IPK");
    371373            }
    372374            if (checkValues && value != null && (value.startsWith(" ") || value.endsWith(" ")) && !withErrors.contains(p, "SPACE")) {
    373                 errors.add( new TestError(this, Severity.WARNING, tr("Property values start or end with white space"),
    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));
    375377                withErrors.put(p, "SPACE");
    376378            }
    377379            if (checkValues && value != null && !value.equals(entities.unescape(value)) && !withErrors.contains(p, "HTML")) {
    378                 errors.add( new TestError(this, Severity.OTHER, tr("Property values contain HTML entity"),
    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));
    380382                withErrors.put(p, "HTML");
    381383            }
     
    413415                    if (!keyInPresets) {
    414416                        String i = marktr("Key ''{0}'' not in presets.");
    415                         errors.add( new TestError(this, Severity.OTHER, tr("Presets do not contain property key"),
    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));
    417419                        withErrors.put(p, "UPK");
    418420                    } 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                        }
    423437                    }
    424438                }
     
    435449            }
    436450        }
     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, "-_;:,");
    437458    }
    438459
     
    554575        List<Command> commands = new ArrayList<>(50);
    555576
    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)));
    576596                    } 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                            }
    580605                        }
    581606                    }
     
    596621        if (testError.getTester() instanceof TagChecker) {
    597622            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;
    599625        }
    600626
Note: See TracChangeset for help on using the changeset viewer.