Ticket #3367: validator_duplicate_ways.diff

File validator_duplicate_ways.diff, 5.8 KB (added by singularita@…, 3 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    /**