Ticket #3367: validator_duplicate_ways.diff

File validator_duplicate_ways.diff, 5.8 KB (added by bilbo, 15 years ago)

Patch to add this check

  • src/org/openstreetmap/josm/plugins/validator/tests/DuplicateWay.java

     
     1package org.openstreetmap.josm.plugins.validator.tests;
     2
     3import static org.openstreetmap.josm.tools.I18n.tr;
     4
     5import java.util.Collection;
     6import java.util.LinkedList;
     7import java.util.List;
     8import java.util.Vector;
     9import java.util.Map;
     10
     11import org.openstreetmap.josm.Main;
     12import org.openstreetmap.josm.command.Command;
     13import org.openstreetmap.josm.command.DeleteCommand;
     14import org.openstreetmap.josm.command.SequenceCommand;
     15import org.openstreetmap.josm.data.coor.LatLon;
     16import org.openstreetmap.josm.data.osm.Node;
     17import org.openstreetmap.josm.data.osm.Way;
     18import org.openstreetmap.josm.data.osm.OsmPrimitive;
     19import org.openstreetmap.josm.plugins.validator.Severity;
     20import org.openstreetmap.josm.plugins.validator.Test;
     21import org.openstreetmap.josm.plugins.validator.TestError;
     22import org.openstreetmap.josm.plugins.validator.util.Bag;
     23/**
     24 * Tests if there are duplicate ways
     25 */
     26public class DuplicateWay extends Test
     27{
     28
     29    private class WayPair {
     30        public List<LatLon> coor;
     31        public Map<String, String> keys;
     32        public WayPair(List<LatLon> _coor,Map<String, String> _keys) {
     33            coor=_coor;
     34            keys=_keys;
     35        }
     36        @Override
     37        public int hashCode() {
     38            return coor.hashCode()+keys.hashCode();
     39        }
     40        @Override
     41        public boolean equals(Object obj) {
     42            if (!(obj instanceof WayPair)) return false;
     43            WayPair wp = (WayPair) obj;
     44            return wp.coor.equals(coor) && wp.keys.equals(keys);
     45        }
     46    }
     47
     48    protected static int DUPLICATE_WAY = 1;
     49
     50    /** Bag of all ways */
     51    Bag<WayPair, OsmPrimitive> ways;
     52
     53    /**
     54     * Constructor
     55     */
     56    public DuplicateWay()
     57    {
     58        super(tr("Duplicated ways")+".",
     59              tr("This test checks that there are no ways with same tags and same node coordinates."));
     60    }
     61
     62
     63    @Override
     64    public void startTest()
     65    {
     66        ways = new Bag<WayPair, OsmPrimitive>(1000);
     67    }
     68
     69    @Override
     70    public void endTest()
     71    {
     72        for(List<OsmPrimitive> duplicated : ways.values() )
     73        {
     74            if( duplicated.size() > 1)
     75            {
     76                TestError testError = new TestError(this, Severity.ERROR, tr("Duplicated ways"), DUPLICATE_WAY, duplicated);
     77                errors.add( testError );
     78            }
     79        }
     80        ways = null;
     81    }
     82
     83    @Override
     84    public void visit(Way w)
     85    {
     86        if( w.deleted || w.incomplete )
     87            return;
     88        List<Node> wNodes=w.getNodes();
     89        Vector<LatLon> wLat=new Vector<LatLon>(wNodes.size());
     90        for(int i=0;i<wNodes.size();i++) {
     91                wLat.add(wNodes.get(i).getCoor());
     92        }
     93        Map<String, String> wkeys=w.getKeys();
     94        wkeys.remove("created_by");
     95        WayPair wKey=new WayPair(wLat,wkeys);
     96        ways.add(wKey, w);
     97    }
     98
     99    /**
     100     * Fix the error by removing all but one instance of duplicate ways
     101     */
     102    @Override
     103    public Command fixError(TestError testError)
     104    {
     105        Collection<? extends OsmPrimitive> sel = testError.getPrimitives();
     106        LinkedList<Way> ways = new LinkedList<Way>();
     107
     108        for (OsmPrimitive osm : sel)
     109            if (osm instanceof Way)
     110                ways.add((Way)osm);
     111
     112        if( ways.size() < 2 )
     113            return null;
     114
     115        long idToKeep = 0;
     116        // Only one way will be kept - the one with lowest positive ID, if such exist
     117        // or one "at random" if no such exists. Rest of the ways will be deleted
     118        for (Way w: ways) {
     119            if (w.id > 0) {
     120                if (idToKeep == 0 || w.id < idToKeep) idToKeep = w.id;
     121            }
     122        }
     123
     124        if (idToKeep > 0) {
     125            //Remove chosen way from the list, rest of ways in the list will be deleted
     126            for (Way w: ways) {
     127                if (w.id == idToKeep) {
     128                    ways.remove(w);
     129                    break;
     130                }
     131            }
     132        } else {
     133            //Remove first way from the list, delete the rest
     134            ways.remove(0);
     135        }
     136
     137        //Delete all ways in the list
     138        //Note: nodes are not deleted, these can be detected and deleted at next pass
     139        Collection<Command> commands = new LinkedList<Command>();
     140        commands.add(new DeleteCommand(ways));
     141        Main.main.undoRedo.add(new SequenceCommand(tr("Delete duplicate ways"), commands));
     142        return null;
     143    }
     144
     145    @Override
     146    public boolean isFixable(TestError testError)
     147    {
     148        return (testError.getTester() instanceof DuplicateWay);
     149    }
     150
     151}
  • src/org/openstreetmap/josm/plugins/validator/OSMValidatorPlugin.java

     
    3838import org.openstreetmap.josm.plugins.validator.tests.Coastlines;
    3939import org.openstreetmap.josm.plugins.validator.tests.CrossingWays;
    4040import org.openstreetmap.josm.plugins.validator.tests.DuplicateNode;
     41import org.openstreetmap.josm.plugins.validator.tests.DuplicateWay;
    4142import org.openstreetmap.josm.plugins.validator.tests.DuplicatedWayNodes;
    4243import org.openstreetmap.josm.plugins.validator.tests.NodesWithSameName;
    4344import org.openstreetmap.josm.plugins.validator.tests.OverlappingWays;
     
    9697            UnclosedWays.class, // ID 1101 .. 1199
    9798            TagChecker.class, // ID 1201 .. 1299
    9899            UnconnectedWays.class, // ID 1301 .. 1399
     100            DuplicateWay.class,
    99101    };
    100102
    101103    /**