Ticket #19600: 19600.patch

File 19600.patch, 4.8 KB (added by GerdP, 5 years ago)
  • src/org/openstreetmap/josm/data/validation/tests/WayConnectedToArea.java

     
    44import static org.openstreetmap.josm.data.validation.tests.CrossingWays.HIGHWAY;
    55import static org.openstreetmap.josm.tools.I18n.tr;
    66
     7import java.util.ArrayList;
     8import java.util.Arrays;
    79import java.util.List;
     10import java.util.stream.Collectors;
    811
    912import org.openstreetmap.josm.data.osm.Node;
    1013import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    1316import org.openstreetmap.josm.data.validation.Severity;
    1417import org.openstreetmap.josm.data.validation.Test;
    1518import org.openstreetmap.josm.data.validation.TestError;
    16 import org.openstreetmap.josm.gui.mappaint.ElemStyles;
    1719
    1820/**
    19  * Checks for ways connected to areas.
     21 * Checks for highways connected to areas.
    2022 * @since 4682
    2123 */
    2224public class WayConnectedToArea extends Test {
     
    3436            return;
    3537        }
    3638
    37         List<OsmPrimitive> r = w.firstNode().getReferrers();
    38         boolean hasway = r.stream().anyMatch(p -> p != w && p.hasKey(HIGHWAY));
    39         if (!hasway) {
    40             for (OsmPrimitive p : r) {
    41                 testForError(w, w.firstNode(), p);
     39        for (Node node : Arrays.asList(w.firstNode(), w.lastNode())) {
     40            if (node.isOutsideDownloadArea()) {
     41                continue;
    4242            }
    43         }
    44         r = w.lastNode().getReferrers();
    45         hasway = r.stream().anyMatch(p -> p != w && p.hasKey(HIGHWAY));
    46         if (!hasway) {
    47             for (OsmPrimitive p : r) {
    48                 testForError(w, w.lastNode(), p);
     43            if (node.hasTag("noexit", "yes")) {
     44                // Avoid "legal" case (see #17036)
     45                continue;
    4946            }
    50         }
    51     }
    5247
    53     private void testForError(Way w, Node wayNode, OsmPrimitive p) {
    54         if (wayNode.isOutsideDownloadArea()
    55                 || wayNode.getReferrers().stream().anyMatch(p1 -> p1.hasTag("route", "ferry"))) {
    56             return;
    57         } else if (isArea(p)) {
    58             addPossibleError(w, wayNode, p, p);
    59         } else {
    60             p.referrers(Relation.class)
    61                     .filter(r -> r.isMultipolygon() && isArea(r))
    62                     .findFirst()
    63                     .ifPresent(r -> addPossibleError(w, wayNode, p, r));
     48            // get other parent ways
     49            List<Way> parentWays = node.referrers(Way.class).filter(p -> w != p).collect(Collectors.toList());
     50            List<OsmPrimitive> badAreas = new ArrayList<>();
     51            boolean hasValidTarget = false;
     52            for (Way other : parentWays) {
     53                hasValidTarget |= wayIsHighwayTarget(other) || isSlipway(w, node);
     54                if (hasValidTarget)
     55                    break;
     56                else if (other.concernsArea()) {
     57                    badAreas.add(other);
     58                }
     59            }
     60            if (!hasValidTarget && !badAreas.isEmpty()) {
     61                List<OsmPrimitive> primitives = new ArrayList<>();
     62                primitives.add(w);
     63                primitives.addAll(badAreas);
     64                errors.add(TestError.builder(this, Severity.WARNING, 2301)
     65                        .message(tr("Way terminates on Area"))
     66                        .primitives(primitives)
     67                        .highlight(node)
     68                        .build());
     69            }
    6470        }
    6571    }
    6672
    67     private static boolean isArea(OsmPrimitive p) {
    68         return p.hasKey("landuse", "natural") && ElemStyles.hasAreaElemStyle(p, false);
     73    private static boolean wayIsHighwayTarget(Way w) {
     74        return w.hasKey(HIGHWAY) || isBuilding(w) || w.hasTag("route", "ferry") || w.hasTag("railway", "platform");
    6975    }
    7076
    71     private void addPossibleError(Way w, Node wayNode, OsmPrimitive p, OsmPrimitive area) {
    72         // Avoid "legal" cases (see #10655)
    73         if (w.hasKey(HIGHWAY) && wayNode.hasTag("leisure", "slipway") && area.hasTag("natural", "water")) {
    74             return;
    75         }
    76         if (wayNode.hasTag("noexit", "yes")) {
    77             // Avoid "legal" case (see #17036)
    78             return;
    79         }
    80         errors.add(TestError.builder(this, Severity.WARNING, 2301)
    81                 .message(tr("Way terminates on Area"))
    82                 .primitives(w, p)
    83                 .highlight(wayNode)
    84                 .build());
     77    // Avoid "legal" cases (see #10655)
     78    private static boolean isSlipway(Way w, Node node) {
     79        return node.hasTag("leisure", "slipway") && (w.hasTag("natural", "water") ||
     80                w.referrers(Relation.class)
     81                .anyMatch(r -> r.isMultipolygon() && r.hasTag("natural", "water")));
    8582    }
    8683}