001 // License: GPL. See LICENSE file for details. 002 package org.openstreetmap.josm.data.validation.tests; 003 004 import static org.openstreetmap.josm.tools.I18n.tr; 005 006 import java.util.Arrays; 007 import java.util.Collections; 008 009 import org.openstreetmap.josm.command.ChangeCommand; 010 import org.openstreetmap.josm.command.Command; 011 import org.openstreetmap.josm.data.osm.Node; 012 import org.openstreetmap.josm.data.osm.Way; 013 import org.openstreetmap.josm.data.validation.Severity; 014 import org.openstreetmap.josm.data.validation.Test; 015 import org.openstreetmap.josm.data.validation.TestError; 016 017 public class DuplicatedWayNodes extends Test { 018 protected static final int DUPLICATE_WAY_NODE = 501; 019 020 public DuplicatedWayNodes() { 021 super(tr("Duplicated way nodes"), 022 tr("Checks for ways with identical consecutive nodes.")); 023 } 024 025 @Override 026 public void visit(Way w) { 027 if (!w.isUsable()) return; 028 029 Node lastN = null; 030 for (Node n : w.getNodes()) { 031 if (lastN == null) { 032 lastN = n; 033 continue; 034 } 035 if (lastN == n) { 036 errors.add(new TestError(this, Severity.ERROR, tr("Duplicated way nodes"), DUPLICATE_WAY_NODE, 037 Arrays.asList(w), Arrays.asList(n))); 038 break; 039 } 040 lastN = n; 041 } 042 } 043 044 @Override public Command fixError(TestError testError) { 045 Way w = (Way) testError.getPrimitives().iterator().next(); 046 Way wnew = new Way(w); 047 wnew.setNodes(null); 048 Node lastN = null; 049 for (Node n : w.getNodes()) { 050 if (lastN == null) { 051 wnew.addNode(n); 052 } else if (n == lastN) { 053 // Skip this node 054 } else { 055 wnew.addNode(n); 056 } 057 lastN = n; 058 } 059 if (wnew.getNodesCount() < 2) 060 // Empty way, delete 061 return deletePrimitivesIfNeeded(Collections.singleton(w)); 062 else 063 return new ChangeCommand(w, wnew); 064 } 065 066 @Override public boolean isFixable(TestError testError) { 067 return testError.getTester() instanceof DuplicatedWayNodes; 068 } 069 }