Changeset 17384 in josm
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/validation/tests/ConnectivityRelations.java
r17374 r17384 71 71 * 72 72 * @param relation A relation with a {@code connectivity} tag. 73 * @return A Map in the form of {@code Map<Lane From, Map<Lane To, Optional>>} May contain nulls when errors are encountered 73 * @return A Map in the form of {@code Map<Lane From, Map<Lane To, Optional>>} May contain nulls when errors are encountered, 74 * empty collection if {@code connectivity} tag contains unusual values 74 75 */ 75 76 public static Map<Integer, Map<Integer, Boolean>> parseConnectivityTag(Relation relation) { 76 String cnTag = relation.get(CONNECTIVITY_TAG);77 if (cnTag == null ) {77 final String cnTag = relation.get(CONNECTIVITY_TAG); 78 if (cnTag == null || cnTag.isEmpty()) { 78 79 return Collections.emptyMap(); 79 80 } … … 81 82 82 83 final Map<Integer, Map<Integer, Boolean>> result = new HashMap<>(); 83 String[] lanes = joined.split("\\|", -1); 84 for (int i = 0; i < lanes.length; i++) { 85 final String[] lane = lanes[i].split(":", -1); 84 String[] lanePairs = joined.split("\\|", -1); 85 for (final String lanePair : lanePairs) { 86 final String[] lane = lanePair.split(":", -1); 87 if (lane.length < 2) 88 return Collections.emptyMap(); 86 89 int laneNumber; 87 //Ignore connections from bw, since we cannot derive a lane number from bw 88 if (!"bw".equals(lane[0])) { 90 try { 89 91 laneNumber = Integer.parseInt(lane[0].trim()); 90 } else { 91 laneNumber = BW; 92 } 92 } catch (NumberFormatException e) { 93 return Collections.emptyMap(); 94 } 95 93 96 Map<Integer, Boolean> connections = new HashMap<>(); 94 97 String[] toLanes = TO_LANE_PATTERN.split(lane[1], -1); 95 for (int j = 0; j < toLanes.length; j++) { 96 String toLane = toLanes[j].trim(); 98 for (String toLane : toLanes) { 97 99 try { 98 100 if (OPTIONAL_LANE_PATTERN.matcher(toLane).matches()) { 99 101 toLane = toLane.replace("(", "").replace(")", "").trim(); 100 if (!"bw".equals(toLane)) { 101 connections.put(Integer.parseInt(toLane), Boolean.TRUE); 102 } else 103 connections.put(BW, Boolean.TRUE); 102 connections.put(Integer.parseInt(toLane), Boolean.TRUE); 104 103 } else { 105 if (!toLane.contains("bw")) { 106 connections.put(Integer.parseInt(toLane), Boolean.FALSE); 107 } else { 108 connections.put(BW, Boolean.FALSE); 109 } 104 connections.put(Integer.parseInt(toLane), Boolean.FALSE); 110 105 } 111 106 } catch (NumberFormatException e) { 112 107 if (MISSING_COMMA_PATTERN.matcher(toLane).matches()) { 113 connections.put(null, true);108 connections.put(null, Boolean.TRUE); 114 109 } else { 115 110 connections.put(null, null); … … 129 124 .message(tr("Connectivity relation without connectivity tag")).primitives(r).build()); 130 125 } else if (!r.hasIncompleteMembers()) { 131 boolean badRole = checkForBadRole(r); 132 boolean missingRole = checkForMissingRole(r); 133 if (!badRole && !missingRole) { 134 Map<String, Integer> roleLanes = checkForInconsistentLanes(r); 135 checkForImpliedConnectivity(r, roleLanes); 126 Map<Integer, Map<Integer, Boolean>> connTagLanes = parseConnectivityTag(r); 127 if (connTagLanes.isEmpty()) { 128 errors.add(TestError.builder(this, Severity.ERROR, MALFORMED_CONNECTIVITY_TAG) 129 .message(tr("Connectivity tag contains unusual data")).primitives(r).build()); 130 } else { 131 boolean badRole = checkForBadRole(r); 132 boolean missingRole = checkForMissingRole(r); 133 if (!badRole && !missingRole) { 134 Map<String, Integer> roleLanes = checkForInconsistentLanes(r, connTagLanes); 135 checkForImpliedConnectivity(r, roleLanes, connTagLanes); 136 } 136 137 } 137 138 } … … 143 144 * 144 145 * @param relation A relation with a {@code connectivity} tag. 146 * @param connTagLanes result of {@link ConnectivityRelations#parseConnectivityTag(Relation)} 145 147 * @return A Map in the form of {@code Map<Role, Lane Count>} 146 148 */ 147 private Map<String, Integer> checkForInconsistentLanes(Relation relation ) {149 private Map<String, Integer> checkForInconsistentLanes(Relation relation, Map<Integer, Map<Integer, Boolean>> connTagLanes) { 148 150 StringBuilder lanelessRoles = new StringBuilder(); 149 151 int lanelessRolesCount = 0; 150 152 // Lane count from connectivity tag 151 Map<Integer, Map<Integer, Boolean>> connTagLanes = parseConnectivityTag(relation); 153 Map<String, Integer> roleLanes = new HashMap<>(); 154 if (connTagLanes.isEmpty()) 155 return roleLanes; 156 152 157 // If the ways involved in the connectivity tag are assuming a standard 2-way bi-directional highway 153 158 boolean defaultLanes = true; … … 165 170 } 166 171 // Lane count from member tags 167 Map<String, Integer> roleLanes = new HashMap<>();168 172 for (RelationMember rM : relation.getMembers()) { 169 173 // Check lanes … … 187 191 } 188 192 189 if (!laneCounts. equals(Collections.emptyList())) {193 if (!laneCounts.isEmpty()) { 190 194 maxLaneCount = Collections.max(laneCounts); 191 195 roleLanes.put(rM.getRole(), (int) maxLaneCount); 192 196 } else { 193 String addString = "'" + rM.getRole() + "'";194 StringBuilder sb = new StringBuilder(addString);195 197 if (lanelessRoles.length() > 0) { 196 sb.insert(0," and ");198 lanelessRoles.append(" and "); 197 199 } 198 lanelessRoles.append( sb.toString());200 lanelessRoles.append('\'').append(rM.getRole()).append('\''); 199 201 lanelessRolesCount++; 200 202 } … … 203 205 } 204 206 205 if (lanelessRoles. toString().isEmpty()) {207 if (lanelessRoles.length() == 0) { 206 208 boolean fromCheck = roleLanes.get(FROM) < Collections 207 209 .max(connTagLanes.entrySet(), Comparator.comparingInt(Map.Entry::getKey)).getKey(); … … 243 245 * @param relation A relation with a {@code connectivity} tag. 244 246 * @param roleLanes The lane counts for each relation role 245 */ 246 private void checkForImpliedConnectivity(Relation relation, Map<String, Integer> roleLanes) { 247 Map<Integer, Map<Integer, Boolean>> connTagLanes = parseConnectivityTag(relation); 247 * @param connTagLanes result of {@link ConnectivityRelations#parseConnectivityTag(Relation)} 248 */ 249 private void checkForImpliedConnectivity(Relation relation, Map<String, Integer> roleLanes, 250 Map<Integer, Map<Integer, Boolean>> connTagLanes) { 248 251 // Don't flag connectivity as already implied when: 249 252 // - Lane counts are different on the roads -
trunk/test/unit/org/openstreetmap/josm/data/validation/tests/ConnectivityRelationsTest.java
r17275 r17384 5 5 import org.junit.jupiter.api.BeforeEach; 6 6 import org.junit.jupiter.api.Test; 7 import org. openstreetmap.josm.JOSMFixture;7 import org.junit.jupiter.api.extension.RegisterExtension; 8 8 import org.openstreetmap.josm.TestUtils; 9 9 import org.openstreetmap.josm.data.coor.LatLon; … … 11 11 import org.openstreetmap.josm.data.osm.Relation; 12 12 import org.openstreetmap.josm.data.osm.RelationMember; 13 import org.openstreetmap.josm.testutils.JOSMTestRules; 14 15 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 13 16 14 17 /** … … 20 23 private ConnectivityRelations check; 21 24 private static final String CONNECTIVITY = "connectivity"; 25 22 26 /** 23 27 * Setup test. 24 *25 * @throws Exception if an error occurs26 28 */ 29 @RegisterExtension 30 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 31 public JOSMTestRules rule = new JOSMTestRules(); 32 27 33 @BeforeEach 28 public void setUp() throws Exception { 29 JOSMFixture.createUnitTestFixture().init(); 34 public void setUpCheck() throws Exception { 30 35 check = new ConnectivityRelations(); 31 36 } … … 86 91 } 87 92 93 /** 94 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/201821">Bug #20182</a>. 95 * @throws Exception if an error occurs 96 */ 97 @Test 98 void testTicket20182() throws Exception { 99 Relation relation = createDefaultTestRelation(); 100 check.visit(relation); 101 int expectedFailures = 0; 102 103 Assert.assertEquals(expectedFailures, check.getErrors().size()); 104 105 relation.put(CONNECTIVITY, "left_turn"); 106 check.visit(relation); 107 Assert.assertEquals(++expectedFailures, check.getErrors().size()); 108 109 relation.put(CONNECTIVITY, "1"); 110 check.visit(relation); 111 Assert.assertEquals(++expectedFailures, check.getErrors().size()); 112 } 88 113 }
Note:
See TracChangeset
for help on using the changeset viewer.