Ticket #19312: 19312.patch
| File 19312.patch, 4.5 KB (added by , 6 years ago) |
|---|
-
src/org/openstreetmap/josm/data/validation/tests/RelationChecker.java
8 8 import java.util.Collection; 9 9 import java.util.EnumSet; 10 10 import java.util.HashMap; 11 import java.util.Iterator; 11 12 import java.util.LinkedHashMap; 12 13 import java.util.LinkedList; 13 14 import java.util.List; … … 14 15 import java.util.Map; 15 16 import java.util.stream.Collectors; 16 17 18 import org.openstreetmap.josm.command.ChangeCommand; 17 19 import org.openstreetmap.josm.command.Command; 18 20 import org.openstreetmap.josm.command.DeleteCommand; 19 21 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 61 63 public static final int RELATION_EMPTY = 1708; 62 64 /** Type ''{0}'' of relation member with role ''{1}'' does not match accepted types ''{2}'' in preset {3} */ 63 65 public static final int WRONG_TYPE = 1709; 66 /** Relations build a loop */ 67 public static final int RELATION_LOOP = 1710; 64 68 // CHECKSTYLE.ON: SingleSpaceSeparator 65 69 66 70 /** … … 70 74 public static final String ROLE_VERIF_PROBLEM_MSG = tr("Role verification problem"); 71 75 private boolean ignoreMultiPolygons; 72 76 private boolean ignoreTurnRestrictions; 73 77 private final List<List<Relation>> loops = new ArrayList<>(); 74 78 /** 75 79 * Constructor 76 80 */ … … 154 158 if (!map.isEmpty() && !allroles.isEmpty()) { 155 159 checkRoles(n, allroles, map); 156 160 } 161 checkLoop(n); 157 162 } 158 163 159 164 private static Map<String, RoleInfo> buildRoleInfoMap(Relation n) { … … 365 370 public Command fixError(TestError testError) { 366 371 Collection<? extends OsmPrimitive> primitives = testError.getPrimitives(); 367 372 if (isFixable(testError) && !primitives.iterator().next().isDeleted()) { 368 return new DeleteCommand(primitives); 373 if (testError.getCode() == RELATION_EMPTY) { 374 return new DeleteCommand(primitives); 375 } 376 if (testError.getCode() == RELATION_LOOP) { 377 Relation old = (Relation) primitives.iterator().next(); 378 Relation mod = new Relation(old); 379 mod.removeMembersFor(primitives); 380 return new ChangeCommand(old, mod); 381 } 369 382 } 370 383 return null; 371 384 } … … 373 386 @Override 374 387 public boolean isFixable(TestError testError) { 375 388 Collection<? extends OsmPrimitive> primitives = testError.getPrimitives(); 376 return testError.getCode() == RELATION_EMPTY && !primitives.isEmpty() && primitives.iterator().next().isNew(); 389 return testError.getCode() == RELATION_EMPTY && !primitives.isEmpty() && primitives.iterator().next().isNew() || 390 testError.getCode() == RELATION_LOOP && primitives.size() == 1; 377 391 } 378 392 379 393 @Override … … 381 395 relationpresets.clear(); 382 396 initializePresets(); 383 397 } 398 399 @Override 400 public void endTest() { 401 loops.forEach(loop -> errors.add(TestError.builder(this, Severity.ERROR, RELATION_LOOP) 402 .message(loop.size() == 1 ? tr("Relation contains itself as a member") : tr("Relations build a dependency loop")) 403 .primitives(loop) 404 .build())); 405 loops.clear(); 406 super.endTest(); 407 } 408 409 private void checkLoop(Relation r) { 410 checkLoop(r, new LinkedList<>()); 411 } 412 413 private void checkLoop(Relation parent, List<Relation> path) { 414 if (path.contains(parent)) { 415 Iterator<List<Relation>> iter = loops.iterator(); 416 while (iter.hasNext()) { 417 List<Relation> loop = iter.next(); 418 if (loop.size() > path.size() && loop.containsAll(path)) { 419 // remove same loop with irrelevant parent 420 iter.remove(); 421 } else if (path.size() >= loop.size() && path.containsAll(loop)) { 422 // same or smaller loop is already known 423 return; 424 } 425 } 426 loops.add(path); 427 return; 428 } 429 path.add(parent); 430 for (Relation sub : parent.getMemberPrimitives(Relation.class)) { 431 if (sub.isUsable() && !sub.isIncomplete()) { 432 checkLoop(sub, new LinkedList<>(path)); 433 } 434 } 435 } 436 384 437 }
