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 }