Index: /applications/editors/josm/plugins/validator/build.xml
===================================================================
--- /applications/editors/josm/plugins/validator/build.xml	(revision 17478)
+++ /applications/editors/josm/plugins/validator/build.xml	(revision 17479)
@@ -26,5 +26,5 @@
                 <attribute name="Plugin-Description" value="An OSM data validator. It checks for problems in data, and provides fixes for the common ones. Spellcheck integrated for tag names."/>
                 <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/Validator"/>
-                <attribute name="Plugin-Mainversion" value="2005"/>
+                <attribute name="Plugin-Mainversion" value="2067"/>
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
             </manifest>
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/OSMValidatorPlugin.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/OSMValidatorPlugin.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/OSMValidatorPlugin.java	(revision 17479)
@@ -39,4 +39,5 @@
 import org.openstreetmap.josm.plugins.validator.tests.CrossingWays;
 import org.openstreetmap.josm.plugins.validator.tests.DuplicateNode;
+import org.openstreetmap.josm.plugins.validator.tests.DuplicateWay;
 import org.openstreetmap.josm.plugins.validator.tests.DuplicatedWayNodes;
 import org.openstreetmap.josm.plugins.validator.tests.NodesWithSameName;
@@ -97,4 +98,5 @@
             TagChecker.class, // ID 1201 .. 1299
             UnconnectedWays.class, // ID 1301 .. 1399
