001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.validation.tests; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.util.ArrayList; 007import java.util.List; 008 009import org.openstreetmap.josm.data.osm.Relation; 010import org.openstreetmap.josm.data.osm.RelationMember; 011import org.openstreetmap.josm.data.validation.Severity; 012import org.openstreetmap.josm.data.validation.Test; 013import org.openstreetmap.josm.data.validation.TestError; 014import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType; 015import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionTypeCalculator; 016 017/** 018 * Tests for <a href="https://wiki.openstreetmap.org/wiki/Proposed_features/Public_Transport">public transport routes</a>. 019 */ 020public class PublicTransportRouteTest extends Test { 021 022 private final WayConnectionTypeCalculator connectionTypeCalculator = new WayConnectionTypeCalculator(); 023 024 /** 025 * Constructs a new {@code PublicTransportRouteTest}. 026 */ 027 public PublicTransportRouteTest() { 028 super(tr("Public Transport Route")); 029 } 030 031 @Override 032 public void visit(Relation r) { 033 final boolean skip = r.hasIncompleteMembers() 034 || !r.hasTag("type", "route") 035 || !r.hasKey("route") 036 || !r.hasTag("public_transport:version", "2"); 037 if (skip) { 038 return; 039 } 040 041 final List<RelationMember> membersToCheck = new ArrayList<>(); 042 for (RelationMember member : r.getMembers()) { 043 if (member.hasRole("forward", "backward")) { 044 errors.add(new TestError(this, Severity.WARNING, tr("Route relation contains a ''{0}'' role", "forward/backward"), 3601, r)); 045 return; 046 } else if (member.hasRole("")) { 047 membersToCheck.add(member); 048 } 049 } 050 if (membersToCheck.isEmpty()) { 051 return; 052 } 053 054 final List<WayConnectionType> links = connectionTypeCalculator.updateLinks(membersToCheck); 055 for (int i = 0; i < links.size(); i++) { 056 final WayConnectionType link = links.get(i); 057 final boolean hasError = !(i == 0 || link.linkPrev) 058 || !(i == links.size() - 1 || link.linkNext) 059 || link.direction == null 060 || WayConnectionType.Direction.NONE.equals(link.direction); 061 if (hasError) { 062 errors.add(new TestError(this, Severity.WARNING, tr("Route relation contains a gap"), 3602, r)); 063 return; 064 } 065 } 066 067 } 068}