Ticket #24851: 24851-powerlines-v3.patch
| File 24851-powerlines-v3.patch, 7.6 KB (added by , 5 weeks ago) |
|---|
-
src/org/openstreetmap/josm/data/validation/tests/PowerLines.java
98 98 99 99 @Override 100 100 public void visit(Node n) { 101 boolean nodeInLineOrCable = false; 102 boolean connectedToUnrelated = false; 103 for (Way parent : n.getParentWays()) { 104 if (parent.hasTag(POWER, "line", MINOR_LINE, "cable")) 105 nodeInLineOrCable = true; 106 else if (!isRelatedToPower(parent)) 107 connectedToUnrelated = true; 101 if (!n.isConnectionNode() || n.referrers(Way.class).noneMatch(PowerLines::isPowerLineOrCable)) 102 return; 103 104 boolean connectedToUnrelated = n.referrers(Way.class).anyMatch(w -> !isPowerLineOrCable(w) && !isRelatedToPower(w)); 105 if (connectedToUnrelated) { 106 badConnections.add(n); 108 107 } 109 if (nodeInLineOrCable && connectedToUnrelated)110 badConnections.add(n);111 108 } 112 109 113 110 @Override … … 164 161 // Then return the errors 165 162 for (Node n : missingTags) { 166 163 if (!isInPowerStation(n)) { 164 List<OsmPrimitive> primitives = new ArrayList<>(); 165 primitives.add(n); 166 n.referrers(Way.class).filter(PowerLines::isPowerLine).forEach(primitives::add); 167 167 168 errors.add(TestError.builder(this, Severity.WARNING, POWER_SUPPORT) 168 169 // the "missing tag" grouping can become broken if the MapCSS message get reworded 169 170 .message(tr("missing tag"), tr("node without power=*")) 170 .primitives(n) 171 .primitives(primitives) 172 .highlight(n) 171 173 .build()); 172 174 } 173 175 } 174 176 175 177 for (Node n : badConnections) { 178 List<OsmPrimitive> primitives = new ArrayList<>(); 179 primitives.add(n); 180 n.referrers(Way.class).filter(w -> !isPowerLineOrCable(w) && !isRelatedToPower(w)).forEach(primitives::add); 181 n.referrers(Way.class).filter(PowerLines::isPowerLineOrCable).forEach(primitives::add); 182 176 183 errors.add(TestError.builder(this, Severity.WARNING, POWER_CONNECTION) 177 184 .message(tr("Node connects a power line or cable with an object " 178 185 + "which is not related to the power infrastructure")) 179 .primitives(n) 186 .primitives(primitives) 187 .highlight(n) 180 188 .build()); 181 189 } 182 190 … … 669 677 } 670 678 671 679 /** 680 * Determines if the specified way denotes a power line or cable. 681 * @param w The way to be tested 682 * @return {@code true} if power key is set and equal to line, minor_line or cable 683 */ 684 protected static boolean isPowerLineOrCable(Way w) { 685 return isPowerIn(w, Arrays.asList("line", MINOR_LINE, "cable")); 686 } 687 688 /** 672 689 * Determines if the specified primitive denotes a power station. 673 690 * @param p The primitive to be tested 674 691 * @return {@code true} if power key is set and equal to generator/substation/plant -
test/unit/org/openstreetmap/josm/data/validation/tests/PowerLinesTest.java
1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.data.validation.tests; 3 3 4 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;5 import static org.junit.jupiter.api.Assertions.assertFalse;6 import static org.junit.jupiter.api.Assertions.assertTrue;7 8 import java.util.ArrayList;9 10 4 import org.junit.jupiter.api.BeforeEach; 11 5 import org.junit.jupiter.api.Test; 12 6 import org.openstreetmap.josm.TestUtils; … … 17 11 import org.openstreetmap.josm.data.osm.RelationMember; 18 12 import org.openstreetmap.josm.data.osm.TagMap; 19 13 import org.openstreetmap.josm.data.osm.Way; 14 import org.openstreetmap.josm.data.validation.TestError; 20 15 import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 21 16 import org.openstreetmap.josm.testutils.annotations.BasicPreferences; 22 17 import org.openstreetmap.josm.testutils.annotations.Projection; 23 18 19 import java.util.ArrayList; 20 21 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 22 import static org.junit.jupiter.api.Assertions.assertFalse; 23 import static org.junit.jupiter.api.Assertions.assertTrue; 24 24 25 /** 25 26 * Test class for {@link PowerLines} 26 27 * @since 18553 … … 159 160 this.powerLines.endTest(); 160 161 assertTrue(this.powerLines.getErrors().isEmpty()); 161 162 } 162 } 163 164 /** 165 * Test for ticket #24851. 166 * Simulates connecting a power line to an existing highway node without power tags. 167 * Validates that the resulting error contains both the Node AND the Way, so it 168 * doesn't get filtered out during partial validation on upload. 169 */ 170 @Test 171 void testTicket24851_ReportExistingNonPowerNodes() { 172 Node sharedNode = new Node(new LatLon(0, 0)); // no power tag attached 173 174 // unrelated highway way 175 Way highway = TestUtils.newWay("highway=unclassified", 176 sharedNode, new Node(new LatLon(0.1, 0))); 177 178 // power line way 179 Way powerline = TestUtils.newWay("power=line", 180 sharedNode, new Node(new LatLon(0, 0.1))); 181 182 // second node has a valid tag 183 powerline.getNode(1).put("power", "tower"); 184 185 ds.addPrimitiveRecursive(highway); 186 ds.addPrimitiveRecursive(powerline); 187 188 powerLines.startTest(NullProgressMonitor.INSTANCE); 189 for (Way w : ds.getWays()) { 190 powerLines.visit(w); 191 } 192 for (Node n : ds.getNodes()) { 193 powerLines.visit(n); 194 } 195 powerLines.endTest(); 196 197 assertFalse(powerLines.getErrors().isEmpty(), "Errors should be generated for the missing tag and bad connection"); 198 199 boolean foundSupportError = false; 200 boolean foundConnectionError = false; 201 202 for (TestError error : powerLines.getErrors()) { 203 // verify POWER_SUPPORT behavior (missing tag) 204 if (error.getCode() == PowerLines.POWER_SUPPORT && error.getPrimitives().contains(sharedNode)) { 205 foundSupportError = true; 206 assertTrue(error.getPrimitives().contains(powerline), 207 "MUST contain the parent powerline way. This prevents JOSM from discarding the error " + 208 "during partial validation if the node itself was unmodified."); 209 } 210 // verify POWER_CONNECTION behavior (bad connection) 211 if (error.getCode() == PowerLines.POWER_CONNECTION && error.getPrimitives().contains(sharedNode)) { 212 foundConnectionError = true; 213 assertTrue(error.getPrimitives().contains(highway), 214 "MUST contain the unrelated parent way. This prevents JOSM from discarding the error" + 215 "during partial validation if the node itself was unmodified."); 216 } 217 } 218 219 assertTrue(foundSupportError, "Should report missing power tag on shared node"); 220 assertTrue(foundConnectionError, "Should report bad connection on shared node"); 221 } 222 } 223 No newline at end of file
