Ticket #5642: validator-sw-dr-check-ni_(updated).patch

File validator-sw-dr-check-ni_(updated).patch, 13.4 KB (added by bastiK, 11 years ago)

validator is in JOSM core now - here is the updated patch

  • src/org/openstreetmap/josm/data/validation/tests/SameWay.java

     
     1// License: GPL. See LICENSE file for details.
     2package org.openstreetmap.josm.data.validation.tests;
     3
     4import java.util.Collection;
     5import static org.openstreetmap.josm.tools.I18n.tr;
     6
     7import java.util.List;
     8import java.util.Vector;
     9
     10import org.openstreetmap.josm.command.Command;
     11import org.openstreetmap.josm.data.coor.LatLon;
     12import org.openstreetmap.josm.data.osm.Node;
     13import org.openstreetmap.josm.data.osm.OsmPrimitive;
     14import org.openstreetmap.josm.data.osm.Way;
     15import org.openstreetmap.josm.data.validation.Severity;
     16import org.openstreetmap.josm.data.validation.Test;
     17import org.openstreetmap.josm.data.validation.TestError;
     18import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     19import org.openstreetmap.josm.tools.MultiMap;
     20
     21/**
     22 * Tests if there are same ways (same position, but maybe different tags)
     23 */
     24public class SameWay extends Test
     25{
     26
     27    private static class WayPair {
     28        public List<LatLon> coor;
     29        public WayPair(List<LatLon> _coor) {
     30            coor=_coor;
     31        }
     32        @Override
     33        public int hashCode() {
     34            return coor.hashCode();
     35        }
     36        @Override
     37        public boolean equals(Object obj) {
     38            if (!(obj instanceof WayPair)) return false;
     39            WayPair wp = (WayPair) obj;
     40            return wp.coor.equals(coor);
     41        }
     42    }
     43
     44    protected static int SAME_WAY = 1901;
     45
     46    /** Bag of all ways */
     47    MultiMap<WayPair, OsmPrimitive> ways;
     48
     49    /**
     50     * Constructor
     51     */
     52    public SameWay()
     53    {
     54        super(tr("Same ways")+".",
     55              tr("This test checks that there are no ways with same node coordinates (tags may differ)."));
     56    }
     57
     58
     59    @Override
     60    public void startTest(ProgressMonitor monitor)
     61    {
     62        super.startTest(monitor);
     63        ways = new MultiMap<WayPair, OsmPrimitive>(1000);
     64    }
     65
     66    @Override
     67    public void endTest()
     68    {
     69        super.endTest();
     70        for(Collection<OsmPrimitive> sameway : ways.values() )
     71        {
     72            if( sameway.size() > 1)
     73            {
     74                TestError testError = new TestError(this, Severity.WARNING, tr("Ways with same position"), SAME_WAY, sameway);
     75                errors.add( testError );
     76            }
     77        }
     78        ways = null;
     79    }
     80
     81    @Override
     82    public void visit(Way w)
     83    {
     84        if( !w.isUsable() )
     85            return;
     86        List<Node> wNodes=w.getNodes();
     87        Vector<LatLon> wLat=new Vector<LatLon>(wNodes.size());
     88        for(int i=0;i<wNodes.size();i++) {
     89                 wLat.add(wNodes.get(i).getCoor());
     90        }
     91        WayPair wKey=new WayPair(wLat);
     92        ways.put(wKey, w);
     93    }
     94
     95    /**
     96     * No fix provided
     97     */
     98    @Override
     99    public Command fixError(TestError testError)
     100    {
     101        return null;
     102    }
     103
     104    @Override
     105    public boolean isFixable(TestError testError)
     106    {
     107        return false;
     108    }
     109}
     110 No newline at end of file
  • src/org/openstreetmap/josm/data/validation/tests/DuplicateRelation.java

    Property changes on: src/org/openstreetmap/josm/data/validation/tests/SameWay.java
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1// License: GPL. See LICENSE file for details.
     2package org.openstreetmap.josm.data.validation.tests;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
     6import java.util.Collection;
     7import java.util.HashSet;
     8import java.util.LinkedList;
     9import java.util.List;
     10import java.util.Map;
     11
     12import org.openstreetmap.josm.command.ChangeCommand;
     13import org.openstreetmap.josm.command.Command;
     14import org.openstreetmap.josm.command.DeleteCommand;
     15import org.openstreetmap.josm.command.SequenceCommand;
     16import org.openstreetmap.josm.data.osm.OsmPrimitive;
     17import org.openstreetmap.josm.data.osm.Relation;
     18import org.openstreetmap.josm.data.osm.RelationMember;
     19import org.openstreetmap.josm.data.validation.Severity;
     20import org.openstreetmap.josm.data.validation.Test;
     21import org.openstreetmap.josm.data.validation.TestError;
     22import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     23import org.openstreetmap.josm.tools.MultiMap;
     24
     25/**
     26 * Tests if there are duplicate relations
     27 */
     28public class DuplicateRelation extends Test
     29{
     30
     31    private static class RelationPair {
     32        public List<RelationMember> members;
     33        public Map<String, String> keys;
     34        public RelationPair(List<RelationMember> _members,Map<String, String> _keys) {
     35            members=_members;
     36            keys=_keys;
     37        }
     38        @Override
     39        public int hashCode() {
     40            return members.hashCode()+keys.hashCode();
     41        }
     42        @Override
     43        public boolean equals(Object obj) {
     44            if (!(obj instanceof RelationPair)) return false;
     45            RelationPair rp = (RelationPair) obj;
     46            return rp.members.equals(members) && rp.keys.equals(keys);
     47        }
     48    }
     49
     50    protected static int DUPLICATE_RELATION = 2001;
     51    protected static int SAME_RELATION = 2002;
     52
     53    /** Bag of all relations */
     54    MultiMap<RelationPair, OsmPrimitive> relations;
     55
     56    /** Bag of all relations, regardless of keys */
     57    MultiMap<List<RelationMember>, OsmPrimitive> relations_nokeys;
     58
     59    /**
     60     * Constructor
     61     */
     62    public DuplicateRelation()
     63    {
     64        super(tr("Duplicated relations")+".",
     65              tr("This test checks that there are no relations with same tags and same members with same roles."));
     66    }
     67
     68
     69    @Override
     70    public void startTest(ProgressMonitor monitor)
     71    {
     72        super.startTest(monitor);
     73        relations = new MultiMap<RelationPair, OsmPrimitive>(1000);
     74        relations_nokeys = new MultiMap<List<RelationMember>, OsmPrimitive>(1000);
     75    }
     76
     77    @Override
     78    public void endTest()
     79    {
     80        super.endTest();
     81        for (Collection<OsmPrimitive> duplicated : relations.values() )
     82        {
     83            if( duplicated.size() > 1)
     84            {
     85                TestError testError = new TestError(this, Severity.ERROR, tr("Duplicated relations"), DUPLICATE_RELATION, duplicated);
     86                errors.add( testError );
     87            }
     88        }
     89        relations = null;
     90        for(Collection<OsmPrimitive> duplicated : relations_nokeys.values() )
     91        {
     92            if( duplicated.size() > 1)
     93            {
     94                TestError testError = new TestError(this, Severity.WARNING, tr("Relations with same members"), SAME_RELATION, duplicated);
     95                errors.add( testError );
     96            }
     97        }
     98        relations_nokeys = null;
     99    }
     100
     101    @Override
     102    public void visit(Relation r)
     103    {
     104        if( !r.isUsable() )
     105            return;
     106        List<RelationMember> rMembers=r.getMembers();
     107        Map<String, String> rkeys=r.getKeys();
     108        rkeys.remove("created_by");
     109        RelationPair rKey=new RelationPair(rMembers,rkeys);
     110        relations.put(rKey, r);
     111        relations_nokeys.put(rMembers, r);
     112    }
     113
     114    /**
     115     * Fix the error by removing all but one instance of duplicate relations
     116     */
     117    @Override
     118    public Command fixError(TestError testError)
     119    {
     120        if (testError.getCode() == SAME_RELATION) return null;
     121        Collection<? extends OsmPrimitive> sel = testError.getPrimitives();
     122        HashSet<Relation> rel_fix = new HashSet<Relation>();
     123
     124        for (OsmPrimitive osm : sel)
     125            if (osm instanceof Relation)
     126                rel_fix.add((Relation)osm);
     127
     128        if( rel_fix.size() < 2 )
     129            return null;
     130
     131        long idToKeep = 0;
     132        Relation relationToKeep = rel_fix.iterator().next();
     133        // Only one relation will be kept - the one with lowest positive ID, if such exist
     134        // or one "at random" if no such exists. Rest of the relations will be deleted
     135        for (Relation w: rel_fix) {
     136            if (!w.isNew()) {
     137                if (idToKeep == 0 || w.getId() < idToKeep) {
     138                    idToKeep = w.getId();
     139                    relationToKeep = w;
     140                }
     141            }
     142        }
     143
     144        // Find the relation that is member of one or more relations. (If any)
     145        Relation relationWithRelations = null;
     146        List<Relation> rel_ref = null;
     147        for (Relation w : rel_fix) {
     148            List<Relation> rel = OsmPrimitive.getFilteredList(w.getReferrers(), Relation.class);
     149            if (!rel.isEmpty()) {
     150                if (relationWithRelations != null)
     151                    throw new AssertionError("Cannot fix duplicate relations: More than one relation is member of another relation.");
     152                relationWithRelations = w;
     153                rel_ref = rel;
     154            }
     155        }
     156
     157        Collection<Command> commands = new LinkedList<Command>();
     158
     159        // Fix relations.
     160        if (relationWithRelations != null && relationToKeep != relationWithRelations) {
     161            for (Relation rel : rel_ref) {
     162                Relation newRel = new Relation(rel);
     163                for (int i = 0; i < newRel.getMembers().size(); ++i) {
     164                    RelationMember m = newRel.getMember(i);
     165                    if (relationWithRelations.equals(m.getMember())) {
     166                        newRel.setMember(i, new RelationMember(m.getRole(), relationToKeep));
     167                    }
     168                }
     169                commands.add(new ChangeCommand(rel, newRel));
     170            }
     171        }
     172
     173        //Delete all relations in the list
     174        rel_fix.remove(relationToKeep);
     175        commands.add(new DeleteCommand(rel_fix));
     176        return new SequenceCommand(tr("Delete duplicate relations"), commands);
     177    }
     178
     179    @Override
     180    public boolean isFixable(TestError testError)
     181    {
     182        if (!(testError.getTester() instanceof DuplicateRelation))
     183            return false;
     184
     185        if (testError.getCode() == SAME_RELATION) return false;
     186
     187        // We fix it only if there is no more than one relation that is relation member.
     188        Collection<? extends OsmPrimitive> sel = testError.getPrimitives();
     189        HashSet<Relation> relations = new HashSet<Relation>();
     190
     191        for (OsmPrimitive osm : sel)
     192            if (osm instanceof Relation)
     193                relations.add((Relation)osm);
     194
     195        if (relations.size() < 2)
     196            return false;
     197
     198        int relationsWithRelations = 0;
     199        for (Relation w : relations) {
     200            List<Relation> rel = OsmPrimitive.getFilteredList(w.getReferrers(), Relation.class);
     201            if (!rel.isEmpty()) {
     202                ++relationsWithRelations;
     203            }
     204        }
     205        return (relationsWithRelations <= 1);
     206    }
     207}
     208 No newline at end of file
  • src/org/openstreetmap/josm/data/validation/tests/DuplicateWay.java

    Property changes on: src/org/openstreetmap/josm/data/validation/tests/DuplicateRelation.java
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
    3030/**
    3131 * Tests if there are duplicate ways
    3232 */
    33 public class DuplicateWay extends Test
    34 {
     33public class DuplicateWay extends Test {
    3534
    3635    private static class WayPair {
    3736        public List<LatLon> coor;
  • src/org/openstreetmap/josm/data/validation/OsmValidator.java

     
    2929import org.openstreetmap.josm.data.validation.tests.Coastlines;
    3030import org.openstreetmap.josm.data.validation.tests.CrossingWays;
    3131import org.openstreetmap.josm.data.validation.tests.DuplicateNode;
     32import org.openstreetmap.josm.data.validation.tests.DuplicateRelation;
    3233import org.openstreetmap.josm.data.validation.tests.DuplicateWay;
    3334import org.openstreetmap.josm.data.validation.tests.DuplicatedWayNodes;
    3435import org.openstreetmap.josm.data.validation.tests.MultipolygonTest;
     
    3637import org.openstreetmap.josm.data.validation.tests.NodesWithSameName;
    3738import org.openstreetmap.josm.data.validation.tests.OverlappingWays;
    3839import org.openstreetmap.josm.data.validation.tests.RelationChecker;
     40import org.openstreetmap.josm.data.validation.tests.SameWay;
    3941import org.openstreetmap.josm.data.validation.tests.SelfIntersectingWay;
    4042import org.openstreetmap.josm.data.validation.tests.SimilarNamedWays;
    4143import org.openstreetmap.josm.data.validation.tests.TagChecker;
     
    99101            MultipolygonTest.class, // ID  1601 ..  1699
    100102            RelationChecker.class, // ID  1701 ..  1799
    101103            TurnrestrictionTest.class, // ID  1801 ..  1899
     104            SameWay.class, // ID 1901 .. 1999
     105            DuplicateRelation.class, // ID 2001 .. 2099
    102106    };
    103107
    104108    public OsmValidator() {