Ticket #21423: 21423.patch

File 21423.patch, 48.8 KB (added by taylor.smock, 3 years ago)

Ensure error codes are unique via a (currently) optional method, errorCodes. The optional method should (eventually) become a hard requirement.

  • src/org/openstreetmap/josm/data/validation/OsmValidator.java

     
    163163    public static void addTest(Class<? extends Test> testClass) {
    164164        allTests.add(testClass);
    165165        try {
    166             allTestsMap.put(testClass.getName(), testClass.getConstructor().newInstance());
     166            Test test = testClass.getConstructor().newInstance();
     167            verifyErrorCodes(test);
     168            allTestsMap.put(testClass.getName(), test);
    167169        } catch (ReflectiveOperationException e) {
    168170            Logging.error(e);
    169171        }
     
    170172    }
    171173
    172174    /**
     175     * Verify that test codes do not overlap
     176     * @param test The test to check
     177     */
     178    private static void verifyErrorCodes(Test test) {
     179        int[] codeRange = test.errorCodes();
     180        if (Arrays.stream(codeRange).distinct().count() != codeRange.length) {
     181            // This should eventually become an exception on or after 2023-01-01.
     182            Logging.error("Duplicate test codes in {0}", test.getName());
     183        }
     184        for (Test other : allTestsMap.values()) {
     185            int[] otherCodeRange = other.errorCodes();
     186            int[] duplicates = Arrays.stream(codeRange)
     187                    .filter(code -> Arrays.stream(otherCodeRange).anyMatch(otherCode -> otherCode == code)).toArray();
     188            if (duplicates.length > 0) {
     189                // This should eventually become an exception on or after 2023-01-01.
     190                Logging.error("Conflicting test codes: {0} and {1} have {2}",
     191                        test.getName(), other.getName(), Arrays.toString(duplicates));
     192            }
     193        }
     194    }
     195
     196    /**
    173197     * Removes a test from the list of available tests. This will not remove
    174198     * core tests.
    175199     *
  • src/org/openstreetmap/josm/data/validation/Test.java

     
    3939 *
    4040 * @author frsantos
    4141 */
    42 public class Test implements OsmPrimitiveVisitor {
     42public abstract class Test implements OsmPrimitiveVisitor {
    4343
    4444    protected static final Predicate<OsmPrimitive> IN_DOWNLOADED_AREA = new NotOutsideDataSourceArea();
    4545    protected static final Predicate<OsmPrimitive> IN_DOWNLOADED_AREA_STRICT = new InDataSourceArea(true);
     
    383383    public Object getSource() {
    384384        return "Java: " + this.getClass().getName();
    385385    }
     386
     387    /**
     388     * Get the error codes for this check. Used to ensure that this test does not conflict with other tests.
     389     * See #21423.
     390     * @return The error codes for this check. This array should never be modified. This is a candidate for frozen arrays.
     391     * @since xxx (not yet mandatory)
     392     */
     393    protected int[] errorCodes() {
     394        return new int[0];
     395    }
    386396}
  • src/org/openstreetmap/josm/data/validation/tests/Addresses.java

     
    5454    protected static final int HOUSE_NUMBER_TOO_FAR = 2605;
    5555    protected static final int OBSOLETE_RELATION = 2606;
    5656
     57    private static final int[] ERROR_CODES = {
     58            HOUSE_NUMBER_WITHOUT_STREET,
     59            DUPLICATE_HOUSE_NUMBER,
     60            MULTIPLE_STREET_NAMES,
     61            MULTIPLE_STREET_RELATIONS,
     62            HOUSE_NUMBER_TOO_FAR,
     63            OBSOLETE_RELATION
     64    };
     65
    5766    protected static final DoubleProperty MAX_DUPLICATE_DISTANCE = new DoubleProperty("validator.addresses.max_duplicate_distance", 200.0);
    5867    protected static final DoubleProperty MAX_STREET_DISTANCE = new DoubleProperty("validator.addresses.max_street_distance", 200.0);
    5968
     
    522531        return testError.getCode() == OBSOLETE_RELATION;
    523532    }
    524533
     534    @Override
     535    protected int[] errorCodes() {
     536        return ERROR_CODES;
     537    }
     538
    525539}
  • src/org/openstreetmap/josm/data/validation/tests/ApiCapabilitiesTest.java

     
    5555                    .build());
    5656        }
    5757    }
     58
     59    @Override
     60    protected int[] errorCodes() {
     61        return new int[] {MAX_WAY_NODES_ERROR};
     62    }
    5863}
  • src/org/openstreetmap/josm/data/validation/tests/BarriersEntrances.java

     
    3939                    .build());
    4040        }
    4141    }
     42
     43    @Override
     44    protected int[] errorCodes() {
     45        return new int[] {BARRIER_ENTRANCE_WITHOUT_BARRIER};
     46    }
    4247}
  • src/org/openstreetmap/josm/data/validation/tests/Coastlines.java

     
    3838    protected static final int UNCONNECTED_COASTLINE = 903;
    3939    protected static final int WRONG_ORDER_COASTLINE = 904;
    4040
     41    private static final int[] ERROR_CODES = {UNORDERED_COASTLINE, REVERSED_COASTLINE, UNCONNECTED_COASTLINE, WRONG_ORDER_COASTLINE};
     42
    4143    private List<Way> coastlineWays;
    4244
    4345    /**
     
    277279
    278280        return false;
    279281    }
     282
     283    @Override
     284    protected int[] errorCodes() {
     285        return ERROR_CODES;
     286    }
    280287}
  • src/org/openstreetmap/josm/data/validation/tests/ConditionalKeys.java

     
    2424 */
    2525public class ConditionalKeys extends Test.TagTest {
    2626
     27    private static final int ERROR_WRONG_SYNTAX = 3201;
     28    private static final int ERROR_SYNTAX_ERROR = 3202;
     29    private static final int[] ERROR_CODES = {ERROR_WRONG_SYNTAX, ERROR_SYNTAX_ERROR};
     30
    2731    private final OpeningHourTest openingHourTest = new OpeningHourTest();
    2832    private static final Set<String> RESTRICTION_TYPES = new HashSet<>(Arrays.asList("oneway", "toll", "noexit", "maxspeed", "minspeed",
    2933            "maxstay", "maxweight", "maxaxleload", "maxheight", "maxwidth", "maxlength", "overtaking", "maxgcweight", "maxgcweightrating",
     
    5660        openingHourTest.initialize();
    5761    }
    5862
     63    @Override
     64    protected int[] errorCodes() {
     65        return ERROR_CODES;
     66    }
     67
    5968    /**
    6069     * Check if the key is a key for an access restriction
    6170     * @param part The key (or the restriction part of it, e.g. for lanes)
     
    228237                return;
    229238            }
    230239            if (!isKeyValid(key)) {
    231                 errors.add(TestError.builder(this, Severity.WARNING, 3201)
     240                errors.add(TestError.builder(this, Severity.WARNING, ERROR_WRONG_SYNTAX)
    232241                        .message(tr("Wrong syntax in {0} key", key))
    233242                        .primitives(p)
    234243                        .build());
     
    236245            }
    237246            final String error = validateValue(key, value);
    238247            if (error != null) {
    239                 errors.add(TestError.builder(this, Severity.WARNING, 3202)
     248                errors.add(TestError.builder(this, Severity.WARNING, ERROR_SYNTAX_ERROR)
    240249                        .message(tr("Error in {0} value: {1}", key, error))
    241250                        .primitives(p)
    242251                        .build());
  • src/org/openstreetmap/josm/data/validation/tests/ConnectivityRelations.java

     
    5050
    5151    protected static final int CONNECTIVITY_IMPLIED = 3908;
    5252
     53    private static final int[] ERROR_CODES = {
     54            INCONSISTENT_LANE_COUNT,
     55            UNKNOWN_CONNECTIVITY_ROLE,
     56            NO_CONNECTIVITY_TAG,
     57            MALFORMED_CONNECTIVITY_TAG,
     58            MISSING_COMMA_CONNECTIVITY_TAG,
     59            TOO_MANY_ROLES,
     60            MISSING_ROLE,
     61            MEMBER_MISSING_LANES,
     62            CONNECTIVITY_IMPLIED
     63    };
     64
    5365    private static final String CONNECTIVITY_TAG = "connectivity";
    5466    private static final String VIA = "via";
    5567    private static final String TO = "to";
     
    140152        }
    141153    }
    142154
     155    @Override
     156    protected int[] errorCodes() {
     157        return ERROR_CODES;
     158    }
     159
    143160    /**
    144161     * Compare lane tags of members to values in the {@code connectivity} tag of the relation
    145162     *
  • src/org/openstreetmap/josm/data/validation/tests/CrossingWays.java

     
    111111        }
    112112
    113113        @Override
     114        protected int[] errorCodes() {
     115            return new int[] {CROSSING_WAYS};
     116        }
     117
     118        @Override
    114119        boolean ignoreWaySegmentCombination(Way w1, Way w2) {
    115120            if (w1 == w2)
    116121                return true;
     
    261266                    visit(w);
    262267            }
    263268        }
     269
     270        @Override
     271        protected int[] errorCodes() {
     272            return new int[] {CROSSING_BOUNDARIES};
     273        }
    264274    }
    265275
    266276    /**
     
    281291        boolean ignoreWaySegmentCombination(Way w1, Way w2) {
    282292            return false; // we should not get here
    283293        }
     294
     295        @Override
     296        protected int[] errorCodes() {
     297            return new int[] {CROSSING_SELF};
     298        }
    284299    }
    285300
    286301    /**
  • src/org/openstreetmap/josm/data/validation/tests/DirectionNodes.java

     
    2727    private static final int NO_WAY_CODE = 4002;
    2828    private static final int NO_SUITABLE_WAY = 4003;
    2929
     30    private static final int[] ERROR_CODES = {
     31            MULTIPLE_WAYS_CODE,
     32            END_NODE_CODE,
     33            NO_WAY_CODE,
     34            NO_SUITABLE_WAY
     35    };
     36
    3037    private static final String INVALID_USE_MSG = tr("Invalid usage of direction on node");
    3138    private static final String DISPUTED_USE_MSG = tr("Disputed usage of direction on node");
    3239
     
    4956        }
    5057    }
    5158
     59    @Override
     60    protected int[] errorCodes() {
     61        return ERROR_CODES;
     62    }
     63
    5264    private static boolean isSuitableParentWay(Way w) {
    5365        return w.hasKey("highway", "railway", "waterway") || w.hasTag("man_made", "pipeline");
    5466    }
  • src/org/openstreetmap/josm/data/validation/tests/DuplicateNode.java

     
    101101    protected static final int DUPLICATE_NODE_RAILWAY = 16;
    102102    protected static final int DUPLICATE_NODE_WATERWAY = 17;
    103103
     104    private static final int[] ERROR_CODES = {
     105            DUPLICATE_NODE,
     106            DUPLICATE_NODE_MIXED,
     107            DUPLICATE_NODE_OTHER,
     108            DUPLICATE_NODE_BUILDING,
     109            DUPLICATE_NODE_BOUNDARY,
     110            DUPLICATE_NODE_HIGHWAY,
     111            DUPLICATE_NODE_LANDUSE,
     112            DUPLICATE_NODE_NATURAL,
     113            DUPLICATE_NODE_POWER,
     114            DUPLICATE_NODE_RAILWAY,
     115            DUPLICATE_NODE_WATERWAY
     116    };
     117
    104118    private static final String[] TYPES = {
    105119            "none", HIGHWAY, RAILWAY, WATERWAY, "boundary", "power", "natural", "landuse", "building"};
    106120
     
    305319                && Command.checkOutlyingOrIncompleteOperation(testError.getPrimitives(), null) == Command.IS_OK;
    306320        // everything else is ok to merge
    307321    }
     322
     323    @Override
     324    protected int[] errorCodes() {
     325        return ERROR_CODES;
     326    }
    308327}
  • src/org/openstreetmap/josm/data/validation/tests/DuplicateRelation.java

     
    175175    /** Code number of relation with same members error */
    176176    protected static final int SAME_RELATION = 1902;
    177177
     178    private static final int[] ERROR_CODES = {DUPLICATE_RELATION, SAME_RELATION};
     179
    178180    /** MultiMap of all relations */
    179181    private MultiMap<RelationPair, OsmPrimitive> relations;
    180182
     
    315317                .limit(2)
    316318                .count() <= 1;
    317319    }
     320
     321    @Override
     322    protected int[] errorCodes() {
     323        return ERROR_CODES;
     324    }
    318325}
  • src/org/openstreetmap/josm/data/validation/tests/DuplicateWay.java

     
    9595    /** Test identification for identical ways (coordinates only). */
    9696    protected static final int SAME_WAY = 1402;
    9797
     98    private static final int[] ERROR_CODES = {DUPLICATE_WAY, SAME_WAY};
     99
    98100    /** Bag of all ways */
    99101    private MultiMap<WayPair, OsmPrimitive> ways;
    100102
     
    318320                .count();
    319321        return waysWithRelations <= 1;
    320322    }
     323
     324    @Override
     325    protected int[] errorCodes() {
     326        return ERROR_CODES;
     327    }
    321328}
  • src/org/openstreetmap/josm/data/validation/tests/DuplicatedWayNodes.java

     
    8181    public boolean isFixable(TestError testError) {
    8282        return testError.getTester() instanceof DuplicatedWayNodes;
    8383    }
     84
     85    @Override
     86    protected int[] errorCodes() {
     87        return new int[] {DUPLICATE_WAY_NODE};
     88    }
    8489}
  • src/org/openstreetmap/josm/data/validation/tests/Highways.java

     
    3838    protected static final int SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_MAXSPEED = 2705;
    3939    protected static final int SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_HIGHWAY = 2706;
    4040    protected static final int SOURCE_WRONG_LINK = 2707;
     41    private static final int[] ERROR_CODES = {
     42            WRONG_ROUNDABOUT_HIGHWAY,
     43            MISSING_PEDESTRIAN_CROSSING,
     44            SOURCE_MAXSPEED_UNKNOWN_COUNTRY_CODE,
     45            SOURCE_MAXSPEED_UNKNOWN_CONTEXT,
     46            SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_MAXSPEED,
     47            SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_HIGHWAY,
     48            SOURCE_WRONG_LINK
     49    };
    4150
    4251    protected static final String SOURCE_MAXSPEED = "source:maxspeed";
    4352
     
    109118        }
    110119    }
    111120
     121    @Override
     122    protected int[] errorCodes() {
     123        return ERROR_CODES;
     124    }
     125
    112126    private void testWrongRoundabout(Way w) {
    113127        Map<String, List<Way>> map = new HashMap<>();
    114128        // Count all highways (per type) connected to this roundabout, except correct links
  • src/org/openstreetmap/josm/data/validation/tests/InternetTags.java

     
    2828    public static final int INVALID_URL = 3301;
    2929    /** Error code for an invalid e-mail */
    3030    public static final int INVALID_EMAIL = 3302;
     31    private static final int[] ERROR_CODES = {INVALID_URL, INVALID_EMAIL};
    3132
    3233    /**
    3334     * List of keys subject to URL validation.
     
    129130            }
    130131        });
    131132    }
     133
     134    @Override
     135    protected int[] errorCodes() {
     136        return ERROR_CODES;
     137    }
    132138}
  • src/org/openstreetmap/josm/data/validation/tests/Lanes.java

     
    2020 * @since 6592
    2121 */
    2222public class Lanes extends Test.TagTest {
     23    private static final int ERROR_LANE_COUNT_MISMATCH = 3100;
     24    private static final int ERROR_LANE_COUNT_MISMATCH_FORWARD_BACKWARD = 3101;
     25    private static final int[] ERROR_CODES = {ERROR_LANE_COUNT_MISMATCH, ERROR_LANE_COUNT_MISMATCH_FORWARD_BACKWARD};
    2326
    2427    private static final String[] BLACKLIST = {
    2528        "source:lanes",
     
    5053
    5154        if (lanesCount.size() > 1) {
    5255            // if not all numbers are the same
    53             errors.add(TestError.builder(this, Severity.WARNING, 3100)
     56            errors.add(TestError.builder(this, Severity.WARNING, ERROR_LANE_COUNT_MISMATCH)
    5457                    .message(message)
    5558                    .primitives(p)
    5659                    .build());
     
    5861            // ensure that lanes <= *:lanes
    5962            try {
    6063                if (Integer.parseInt(p.get(lanesKey)) > lanesCount.iterator().next()) {
    61                     errors.add(TestError.builder(this, Severity.WARNING, 3100)
     64                    errors.add(TestError.builder(this, Severity.WARNING, ERROR_LANE_COUNT_MISMATCH)
    6265                            .message(tr("Number of {0} greater than {1}", lanesKey, "*:" + lanesKey))
    6366                            .primitives(p)
    6467                            .build());
     
    7679        final String backward = Utils.firstNonNull(p.get("lanes:backward"), "0");
    7780        try {
    7881        if (Integer.parseInt(lanes) < Integer.parseInt(forward) + Integer.parseInt(backward)) {
    79             errors.add(TestError.builder(this, Severity.WARNING, 3101)
     82            errors.add(TestError.builder(this, Severity.WARNING, ERROR_LANE_COUNT_MISMATCH_FORWARD_BACKWARD)
    8083                    .message(tr("Number of {0} greater than {1}", tr("{0}+{1}", "lanes:forward", "lanes:backward"), "lanes"))
    8184                    .primitives(p)
    8285                    .build());
     
    98101    public boolean isPrimitiveUsable(OsmPrimitive p) {
    99102        return p.isTagged() && p instanceof Way && p.hasTag("highway") && super.isPrimitiveUsable(p);
    100103    }
     104
     105    @Override
     106    protected int[] errorCodes() {
     107        return ERROR_CODES;
     108    }
    101109}
  • src/org/openstreetmap/josm/data/validation/tests/LongSegment.java

     
    7878        testWay(w);
    7979    }
    8080
     81    @Override
     82    protected int[] errorCodes() {
     83        return new int[] {LONG_SEGMENT};
     84    }
     85
    8186    private void testWay(Way w) {
    8287        for (int i = 0; i < w.getNodesCount() - 1; i++) {
    8388            visitWaySegment(w, i);
  • src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

     
    6464    static final boolean ALL_TESTS = true;
    6565    static final boolean ONLY_SELECTED_TESTS = false;
    6666
     67    static final int ERROR_MAPCSS = 3000;
     68
    6769    /**
    6870     * Cached version of {@link ValidatorPrefHelper#PREF_OTHER}, see #20745.
    6971     */
     
    384386        visit(selection, null);
    385387    }
    386388
     389    @Override
     390    protected int[] errorCodes() {
     391        return new int[] {ERROR_MAPCSS};
     392    }
     393
    387394    /**
    388395     * Execute the rules from the URLs matching the given predicate.
    389396     * @param selection collection of primitives
  • src/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerRule.java

     
    388388            final String description1 = group == null ? description : group;
    389389            final String description2 = group == null ? null : description;
    390390            final String selector = matchingSelector.toString();
    391             TestError.Builder errorBuilder = TestError.builder(tester, getSeverity(), 3000)
     391            TestError.Builder errorBuilder = TestError.builder(tester, getSeverity(), MapCSSTagChecker.ERROR_MAPCSS)
    392392                    .messageWithManuallyTranslatedDescription(description1, description2, selector);
    393393            if (fix != null) {
    394394                errorBuilder.fix(() -> fix);
     
    398398            } else if (env.children != null) {
    399399                for (IPrimitive c : env.children) {
    400400                    if (c instanceof OsmPrimitive) {
    401                         errorBuilder = TestError.builder(tester, getSeverity(), 3000)
     401                        errorBuilder = TestError.builder(tester, getSeverity(), MapCSSTagChecker.ERROR_MAPCSS)
    402402                                .messageWithManuallyTranslatedDescription(description1, description2, selector);
    403403                        if (fix != null) {
    404404                            errorBuilder.fix(() -> fix);
  • src/org/openstreetmap/josm/data/validation/tests/MultipolygonTest.java

     
    7777    /** Incomplete multipolygon was modified */
    7878    public static final int MODIFIED_INCOMPLETE = 1618;
    7979
     80    private static final int[] ERROR_CODES = {
     81            WRONG_MEMBER_TYPE,
     82            WRONG_MEMBER_ROLE,
     83            NON_CLOSED_WAY,
     84            INNER_WAY_OUTSIDE,
     85            CROSSING_WAYS,
     86            OUTER_STYLE_MISMATCH,
     87            INNER_STYLE_MISMATCH,
     88            NO_STYLE,
     89            OUTER_STYLE,
     90            REPEATED_MEMBER_SAME_ROLE,
     91            REPEATED_MEMBER_DIFF_ROLE,
     92            EQUAL_RINGS,
     93            RINGS_SHARE_NODES,
     94            MODIFIED_INCOMPLETE
     95    };
     96
    8097    private static final int FOUND_INSIDE = 1;
    8198    private static final int FOUND_OUTSIDE = 2;
    8299
     
    769786        return testError.getCode() == REPEATED_MEMBER_SAME_ROLE;
    770787    }
    771788
     789    @Override
     790    protected int[] errorCodes() {
     791        return ERROR_CODES;
     792    }
     793
    772794    /**
    773795     * Find nesting levels of polygons. Logic taken from class MultipolygonBuilder, uses different structures.
    774796     */
  • src/org/openstreetmap/josm/data/validation/tests/NameMismatch.java

     
    3535public class NameMismatch extends Test.TagTest {
    3636    protected static final int NAME_MISSING = 1501;
    3737    protected static final int NAME_TRANSLATION_MISSING = 1502;
     38    private static final int[] ERROR_CODES = {NAME_MISSING, NAME_TRANSLATION_MISSING};
    3839    private static final Pattern NAME_SPLIT_PATTERN = Pattern.compile(" - ");
    3940
    4041    private static final List<String> EXCLUSIONS = Arrays.asList(
     
    121122        return p.isTagged() && super.isPrimitiveUsable(p);
    122123    }
    123124
     125    @Override
     126    protected int[] errorCodes() {
     127        return ERROR_CODES;
     128    }
     129
    124130}
  • src/org/openstreetmap/josm/data/validation/tests/OpeningHourTest.java

     
    3939 */
    4040public class OpeningHourTest extends TagTest {
    4141
     42    private static final int ERROR_OPENING_HOURS_SYNTAX = 2901;
    4243    private static final Collection<String> KEYS_TO_CHECK = Arrays.asList("opening_hours", "collection_times", "service_times");
    4344    private static final BooleanProperty PREF_STRICT_MODE =
    4445            new BooleanProperty(ValidatorPrefHelper.PREFIX + "." + OpeningHourTest.class.getSimpleName() + "." + "strict", false);
     
    6364     * @return The real test error given to JOSM validator. Can be fixable or not if a prettified values has been determined.
    6465     */
    6566    private TestError createTestError(Severity severity, String message, String key, String value, String prettifiedValue, OsmPrimitive p) {
    66         final TestError.Builder error = TestError.builder(this, severity, 2901)
     67        final TestError.Builder error = TestError.builder(this, severity, ERROR_OPENING_HOURS_SYNTAX)
    6768                .message(tr("Opening hours syntax"), message) // todo obtain English message for ignore functionality
    6869                .primitives(p != null ? new OsmPrimitive[] {p} : new OsmPrimitive[] {});
    6970        if (p == null || prettifiedValue == null || prettifiedValue.equals(value)) {
     
    161162        PREF_STRICT_MODE.put(checkboxStrictMode.isSelected());
    162163        return false;
    163164    }
     165
     166    @Override
     167    protected int[] errorCodes() {
     168        return new int[] {ERROR_OPENING_HOURS_SYNTAX};
     169    }
    164170}
  • src/org/openstreetmap/josm/data/validation/tests/OverlappingWays.java

     
    6363    protected static final int OVERLAPPING_HIGHWAY_LINEAR_WAY = 131;
    6464    protected static final int OVERLAPPING_RAILWAY_LINEAR_WAY = 132;
    6565    protected static final int OVERLAPPING_WATERWAY_LINEAR_WAY = 133;
     66    private static final int[] ERROR_CODES = {
     67            OVERLAPPING_HIGHWAY,
     68            OVERLAPPING_RAILWAY,
     69            OVERLAPPING_WAY,
     70            OVERLAPPING_WATERWAY,
     71            OVERLAPPING_HIGHWAY_AREA,
     72            OVERLAPPING_RAILWAY_AREA,
     73            OVERLAPPING_WAY_AREA,
     74            OVERLAPPING_WATERWAY_AREA,
     75            DUPLICATE_WAY_SEGMENT,
     76            OVERLAPPING_HIGHWAY_LINEAR_WAY,
     77            OVERLAPPING_RAILWAY_LINEAR_WAY,
     78            OVERLAPPING_WATERWAY_LINEAR_WAY
     79    };
    6680
    6781    protected static final ListProperty IGNORED_KEYS = new ListProperty(
    6882            "overlapping-ways.ignored-keys", Arrays.asList(
     
    285299            lastN = n;
    286300        }
    287301    }
     302
     303    @Override
     304    protected int[] errorCodes() {
     305        return ERROR_CODES;
     306    }
    288307}
  • src/org/openstreetmap/josm/data/validation/tests/PowerLines.java

     
    3333    /** Test identifier */
    3434    protected static final int POWER_LINES = 2501;
    3535    protected static final int POWER_CONNECTION = 2502;
     36    private static final int[] ERROR_CODES = {POWER_LINES, POWER_CONNECTION};
    3637
    3738    /** Values for {@code power} key interpreted as power lines */
    3839    static final Collection<String> POWER_LINE_TAGS = Arrays.asList("line", "minor_line");
     
    111112    }
    112113
    113114    @Override
     115    protected int[] errorCodes() {
     116        return ERROR_CODES;
     117    }
     118
     119    @Override
    114120    public void startTest(ProgressMonitor progressMonitor) {
    115121        super.startTest(progressMonitor);
    116122        clearCollections();
  • src/org/openstreetmap/josm/data/validation/tests/PublicTransportRouteTest.java

     
    2222 * Tests for <a href="https://wiki.openstreetmap.org/wiki/Proposed_features/Public_Transport">public transport routes</a>.
    2323 */
    2424public class PublicTransportRouteTest extends Test {
     25    private static final int ERROR_BAD_ROLE = 3601;
     26    private static final int ERROR_GAP = 3602;
     27    private static final int ERROR_STOP_NOT_IN_ROUTE = 3603;
     28    private static final int[] ERROR_CODES = {ERROR_BAD_ROLE, ERROR_GAP, ERROR_STOP_NOT_IN_ROUTE};
    2529
    2630    private final WayConnectionTypeCalculator connectionTypeCalculator = new WayConnectionTypeCalculator();
    2731
     
    4650        final Set<Node> routeNodes = new HashSet<>();
    4751        for (RelationMember member : r.getMembers()) {
    4852            if (member.hasRole("forward", "backward", "alternate")) {
    49                 errors.add(TestError.builder(this, Severity.ERROR, 3601)
     53                errors.add(TestError.builder(this, Severity.ERROR, ERROR_BAD_ROLE)
    5054                        .message(tr("Route relation contains a ''{0}'' role", "forward/backward/alternate"))
    5155                        .primitives(r)
    5256                        .build());
     
    6872                    || link.direction == null
    6973                    || WayConnectionType.Direction.NONE == link.direction;
    7074            if (hasError) {
    71                 errors.add(TestError.builder(this, Severity.WARNING, 3602)
     75                errors.add(TestError.builder(this, Severity.WARNING, ERROR_GAP)
    7276                        .message(tr("Route relation contains a gap"))
    7377                        .primitives(r)
    7478                        .build());
     
    8084            if (member.hasRole("stop", "stop_exit_only", "stop_entry_only")
    8185                    && OsmPrimitiveType.NODE == member.getType()
    8286                    && !routeNodes.contains(member.getNode())) {
    83                 errors.add(TestError.builder(this, Severity.WARNING, 3603)
     87                errors.add(TestError.builder(this, Severity.WARNING, ERROR_STOP_NOT_IN_ROUTE)
    8488                        .message(tr("Stop position not part of route"))
    8589                        .primitives(member.getMember(), r)
    8690                        .build());
     
    9397        connectionTypeCalculator.clear();
    9498        super.clear();
    9599    }
     100
     101    @Override
     102    protected int[] errorCodes() {
     103        return ERROR_CODES;
     104    }
    96105}
  • src/org/openstreetmap/josm/data/validation/tests/RelationChecker.java

     
    6868    public static final int RELATION_LOOP    = 1710;
    6969    /** Relation is empty */
    7070    public static final int RELATION_EMPTY   = 1711; // was 1708 up to r18505
     71    private static final int[] ERROR_CODES = {
     72            ROLE_UNKNOWN,
     73            ROLE_EMPTY,
     74            HIGH_COUNT,
     75            LOW_COUNT,
     76            ROLE_MISSING,
     77            RELATION_UNKNOWN,
     78            WRONG_ROLE,
     79            WRONG_TYPE,
     80            RELATION_LOOP,
     81            RELATION_EMPTY
     82    };
    7183    // CHECKSTYLE.ON: SingleSpaceSeparator
    7284
    7385    // see 19312 comment:17
     
    401413    }
    402414
    403415    @Override
     416    protected int[] errorCodes() {
     417        return ERROR_CODES;
     418    }
     419
     420    @Override
    404421    public void taggingPresetsModified() {
    405422        relationpresets.clear();
    406423        initializePresets();
  • src/org/openstreetmap/josm/data/validation/tests/RightAngleBuildingTest.java

     
    2121 * @since 13670
    2222 */
    2323public class RightAngleBuildingTest extends Test {
     24    private static final int ERROR_ALMOST_SQUARE_ANGLE = 3701;
    2425
    2526    /** Maximum angle difference from right angle that is considered as invalid. */
    2627    protected double maxAngleDelta;
     
    4344        List<Pair<Double, Node>> angles = w.getAngles();
    4445        for (Pair<Double, Node> pair: angles) {
    4546            if (checkAngle(pair.a)) {
    46                 TestError.Builder builder = TestError.builder(this, Severity.OTHER, 3701)
     47                TestError.Builder builder = TestError.builder(this, Severity.OTHER, ERROR_ALMOST_SQUARE_ANGLE)
    4748                                                     .message(tr("Building with an almost square angle"))
    4849                                                     .primitives(w)
    4950                                                     .highlight(pair.b);
     
    5455    }
    5556
    5657    @Override
     58    protected int[] errorCodes() {
     59        return new int[]{ERROR_ALMOST_SQUARE_ANGLE};
     60    }
     61
     62    @Override
    5763    public void startTest(ProgressMonitor monitor) {
    5864        super.startTest(monitor);
    5965        maxAngleDelta = Config.getPref().getDouble("validator.RightAngleBuilding.maximumDelta", 10.0);
  • src/org/openstreetmap/josm/data/validation/tests/SelfIntersectingWay.java

     
    6363        }
    6464    }
    6565
     66    @Override
     67    protected int[] errorCodes() {
     68        return new int[]{SELF_INTERSECT};
     69    }
     70
    6671    /**
    6772     * Check if the given way is self-intersecting
    6873     * @param way the way to check
  • src/org/openstreetmap/josm/data/validation/tests/SharpAngles.java

     
    5555        }
    5656    }
    5757
     58    @Override
     59    protected int[] errorCodes() {
     60        return new int[]{SHARP_ANGLES};
     61    }
     62
    5863    /**
    5964     * Check whether or not a way should be checked for sharp angles
    6065     * @param way The way that needs to be checked
  • src/org/openstreetmap/josm/data/validation/tests/SimilarNamedWays.java

     
    109109        }
    110110    }
    111111
     112    @Override
     113    protected int[] errorCodes() {
     114        return new int[]{SIMILAR_NAMED};
     115    }
     116
    112117    /**
    113118     * Add a regular expression rule.
    114119     * @param regExpr the regular expression to search for
  • src/org/openstreetmap/josm/data/validation/tests/TagChecker.java

     
    211211    protected static final int MULTIPOLYGON_MAYBE_NO_AREA       = 1220;
    212212    protected static final int MULTIPOLYGON_SAME_TAG_ON_OUTER   = 1221;
    213213    // CHECKSTYLE.ON: SingleSpaceSeparator
     214    private static final int[] ERROR_CODES = {
     215            EMPTY_VALUES,
     216            INVALID_KEY,
     217            INVALID_VALUE,
     218            FIXME,
     219            INVALID_SPACE,
     220            INVALID_KEY_SPACE,
     221            INVALID_HTML,
     222            LONG_VALUE,
     223            LONG_KEY,
     224            LOW_CHAR_VALUE,
     225            LOW_CHAR_KEY,
     226            MISSPELLED_VALUE,
     227            MISSPELLED_KEY,
     228            MULTIPLE_SPACES,
     229            MISSPELLED_VALUE_NO_FIX,
     230            UNUSUAL_UNICODE_CHAR_VALUE,
     231            INVALID_PRESETS_TYPE,
     232            MULTIPOLYGON_NO_AREA,
     233            MULTIPOLYGON_INCOMPLETE,
     234            MULTIPOLYGON_MAYBE_NO_AREA,
     235            MULTIPOLYGON_SAME_TAG_ON_OUTER
     236    };
    214237
    215238    protected EditableList sourcesList;
    216239
     
    12561279    }
    12571280
    12581281    @Override
     1282    protected int[] errorCodes() {
     1283        return ERROR_CODES;
     1284    }
     1285
     1286    @Override
    12591287    public void taggingPresetsModified() {
    12601288        try {
    12611289            initializeData();
  • src/org/openstreetmap/josm/data/validation/tests/TurnrestrictionTest.java

     
    4444    protected static final int UNKNOWN_RESTRICTION = 1817;
    4545    protected static final int TO_CLOSED_WAY = 1818;
    4646    protected static final int FROM_CLOSED_WAY = 1819;
     47    private static final int[] ERROR_CODES = {
     48            NO_VIA,
     49            NO_FROM,
     50            NO_TO,
     51            MORE_VIA,
     52            MORE_FROM,
     53            MORE_TO,
     54            UNEXPECTED_ROLE,
     55            UNEXPECTED_TYPE,
     56            FROM_VIA_NODE,
     57            TO_VIA_NODE,
     58            FROM_VIA_WAY,
     59            TO_VIA_WAY,
     60            MIX_VIA,
     61            UNCONNECTED_VIA,
     62            SUPERFLUOUS,
     63            FROM_EQUALS_TO,
     64            UNKNOWN_RESTRICTION,
     65            TO_CLOSED_WAY,
     66            FROM_CLOSED_WAY
     67    };
    4768
    4869    private static final List<String> SUPPORTED_RESTRICTIONS = Arrays.asList(
    4970            "no_right_turn", "no_left_turn", "no_u_turn", "no_straight_on",
     
    303324        }
    304325    }
    305326
     327    @Override
     328    protected int[] errorCodes() {
     329        return ERROR_CODES;
     330    }
     331
    306332    private static boolean isFullOneway(Way w) {
    307333        return w.isOneway() != 0 && !w.hasTag("oneway:bicycle", "no");
    308334    }
  • src/org/openstreetmap/josm/data/validation/tests/UnclosedWays.java

     
    140140        }
    141141    }
    142142
     143    private static final int CODE_NATURAL = 1101;
     144    private static final int CODE_LANDUSE = 1102;
     145    private static final int CODE_AMENITY = 1103;
     146    private static final int CODE_SPORT = 1104;
     147    private static final int CODE_TOURISM = 1105;
     148    private static final int CODE_SHOP = 1106;
     149    private static final int CODE_LEISURE = 1107;
     150    private static final int CODE_WATERWAY = 1108;
     151    private static final int CODE_BOUNDARY = 1109;
     152    private static final int CODE_AREA_HIGHWAY = 1110;
     153    private static final int CODE_PLACE = 1111;
     154    private static final int CODE_BUILDING = 1120;
     155    private static final int CODE_AREA = 1130;
     156    private static final int CODE_AREA_OTHER = 1131;
     157    private static final int[] ERROR_CODES = {
     158            CODE_NATURAL,
     159            CODE_LANDUSE,
     160            CODE_AMENITY,
     161            CODE_SPORT,
     162            CODE_TOURISM,
     163            CODE_SHOP,
     164            CODE_LEISURE,
     165            CODE_WATERWAY,
     166            CODE_BOUNDARY,
     167            CODE_AREA_HIGHWAY,
     168            CODE_PLACE,
     169            CODE_BUILDING,
     170            CODE_AREA,
     171            CODE_AREA_OTHER
     172    };
     173
    143174    private static final UnclosedWaysCheck[] checks = {
    144175        // CHECKSTYLE.OFF: SingleSpaceSeparator
    145176        // list contains natural tag allowed on unclosed ways as well as those only allowed on nodes to avoid
    146177        // duplicate warnings
    147         new UnclosedWaysCheck(1101, "natural", marktr("natural type {0}"),
     178        new UnclosedWaysCheck(CODE_NATURAL, "natural", marktr("natural type {0}"),
    148179            new HashSet<>(Arrays.asList("arete", "bay", "cave", "cliff", "coastline", "earth_bank", "gorge", "gully",
    149180                    "mountain_range", "peak", "ridge", "saddle", "strait", "tree", "tree_row", "valley", "volcano"))),
    150181
    151         new UnclosedWaysCheck(1102, "landuse", marktr("landuse type {0}")),
    152         new UnclosedWaysCheck(1103, "amenity", marktr("amenity type {0}"),
     182        new UnclosedWaysCheck(CODE_LANDUSE, "landuse", marktr("landuse type {0}")),
     183        new UnclosedWaysCheck(CODE_AMENITY, "amenity", marktr("amenity type {0}"),
    153184                new HashSet<>(Arrays.asList("bench", "bicycle_parking", "weighbridge"))),
    154         new UnclosedWaysCheck(1104, "sport",     marktr("sport type {0}"),
     185        new UnclosedWaysCheck(CODE_SPORT, "sport",     marktr("sport type {0}"),
    155186                new HashSet<>(Arrays.asList("water_slide", "climbing", "skiing", "toboggan", "bobsleigh", "karting", "motor", "motocross",
    156187                            "cycling", "running"))),
    157         new UnclosedWaysCheck(1105, "tourism",   marktr("tourism type {0}"),
     188        new UnclosedWaysCheck(CODE_TOURISM, "tourism",   marktr("tourism type {0}"),
    158189                new HashSet<>(Arrays.asList("attraction", "artwork"))),
    159         new UnclosedWaysCheck(1106, "shop",      marktr("shop type {0}")),
    160         new UnclosedWaysCheck(1107, "leisure",   marktr("leisure type {0}"),
     190        new UnclosedWaysCheck(CODE_SHOP, "shop",      marktr("shop type {0}")),
     191        new UnclosedWaysCheck(CODE_LEISURE, "leisure",   marktr("leisure type {0}"),
    161192                new HashSet<>(Arrays.asList("track", "slipway", "barefoot"))),
    162         new UnclosedWaysCheck(1108, "waterway",  marktr("waterway type {0}"),
    163                 new HashSet<>(Arrays.asList("riverbank")), false),
    164         new UnclosedWaysCheck(1109, "boundary", marktr("boundary type {0}")),
    165         new UnclosedWaysCheck(1110, "area:highway", marktr("area:highway type {0}")),
    166         new UnclosedWaysCheck(1111, "place", marktr("place type {0}")),
    167         new UnclosedWaysBooleanCheck(1120, "building", marktr("building")),
    168         new UnclosedWaysBooleanCheck(1130, "area",     marktr("area")),
     193        new UnclosedWaysCheck(CODE_WATERWAY, "waterway",  marktr("waterway type {0}"),
     194                new HashSet<>(Collections.singleton("riverbank")), false),
     195        new UnclosedWaysCheck(CODE_BOUNDARY, "boundary", marktr("boundary type {0}")),
     196        new UnclosedWaysCheck(CODE_AREA_HIGHWAY, "area:highway", marktr("area:highway type {0}")),
     197        new UnclosedWaysCheck(CODE_PLACE, "place", marktr("place type {0}")),
     198        new UnclosedWaysBooleanCheck(CODE_BUILDING, "building", marktr("building")),
     199        new UnclosedWaysBooleanCheck(CODE_AREA, "area",     marktr("area")),
    169200        // 1131: Area style way is not closed
    170201        // CHECKSTYLE.ON: SingleSpaceSeparator
    171202    };
     
    196227        }
    197228        // code 1131: other area style ways
    198229        if (ElemStyles.hasOnlyAreaElements(w) && !w.getNodes().isEmpty()) {
    199             errors.add(TestError.builder(this, Severity.WARNING, 1131)
     230            errors.add(TestError.builder(this, Severity.WARNING, CODE_AREA_OTHER)
    200231                    .message(tr("Unclosed way"), marktr("Area style way is not closed"), new Object())
    201232                    .primitives(w)
    202233                    .highlight(Arrays.asList(w.firstNode(), w.lastNode()))
     
    203234                    .build());
    204235        }
    205236    }
     237
     238    @Override
     239    protected int[] errorCodes() {
     240        return ERROR_CODES;
     241    }
    206242}
  • src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java

     
    635635        }
    636636    }
    637637
     638    @Override
     639    protected int[] errorCodes() {
     640        return new int[] {this.code};
     641    }
     642
    638643    private void addNode(Node n, Set<Node> s) {
    639644        boolean m = middlenodes.contains(n);
    640645        boolean e = endnodes.contains(n);
  • src/org/openstreetmap/josm/data/validation/tests/UntaggedNode.java

     
    2929    protected static final int UNTAGGED_NODE_WATCH = 205;
    3030    protected static final int UNTAGGED_NODE_SOURCE = 206;
    3131    protected static final int UNTAGGED_NODE_OTHER = 207;
     32    private static final int[] ERROR_CODES = {
     33            UNTAGGED_NODE_BLANK,
     34            UNTAGGED_NODE_FIXME,
     35            UNTAGGED_NODE_NOTE,
     36            UNTAGGED_NODE_CREATED_BY,
     37            UNTAGGED_NODE_WATCH,
     38            UNTAGGED_NODE_SOURCE,
     39            UNTAGGED_NODE_OTHER
     40    };
    3241    protected static final String ERROR_MESSAGE = tr("Unconnected nodes without physical tags");
    3342
    3443    /**
     
    121130        }
    122131        return false;
    123132    }
     133
     134    @Override
     135    protected int[] errorCodes() {
     136        return ERROR_CODES;
     137    }
    124138}
  • src/org/openstreetmap/josm/data/validation/tests/UntaggedWay.java

     
    4141    protected static final int UNNAMED_JUNCTION = 305;
    4242    /** Untagged, but commented way error */
    4343    protected static final int COMMENTED_WAY    = 306;
     44
     45    private static final int[] ERROR_CODES = {
     46            EMPTY_WAY,
     47            UNTAGGED_WAY,
     48            UNNAMED_WAY,
     49            ONE_NODE_WAY,
     50            UNNAMED_JUNCTION,
     51            COMMENTED_WAY
     52    };
    4453    // CHECKSTYLE.ON: SingleSpaceSeparator
    4554
    4655    private Set<Way> waysUsedInRelations;
     
    177186    }
    178187
    179188    @Override
     189    protected int[] errorCodes() {
     190        return ERROR_CODES;
     191    }
     192
     193    @Override
    180194    public Command fixError(TestError testError) {
    181195        return deletePrimitivesIfNeeded(testError.getPrimitives());
    182196    }
  • src/org/openstreetmap/josm/data/validation/tests/WayConnectedToArea.java

     
    2020 * @since 4682
    2121 */
    2222public class WayConnectedToArea extends Test {
     23    private static final int ERROR_WAY_TERMINATES_ON_AREA = 2301;
    2324
    2425    /**
    2526     * Constructs a new {@code WayConnectedToArea} test.
     
    5051        }
    5152    }
    5253
     54    @Override
     55    protected int[] errorCodes() {
     56        return new int[] {ERROR_WAY_TERMINATES_ON_AREA};
     57    }
     58
    5359    private void testForError(Way w, Node wayNode, OsmPrimitive p) {
    5460        if (wayNode.isOutsideDownloadArea()
    5561                || wayNode.getReferrers().stream().anyMatch(p1 -> p1.hasTag("route", "ferry"))) {
     
    7783            // Avoid "legal" case (see #17036)
    7884            return;
    7985        }
    80         errors.add(TestError.builder(this, Severity.WARNING, 2301)
     86        errors.add(TestError.builder(this, Severity.WARNING, ERROR_WAY_TERMINATES_ON_AREA)
    8187                .message(tr("Way terminates on Area"))
    8288                .primitives(w, p)
    8389                .highlight(wayNode)
  • src/org/openstreetmap/josm/data/validation/tests/WronglyOrderedWays.java

     
    2020    protected static final int WRONGLY_ORDERED_COAST = 1001;
    2121    protected static final int WRONGLY_ORDERED_LAND  = 1003;
    2222    // CHECKSTYLE.ON: SingleSpaceSeparator
     23    private static final int[] ERROR_CODES = {WRONGLY_ORDERED_COAST, WRONGLY_ORDERED_LAND};
    2324
    2425    /**
    2526     * Constructor
     
    4546        }
    4647    }
    4748
     49    @Override
     50    protected int[] errorCodes() {
     51        return ERROR_CODES;
     52    }
     53
    4854    private void reportError(Way w, String msg, int type) {
    4955        errors.add(TestError.builder(this, Severity.WARNING, type)
    5056                .message(msg)