source: josm/trunk/src/org/openstreetmap/josm/data/validation/tests/TurnrestrictionTest.java@ 6241

Last change on this file since 6241 was 6241, checked in by Don-vip, 11 years ago

fix more warnings/javadoc in data.validation.tests

  • Property svn:eol-style set to native
File size: 8.2 KB
Line 
1// License: GPL. See LICENSE file for details.
2package org.openstreetmap.josm.data.validation.tests;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.Arrays;
8import java.util.Collections;
9import java.util.List;
10
11import org.openstreetmap.josm.data.osm.Node;
12import org.openstreetmap.josm.data.osm.OsmPrimitive;
13import org.openstreetmap.josm.data.osm.Relation;
14import org.openstreetmap.josm.data.osm.RelationMember;
15import org.openstreetmap.josm.data.osm.Way;
16import org.openstreetmap.josm.data.validation.Severity;
17import org.openstreetmap.josm.data.validation.Test;
18import org.openstreetmap.josm.data.validation.TestError;
19
20/**
21 * Checks if turnrestrictions are valid
22 * @since 3669
23 */
24public class TurnrestrictionTest extends Test {
25
26 protected static final int NO_VIA = 1801;
27 protected static final int NO_FROM = 1802;
28 protected static final int NO_TO = 1803;
29 protected static final int MORE_VIA = 1804;
30 protected static final int MORE_FROM = 1805;
31 protected static final int MORE_TO = 1806;
32 protected static final int UNKNOWN_ROLE = 1807;
33 protected static final int UNKNOWN_TYPE = 1808;
34 protected static final int FROM_VIA_NODE = 1809;
35 protected static final int TO_VIA_NODE = 1810;
36 protected static final int FROM_VIA_WAY = 1811;
37 protected static final int TO_VIA_WAY = 1812;
38 protected static final int MIX_VIA = 1813;
39 protected static final int UNCONNECTED_VIA = 1814;
40 protected static final int SUPERFLUOUS = 1815;
41
42 /**
43 * Constructs a new {@code TurnrestrictionTest}.
44 */
45 public TurnrestrictionTest() {
46 super(tr("Turnrestrictions"), tr("This test checks if turnrestrictions are valid"));
47 }
48
49 @Override
50 public void visit(Relation r) {
51 if (!"restriction".equals(r.get("type")))
52 return;
53
54 Way fromWay = null;
55 Way toWay = null;
56 List<OsmPrimitive> via = new ArrayList<OsmPrimitive>();
57
58 boolean morefrom = false;
59 boolean moreto = false;
60 boolean morevia = false;
61 boolean mixvia = false;
62
63 /* find the "from", "via" and "to" elements */
64 for (RelationMember m : r.getMembers()) {
65 if (m.getMember().isIncomplete())
66 return;
67
68 ArrayList<OsmPrimitive> l = new ArrayList<OsmPrimitive>();
69 l.add(r);
70 l.add(m.getMember());
71 if (m.isWay()) {
72 Way w = m.getWay();
73 if (w.getNodesCount() < 2) {
74 continue;
75 }
76
77 if ("from".equals(m.getRole())) {
78 if (fromWay != null) {
79 morefrom = true;
80 } else {
81 fromWay = w;
82 }
83 } else if ("to".equals(m.getRole())) {
84 if (toWay != null) {
85 moreto = true;
86 } else {
87 toWay = w;
88 }
89 } else if ("via".equals(m.getRole())) {
90 if (!via.isEmpty() && via.get(0) instanceof Node) {
91 mixvia = true;
92 } else {
93 via.add(w);
94 }
95 } else {
96 errors.add(new TestError(this, Severity.WARNING, tr("Unknown role"), UNKNOWN_ROLE,
97 l, Collections.singletonList(m)));
98 }
99 } else if (m.isNode()) {
100 Node n = m.getNode();
101 if ("via".equals(m.getRole())) {
102 if (!via.isEmpty()) {
103 if (via.get(0) instanceof Node) {
104 morevia = true;
105 } else {
106 mixvia = true;
107 }
108 } else {
109 via.add(n);
110 }
111 } else {
112 errors.add(new TestError(this, Severity.WARNING, tr("Unknown role"), UNKNOWN_ROLE,
113 l, Collections.singletonList(m)));
114 }
115 } else {
116 errors.add(new TestError(this, Severity.WARNING, tr("Unknown member type"), UNKNOWN_TYPE,
117 l, Collections.singletonList(m)));
118 }
119 }
120 if (morefrom) {
121 errors.add(new TestError(this, Severity.ERROR, tr("More than one \"from\" way found"), MORE_FROM, r));
122 }
123 if (moreto) {
124 errors.add(new TestError(this, Severity.ERROR, tr("More than one \"to\" way found"), MORE_TO, r));
125 }
126 if (morevia) {
127 errors.add(new TestError(this, Severity.ERROR, tr("More than one \"via\" node found"), MORE_VIA, r));
128 }
129 if (mixvia) {
130 errors.add(new TestError(this, Severity.ERROR, tr("Cannot mix node and way for role \"via\""), MIX_VIA, r));
131 }
132
133 if (fromWay == null) {
134 errors.add(new TestError(this, Severity.ERROR, tr("No \"from\" way found"), NO_FROM, r));
135 return;
136 }
137 if (toWay == null) {
138 errors.add(new TestError(this, Severity.ERROR, tr("No \"to\" way found"), NO_TO, r));
139 return;
140 }
141 if (via.isEmpty()) {
142 errors.add(new TestError(this, Severity.ERROR, tr("No \"via\" node or way found"), NO_VIA, r));
143 return;
144 }
145
146 if (via.get(0) instanceof Node) {
147 final Node viaNode = (Node) via.get(0);
148 final Way viaPseudoWay = new Way();
149 viaPseudoWay.addNode(viaNode);
150 checkIfConnected(fromWay, viaPseudoWay,
151 tr("The \"from\" way does not start or end at a \"via\" node"), FROM_VIA_NODE);
152 if (toWay.isOneway() != 0 && viaNode.equals(toWay.lastNode(true))) {
153 errors.add(new TestError(this, Severity.WARNING, tr("Superfluous turnrestriction as \"to\" way is oneway"), SUPERFLUOUS, r));
154 return;
155 }
156 checkIfConnected(viaPseudoWay, toWay,
157 tr("The \"to\" way does not start or end at a \"via\" node"), TO_VIA_NODE);
158 } else {
159 // check if consecutive ways are connected: from/via[0], via[i-1]/via[i], via[last]/to
160 checkIfConnected(fromWay, (Way) via.get(0),
161 tr("The \"from\" and the first \"via\" way are not connected."), FROM_VIA_WAY);
162 if (via.size() > 1) {
163 for (int i = 1; i < via.size(); i++) {
164 Way previous = (Way) via.get(i - 1);
165 Way current = (Way) via.get(i);
166 checkIfConnected(previous, current,
167 tr("The \"via\" ways are not connected."), UNCONNECTED_VIA);
168 }
169 }
170 if (toWay.isOneway() != 0 && ((Way) via.get(via.size() - 1)).isFirstLastNode(toWay.lastNode(true))) {
171 errors.add(new TestError(this, Severity.WARNING, tr("Superfluous turnrestriction as \"to\" way is oneway"), SUPERFLUOUS, r));
172 return;
173 }
174 checkIfConnected((Way) via.get(via.size() - 1), toWay,
175 tr("The last \"via\" and the \"to\" way are not connected."), TO_VIA_WAY);
176
177 }
178 }
179
180 private void checkIfConnected(Way previous, Way current, String msg, int code) {
181 boolean c;
182 if (previous.isOneway() != 0 && current.isOneway() != 0) {
183 // both oneways: end/start node must be equal
184 c = previous.lastNode(true).equals(current.firstNode(true));
185 } else if (previous.isOneway() != 0) {
186 // previous way is oneway: end of previous must be start/end of current
187 c = current.isFirstLastNode(previous.lastNode(true));
188 } else if (current.isOneway() != 0) {
189 // current way is oneway: start of current must be start/end of previous
190 c = previous.isFirstLastNode(current.firstNode(true));
191 } else {
192 // otherwise: start/end of previous must be start/end of current
193 c = current.isFirstLastNode(previous.firstNode()) || current.isFirstLastNode(previous.lastNode());
194 }
195 if (!c) {
196 errors.add(new TestError(this, Severity.ERROR, msg, code, Arrays.asList(previous, current)));
197 }
198 }
199}
Note: See TracBrowser for help on using the repository browser.