Index: /applications/editors/josm/plugins/validator/build.xml
===================================================================
--- /applications/editors/josm/plugins/validator/build.xml	(revision 17584)
+++ /applications/editors/josm/plugins/validator/build.xml	(revision 17585)
@@ -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="2082"/>
+                <attribute name="Plugin-Mainversion" value="2095"/>
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
             </manifest>
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 17584)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java	(revision 17585)
@@ -11,7 +11,11 @@
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.Set;
 
@@ -21,4 +25,5 @@
 import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
 import javax.swing.event.TreeSelectionEvent;
 import javax.swing.event.TreeSelectionListener;
@@ -33,7 +38,12 @@
 import org.openstreetmap.josm.data.osm.WaySegment;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.OsmTransferException;
+import org.openstreetmap.josm.plugins.validator.tests.DuplicateNode;
 import org.openstreetmap.josm.tools.Shortcut;
+import org.xml.sax.SAXException;
 
 /**
@@ -133,4 +143,7 @@
 
         Set<DefaultMutableTreeNode> processedNodes = new HashSet<DefaultMutableTreeNode>();
+               
+        DuplicateNode.clearBackreferences();
+        LinkedList<TestError> errorsToFix = new LinkedList<TestError>();
         for (TreePath path : selectionPaths) {
             DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
@@ -147,17 +160,13 @@
                 Object nodeInfo = childNode.getUserObject();
                 if (nodeInfo instanceof TestError) {
-                    TestError error = (TestError) nodeInfo;
-                    Command fixCommand = error.getFix();
-                    if (fixCommand != null) {
-                        Main.main.undoRedo.add(fixCommand);
-                        error.setIgnored(true);
-                    }
+                	errorsToFix.add((TestError)nodeInfo);
                 }
             }
         }
-
-        Main.map.repaint();
-        tree.resetErrors();
-        DataSet.fireSelectionChanged(Main.main.getCurrentDataSet().getSelected());
+        
+        // run fix task asynchronously
+        //
+        FixTask fixTask = new FixTask(errorsToFix);
+        Main.worker.submit(fixTask);
     }
 
@@ -436,3 +445,76 @@
         tree.setFilter(filter);
     }
+    
+    /**
+     * Task for fixing a collection of {@see TestError}s. Can be run asynchronously. 
+     * 
+     *
+     */
+    class FixTask extends PleaseWaitRunnable {
+    	private Collection<TestError> testErrors;
+    	private boolean canceled;
+    	private LinkedList<Command> fixCommands;
+    
+    	
+    	public FixTask(Collection<TestError> testErrors) {
+    		super(tr("Fixing errors ..."), false /* don't ignore exceptions */);
+    		this.testErrors = testErrors == null ? new ArrayList<TestError> (): testErrors;
+    		fixCommands = new LinkedList<Command>();
+    	}
+
+		@Override
+		protected void cancel() {
+			this.canceled = true; 			
+		}
+
+		@Override
+		protected void finish() {
+			// do nothing
+		}
+ 		
+		@Override
+		protected void realRun() throws SAXException, IOException,
+				OsmTransferException {
+			ProgressMonitor monitor = getProgressMonitor();
+			try {				
+				monitor.setTicksCount(testErrors.size());
+				int i=0;
+				for (TestError error: testErrors) {
+					i++;
+					monitor.subTask(tr("Fixing ({0}/{1}): ''{2}''", i, testErrors.size(),error.getMessage()));
+					if (this.canceled) 
+						return;
+					final Command fixCommand = error.getFix();
+                    if (fixCommand != null) {
+                    	fixCommands.add(fixCommand);
+        				SwingUtilities.invokeAndWait(
+        						new Runnable() {
+        							public void run() {
+        								Main.main.undoRedo.add(fixCommand);
+        							}
+        						}
+        				);
+                        error.setIgnored(true);
+                    }
+                    monitor.worked(1);
+				}		
+				monitor.subTask(tr("Updating map ..."));
+				SwingUtilities.invokeAndWait(new Runnable() {
+					public void run() {
+						Main.map.repaint();
+						tree.resetErrors();
+						DataSet.fireSelectionChanged(Main.main.getCurrentDataSet().getSelected());
+					}
+				});
+			} catch(InterruptedException e) { 
+				// FIXME: signature of realRun should have a generic checked exception we
+				// could throw here
+				throw new RuntimeException(e);
+			} catch(InvocationTargetException e) {
+				throw new RuntimeException(e);
+			} finally {
+				monitor.finishTask();
+			}			
+		}
+    }
 }
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 17584)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateNode.java	(revision 17585)
@@ -16,4 +16,5 @@
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.BackreferencedDataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -28,6 +29,20 @@
  * @author frsantos
  */
-public class DuplicateNode extends Test
-{
+public class DuplicateNode extends Test{
+	
+	private static BackreferencedDataSet backreferences;
+	
+	public static BackreferencedDataSet getBackreferenceDataSet() {
+		if (backreferences == null) {
+			backreferences = new BackreferencedDataSet(Main.main.getEditLayer().data);
+			backreferences.build();
+		}
+		return backreferences;
+	}
+	
+	public static void clearBackreferences() {
+		backreferences = null;
+	}
+	
     protected static int DUPLICATE_NODE = 1;
 
@@ -92,29 +107,12 @@
     public Command fixError(TestError testError)
     {
-        Collection<? extends OsmPrimitive> sel = testError.getPrimitives();
-        LinkedList<Node> nodes = new LinkedList<Node>();
+        Collection<OsmPrimitive> sel = new LinkedList<OsmPrimitive>(testError.getPrimitives());
+        LinkedList<Node> nodes = new LinkedList<Node>(OsmPrimitive.getFilteredList(sel, Node.class));
+        MergeNodesAction mergeAction  = new MergeNodesAction();
+        Node target = mergeAction.selectTargetNode(nodes);
+        if(checkAndConfirmOutlyingDeletes(nodes))
+            return mergeAction.mergeNodes(Main.main.getEditLayer(),getBackreferenceDataSet(), nodes, target);
 
-        for (OsmPrimitive osm : sel)
-            if (osm instanceof Node)
-                nodes.add((Node)osm);
-
-        if( nodes.size() < 2 )
-            return null;
-
-        Node target = null;
-        // select the target node in the same way as in the core action MergeNodesAction, rev.1084
-        for (Node n: nodes) {
-            if (n.getId() > 0) {
-                target = n;
-                break;
-            }
-        }
-        if (target == null)
-            target = nodes.iterator().next();
-
-        if(checkAndConfirmOutlyingDeletes(nodes))
-            new MergeNodesAction().mergeNodes(nodes, target);
-
-        return null; // undoRedo handling done in mergeNodes
+        return null;// undoRedo handling done in mergeNodes
     }
 
