Ticket #17010: 17010-v2.patch

File 17010-v2.patch, 8.5 KB (added by GerdP, 7 years ago)
  • src/org/openstreetmap/josm/data/validation/tests/MultipolygonTest.java

     
    5353    public static final int WRONG_MEMBER_ROLE = 1602;
    5454    /** Multipolygon is not closed */
    5555    public static final int NON_CLOSED_WAY = 1603;
    56     /** No outer way for multipolygon */
    57     public static final int MISSING_OUTER_WAY = 1604;
    5856    /** Multipolygon inner way is outside */
    5957    public static final int INNER_WAY_OUTSIDE = 1605;
    6058    /** Intersection between multipolygon ways */
     
    132130    @Override
    133131    public void visit(Relation r) {
    134132        if (r.isMultipolygon() && r.getMembersCount() > 0) {
    135             checkMembersAndRoles(r);
    136             checkOuterWay(r);
     133            List<TestError> tmpErrors = new ArrayList<>(30);
     134            boolean hasUnexpectedWayRoles = checkMembersAndRoles(r, tmpErrors);
    137135            boolean hasRepeatedMembers = checkRepeatedWayMembers(r);
    138136            // Rest of checks is only for complete multipolygon
    139             if (!hasRepeatedMembers && !r.hasIncompleteMembers()) {
     137            if (!hasUnexpectedWayRoles && !hasRepeatedMembers && !r.hasIncompleteMembers()) {
    140138                Multipolygon polygon = new Multipolygon(r);
    141139                checkStyleConsistency(r, polygon);
    142140                checkGeometryAndRoles(r, polygon);
     141            } else {
     142                // if we are not able to calculate the geometry we report the messages found by simple checks
     143                errors.addAll(tmpErrors);
    143144            }
    144145        }
    145146    }
    146147
    147148    /**
    148      * Checks that multipolygon has at least an outer way:<ul>
    149      * <li>{@link #MISSING_OUTER_WAY}: No outer way for multipolygon</li>
    150      * </ul>
    151      * @param r relation
    152      */
    153     private void checkOuterWay(Relation r) {
    154         for (RelationMember m : r.getMembers()) {
    155             if (m.isWay() && "outer".equals(m.getRole())) {
    156                 return;
    157             }
    158         }
    159         errors.add(TestError.builder(this, Severity.WARNING, MISSING_OUTER_WAY)
    160                 .message(r.isBoundary() ? tr("No outer way for boundary") : tr("No outer way for multipolygon"))
    161                 .primitives(r)
    162                 .build());
    163     }
    164 
    165     /**
    166149     * Various style-related checks:<ul>
    167150     * <li>{@link #NO_STYLE_POLYGON}: Multipolygon relation should be tagged with area tags and not the outer way</li>
    168151     * <li>{@link #INNER_STYLE_MISMATCH}: With the currently used mappaint style the style for inner way equals the multipolygon style</li>
     
    527510            String calculatedRole = (pol.level % 2 == 0) ? "outer" : "inner";
    528511            for (long wayId : pol.outerWay.getWayIds()) {
    529512                RelationMember member = wayMap.get(wayId);
    530                 if (!member.getRole().equals(calculatedRole)) {
     513                if (!calculatedRole.equals(member.getRole())) {
    531514                    errors.add(TestError.builder(this, Severity.ERROR, WRONG_MEMBER_ROLE)
    532515                            .message(RelationChecker.ROLE_VERIF_PROBLEM_MSG,
    533516                                    marktr("Role for ''{0}'' should be ''{1}''"),
     
    704687     * <li>{@link #WRONG_MEMBER_TYPE}: Non-Way in multipolygon</li>
    705688     * </ul>
    706689     * @param r relation
     690     * @param tmpErrors list that will contain found errors
     691     * @return true if ways with roles other than inner, outer or empty where found
    707692     */
    708     private void checkMembersAndRoles(Relation r) {
     693    private boolean checkMembersAndRoles(Relation r, List<TestError> tmpErrors) {
     694        boolean hasUnexpectedWayRole = false;
    709695        for (RelationMember rm : r.getMembers()) {
    710696            if (rm.isWay()) {
    711                 if (!(rm.hasRole("inner", "outer") || !rm.hasRole())) {
    712                     errors.add(TestError.builder(this, Severity.WARNING, WRONG_MEMBER_ROLE)
    713                             .message(tr("No useful role for multipolygon member"))
     697                if (rm.hasRole() && !(rm.hasRole("inner", "outer")))
     698                    hasUnexpectedWayRole = true;
     699                if (!(rm.hasRole("inner", "outer")) || !rm.hasRole()) {
     700                    tmpErrors.add(TestError.builder(this, Severity.ERROR, WRONG_MEMBER_ROLE)
     701                            .message(tr("Role for multipolygon way member should be inner or outer"))
    714702                            .primitives(Arrays.asList(r, rm.getMember()))
    715703                            .build());
    716704                }
    717705            } else {
    718706                if (!r.isBoundary() || !rm.hasRole("admin_centre", "label", "subarea", "land_area")) {
    719                     errors.add(TestError.builder(this, Severity.WARNING, WRONG_MEMBER_TYPE)
     707                    tmpErrors.add(TestError.builder(this, Severity.WARNING, WRONG_MEMBER_TYPE)
    720708                            .message(r.isBoundary() ? tr("Non-Way in boundary") : tr("Non-Way in multipolygon"))
    721709                            .primitives(Arrays.asList(r, rm.getMember()))
    722710                            .build());
     
    723711                }
    724712            }
    725713        }
     714        return hasUnexpectedWayRole;
    726715    }
    727716
    728717    private static Collection<? extends OsmPrimitive> combineRelAndPrimitives(Relation r, Collection<? extends OsmPrimitive> primitives) {
     
    748737        boolean hasDups = false;
    749738        Map<OsmPrimitive, List<RelationMember>> seenMemberPrimitives = new HashMap<>();
    750739        for (RelationMember rm : r.getMembers()) {
     740            if (!rm.isWay())
     741                continue;
    751742            List<RelationMember> list = seenMemberPrimitives.get(rm.getMember());
    752743            if (list == null) {
    753744                list = new ArrayList<>(2);
  • src/org/openstreetmap/josm/data/validation/tests/RelationChecker.java

     
    1818import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    1919import org.openstreetmap.josm.data.osm.Relation;
    2020import org.openstreetmap.josm.data.osm.RelationMember;
     21import org.openstreetmap.josm.data.validation.OsmValidator;
    2122import org.openstreetmap.josm.data.validation.Severity;
    2223import org.openstreetmap.josm.data.validation.Test;
    2324import org.openstreetmap.josm.data.validation.TestError;
     25import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    2426import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
    2527import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItem;
    2628import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetType;
     
    6062     * @since 6731
    6163     */
    6264    public static final String ROLE_VERIF_PROBLEM_MSG = tr("Role verification problem");
     65    private boolean ignoreMultiPolygons;
    6366
    6467    /**
    6568     * Constructor
     
    99102    }
    100103
    101104    @Override
     105    public void startTest(ProgressMonitor progressMonitor) {
     106        super.startTest(progressMonitor);
     107
     108        for (Test t : OsmValidator.getEnabledTests(false)) {
     109            if (t instanceof MultipolygonTest) {
     110                ignoreMultiPolygons = true;
     111                break;
     112            }
     113        }
     114    }
     115
     116    @Override
    102117    public void visit(Relation n) {
     118        Map<String, RoleInfo> map = buildRoleInfoMap(n);
     119        if (map.isEmpty()) {
     120            errors.add(TestError.builder(this, Severity.ERROR, RELATION_EMPTY)
     121                    .message(tr("Relation is empty"))
     122                    .primitives(n)
     123                    .build());
     124        }
     125        if (ignoreMultiPolygons && n.isMultipolygon()) {
     126            // see #17010: don't report same problem twice
     127            return;
     128        }
    103129        Map<Role, String> allroles = buildAllRoles(n);
    104130        if (allroles.isEmpty() && n.hasTag("type", "route")
    105131                && n.hasTag("route", "train", "subway", "monorail", "tram", "bus", "trolleybus", "aerialway", "ferry")) {
     
    114140                    .build());
    115141        }
    116142
    117         Map<String, RoleInfo> map = buildRoleInfoMap(n);
    118         if (map.isEmpty()) {
    119             errors.add(TestError.builder(this, Severity.ERROR, RELATION_EMPTY)
    120                     .message(tr("Relation is empty"))
    121                     .primitives(n)
    122                     .build());
    123         } else if (!allroles.isEmpty()) {
     143        if (!map.isEmpty() && !allroles.isEmpty()) {
    124144            checkRoles(n, allroles, map);
    125145        }
    126146    }