// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.data.validation.tests; import static org.openstreetmap.josm.tools.I18n.tr; import java.util.List; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.data.osm.Relation; import org.openstreetmap.josm.data.osm.Way; import org.openstreetmap.josm.data.validation.Severity; import org.openstreetmap.josm.data.validation.Test; import org.openstreetmap.josm.data.validation.TestError; import org.openstreetmap.josm.gui.mappaint.ElemStyles; /** * Checks for ways connected to areas. * @since 4682 */ public class WayConnectedToArea extends Test { /** * Constructs a new {@code WayConnectedToArea} test. */ public WayConnectedToArea() { super(tr("Way connected to Area"), tr("Checks for ways connected to areas.")); } @Override public void visit(Way w) { if (!w.isUsable() || w.isClosed() || !w.hasKey("highway")) { return; } boolean hasway = false; List<OsmPrimitive> r = w.firstNode().getReferrers(); for (OsmPrimitive p : r) { if (p != w && p.hasKey("highway")) { hasway = true; break; } } if (!hasway) { for (OsmPrimitive p : r) { testForError(w, w.firstNode(), p); } } hasway = false; r = w.lastNode().getReferrers(); for (OsmPrimitive p : r) { if (p != w && p.hasKey("highway")) { hasway = true; break; } } if (!hasway) { for (OsmPrimitive p : r) { testForError(w, w.lastNode(), p); } } } private void testForError(Way w, Node wayNode, OsmPrimitive p) { if (wayNode.isOutsideDownloadArea() || wayNode.getReferrers().stream().anyMatch(p1 -> p1.hasTag("route", "ferry"))) { return; } else if (isArea(p)) { addPossibleError(w, wayNode, p, p); } else { for (OsmPrimitive r : p.getReferrers()) { if (r instanceof Relation && r.hasTag("type", "multipolygon") && isArea(r)) { addPossibleError(w, wayNode, p, r); break; } } } } private static boolean isArea(OsmPrimitive p) { return p.hasKey("landuse", "natural") && ElemStyles.hasAreaElemStyle(p, false); } private void addPossibleError(Way w, Node wayNode, OsmPrimitive p, OsmPrimitive area) { // Avoid "legal" cases (see #10655) if (w.hasKey("highway") && wayNode.hasTag("leisure", "slipway") && area.hasTag("natural", "water")) { return; } errors.add(TestError.builder(this, Severity.WARNING, 2301) .message(tr("Way terminates on Area")) .primitives(w, p) .highlight(wayNode) .build()); } }