+            DuplicateWay.class, // ID 1401 .. 1499
     };
 
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/Test.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/Test.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/Test.java	(revision 17479)
@@ -124,5 +124,5 @@
         for (OsmPrimitive p : selection)
         {
-            if( !p.deleted && !p.incomplete )
+            if( p.isUsable() )
                 p.visit(this);
         }
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java	(revision 17479)
@@ -153,5 +153,5 @@
         for (OsmPrimitive o : primitives) {
             // ignore data not yet uploaded
-            if (o.id == 0)
+            if (o.getId() == 0)
                 return null;
             String type = "u";
@@ -162,5 +162,5 @@
             else if (o instanceof Node)
                 type = "n";
-            strings.add(type + "_" + o.id);
+            strings.add(type + "_" + o.getId());
         }
         for (String o : strings) {
@@ -269,5 +269,5 @@
 
         public void visit(OsmPrimitive p) {
-            if (!p.deleted && !p.incomplete) {
+            if (p.isUsable()) {
                 p.visit(this);
             }
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java	(revision 17479)
@@ -415,5 +415,5 @@
 
         public void visit(OsmPrimitive p) {
-            if (!p.deleted && !p.incomplete) {
+            if (p.isUsable()) {
                 p.visit(this);
             }
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/ChangePropertyKeyCommand.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/ChangePropertyKeyCommand.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/ChangePropertyKeyCommand.java	(revision 17479)
@@ -53,7 +53,7 @@
             if(osm.hasKeys())
             {
-                osm.modified = true;
-                String oldValue= osm.get(key);
-                osm.put(newKey, oldValue );
+                osm.setModified(true);
+                String oldValue = osm.get(key);
+                osm.put(newKey, oldValue);
                 osm.remove(key);
             }
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/Coastlines.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/Coastlines.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/Coastlines.java	(revision 17479)
@@ -54,5 +54,5 @@
     public void visit(Way w)
     {
-        if( w.deleted || w.incomplete )
+        if( !w.isUsable() )
             return;
 
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/CrossingWays.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/CrossingWays.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/CrossingWays.java	(revision 17479)
@@ -67,5 +67,5 @@
     public void visit(Way w)
     {
-        if( w.deleted || w.incomplete )
+        if( !w.isUsable() )
             return;
 
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateNode.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateNode.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateNode.java	(revision 17479)
@@ -67,5 +67,5 @@
     public void visit(Node n)
     {
-        if(!n.deleted && !n.incomplete)
+        if(n.isUsable())
             nodes.add(n.getCoor(), n);
     }
@@ -91,5 +91,5 @@
         // select the target node in the same way as in the core action MergeNodesAction, rev.1084
         for (Node n: nodes) {
-            if (n.id > 0) {
+            if (n.getId() > 0) {
                 target = n;
                 break;
@@ -119,5 +119,5 @@
         if (a != null) {
             for (OsmPrimitive osm : del) {
-                if (osm instanceof Node && osm.id != 0) {
+                if (osm instanceof Node && osm.getId() != 0) {
                     Node n = (Node) osm;
                     if (!a.contains(n.getCoor())) {
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateWay.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateWay.java	(revision 17479)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateWay.java	(revision 17479)
@@ -0,0 +1,150 @@
+package org.openstreetmap.josm.plugins.validator.tests;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Vector;
+import java.util.Map;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.DeleteCommand;
+import org.openstreetmap.josm.command.SequenceCommand;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.plugins.validator.Severity;
+import org.openstreetmap.josm.plugins.validator.Test;
+import org.openstreetmap.josm.plugins.validator.TestError;
+import org.openstreetmap.josm.plugins.validator.util.Bag;
+/**
+ * Tests if there are duplicate ways
+ */
+public class DuplicateWay extends Test
+{
+
+    private class WayPair {
+        public List<LatLon> coor;
+        public Map<String, String> keys;
+        public WayPair(List<LatLon> _coor,Map<String, String> _keys) {
+            coor=_coor;
+            keys=_keys;
+        }
+        @Override
+        public int hashCode() {
+            return coor.hashCode()+keys.hashCode();
+        }
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof WayPair)) return false;
+            WayPair wp = (WayPair) obj;
+            return wp.coor.equals(coor) && wp.keys.equals(keys);
+        }
+    }
+
+    protected static int DUPLICATE_WAY = 1401;
+
+    /** Bag of all ways */
+    Bag<WayPair, OsmPrimitive> ways;
+
+    /**
+     * Constructor
+     */
+    public DuplicateWay()
+    {
+        super(tr("Duplicated ways")+".",
+              tr("This test checks that there are no ways with same tags and same node coordinates."));
+    }
+
+
+    @Override
+    public void startTest()
+    {
+        ways = new Bag<WayPair, OsmPrimitive>(1000);
+    }
+
+    @Override
+    public void endTest()
+    {
+        for(List<OsmPrimitive> duplicated : ways.values() )
+        {
+            if( duplicated.size() > 1)
+            {
+                TestError testError = new TestError(this, Severity.ERROR, tr("Duplicated ways"), DUPLICATE_WAY, duplicated);
+                errors.add( testError );
+            }
+        }
+        ways = null;
+    }
+
+    @Override
+    public void visit(Way w)
+    {
+        if( !w.isUsable() )
+            return;
+        List<Node> wNodes=w.getNodes();
+        Vector<LatLon> wLat=new Vector<LatLon>(wNodes.size());
+        for(int i=0;i<wNodes.size();i++) {
+                 wLat.add(wNodes.get(i).getCoor());
+        }
+        Map<String, String> wkeys=w.getKeys();
+        wkeys.remove("created_by");
+        WayPair wKey=new WayPair(wLat,wkeys);
+        ways.add(wKey, w);
+    }
+
+    /**
+     * Fix the error by removing all but one instance of duplicate ways
+     */
+    @Override
+    public Command fixError(TestError testError)
+    {
+        Collection<? extends OsmPrimitive> sel = testError.getPrimitives();
+        LinkedList<Way> ways = new LinkedList<Way>();
+
+        for (OsmPrimitive osm : sel)
+            if (osm instanceof Way)
+                ways.add((Way)osm);
+
+        if( ways.size() < 2 )
+            return null;
+
+        long idToKeep = 0;
+        // Only one way will be kept - the one with lowest positive ID, if such exist
+        // or one "at random" if no such exists. Rest of the ways will be deleted
+        for (Way w: ways) {
+            if (w.getId() > 0) {
+                if (idToKeep == 0 || w.getId() < idToKeep) idToKeep = w.getId();
+            }
+        }
+
+        if (idToKeep > 0) {
+            //Remove chosen way from the list, rest of ways in the list will be deleted
+            for (Way w: ways) {
+                if (w.getId() == idToKeep) {
+                        ways.remove(w);
+                    break;
+                }
+            }
+        } else {
+            //Remove first way from the list, delete the rest
+            ways.remove(0);
+        }
+
+        //Delete all ways in the list
+        //Note: nodes are not deleted, these can be detected and deleted at next pass
+        Collection<Command> commands = new LinkedList<Command>();
+        commands.add(new DeleteCommand(ways));
+        Main.main.undoRedo.add(new SequenceCommand(tr("Delete duplicate ways"), commands));
+        return null;
+    }
+
+    @Override
+    public boolean isFixable(TestError testError)
+    {
+        return (testError.getTester() instanceof DuplicateWay);
+    }
+}
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicatedWayNodes.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicatedWayNodes.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicatedWayNodes.java	(revision 17479)
@@ -25,5 +25,5 @@
 
     @Override public void visit(Way w) {
-        if (w.deleted || w.incomplete) return;
+        if (!w.isUsable()) return;
 
         Node lastN = null;
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/NodesWithSameName.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/NodesWithSameName.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/NodesWithSameName.java	(revision 17479)
@@ -28,5 +28,5 @@
 
     @Override public void visit(Node n) {
-        if (n.deleted || n.incomplete) return;
+        if (!n.isUsable()) return;
 
         String name = n.get("name");
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/SimilarNamedWays.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/SimilarNamedWays.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/SimilarNamedWays.java	(revision 17479)
@@ -55,5 +55,5 @@
     public void visit(Way w)
     {
-        if( w.deleted || w.incomplete )
+        if( !w.isUsable() )
             return;
 
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnclosedWays.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnclosedWays.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnclosedWays.java	(revision 17479)
@@ -69,5 +69,5 @@
         mode = 0;
 
-        if (w.deleted || w.incomplete)
+        if (!w.isUsable())
             return;
 
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnconnectedWays.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnconnectedWays.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnconnectedWays.java	(revision 17479)
@@ -190,5 +190,5 @@
     public void visit(Way w)
     {
-        if( w.deleted || w.incomplete )
+        if( !w.isUsable() )
             return;
         int size = w.getNodesCount();
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedNode.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedNode.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedNode.java	(revision 17479)
@@ -52,5 +52,5 @@
         if (partialSelection) {
             for (OsmPrimitive p : selection) {
-                if (!p.deleted && !p.incomplete && p instanceof Node) {
+                if (p.isUsable() && p instanceof Node) {
                     p.visit(this);
                 }
@@ -61,5 +61,5 @@
         } else {
             for (OsmPrimitive p : selection) {
-                if (!p.deleted && !p.incomplete) {
+                if (p.isUsable()) {
                     p.visit(this);
                 }
@@ -71,5 +71,5 @@
     public void visit(Node n)
     {
-        if(!n.incomplete && !n.deleted && !n.isTagged())
+        if(n.isUsable() && !n.isTagged())
             emptyNodes.add(n);
     }
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedWay.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedWay.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedWay.java	(revision 17479)
@@ -63,8 +63,8 @@
     public void visit(Way w)
     {
-        if (w.deleted || w.incomplete) return;
+        if (!w.isUsable()) return;
 
         Map<String, String> tags = w.getKeys();
-        if( tags != null )
+        if( tags.size() != 0 )
         {
             String highway = tags.get("highway");
@@ -117,12 +117,10 @@
         for (final Relation r : Main.main.getCurrentDataSet().relations)
         {
-            if(!r.deleted && !r.incomplete && r.getKeys() != null
-            && "multipolygon".equals(r.get("type")))
+            if(r.isUsable() && "multipolygon".equals(r.get("type")))
             {
                 for (RelationMember m : r.members)
                 {
                     if(m.member != null && m.member instanceof Way &&
-                    !m.member.deleted && !m.member.incomplete
-                    && !m.member.isTagged())
+                    m.member.isUsable() && !m.member.isTagged())
                         multipolygonways.add((Way)m.member);
                 }
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/WronglyOrderedWays.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/WronglyOrderedWays.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/WronglyOrderedWays.java	(revision 17479)
@@ -53,5 +53,5 @@
         int type;
 
-        if( w.deleted || w.incomplete )
+        if( !w.isUsable() )
             return;
 
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/NameVisitor.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/NameVisitor.java	(revision 17478)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/NameVisitor.java	(revision 17479)
@@ -79,5 +79,5 @@
     private void addId(OsmPrimitive osm) {
         if (Main.pref.getBoolean("osm-primitives.showid"))
-            name += tr(" [id: {0}]", osm.id);
+            name += tr(" [id: {0}]", osm.getId());
     }
 }
