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    }