Index: trunk/src/org/openstreetmap/josm/actions/downloadtasks/AbstractChangesetDownloadTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/downloadtasks/AbstractChangesetDownloadTask.java	(revision 10126)
+++ trunk/src/org/openstreetmap/josm/actions/downloadtasks/AbstractChangesetDownloadTask.java	(revision 10129)
@@ -3,4 +3,5 @@
 
 import java.awt.Component;
+import java.lang.reflect.InvocationTargetException;
 import java.net.URL;
 import java.util.HashSet;
@@ -8,10 +9,15 @@
 import java.util.concurrent.Future;
 
+import javax.swing.SwingUtilities;
+
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.osm.ChangesetCache;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.OsmServerChangesetReader;
+import org.openstreetmap.josm.tools.ExceptionUtil;
+import org.openstreetmap.josm.tools.bugreport.BugReportExceptionHandler;
 
 /**
@@ -46,4 +52,36 @@
             lastException = e;
             setFailed(true);
+        }
+
+        protected final void updateChangesets() {
+            // update the global changeset cache with the downloaded changesets.
+            // this will trigger change events which views are listening to. They
+            // will update their views accordingly.
+            //
+            // Run on the EDT because UI updates are triggered.
+            //
+            Runnable r = new Runnable() {
+                @Override public void run() {
+                    ChangesetCache.getInstance().update(downloadedChangesets);
+                }
+            };
+            if (SwingUtilities.isEventDispatchThread()) {
+                r.run();
+            } else {
+                try {
+                    SwingUtilities.invokeAndWait(r);
+                } catch (InterruptedException e) {
+                    Main.warn("InterruptedException in "+getClass().getSimpleName()+" while updating changeset cache");
+                } catch (InvocationTargetException e) {
+                    Throwable t = e.getTargetException();
+                    if (t instanceof RuntimeException) {
+                        BugReportExceptionHandler.handleException(t);
+                    } else if (t instanceof Exception) {
+                        ExceptionUtil.explainException(e);
+                    } else {
+                        BugReportExceptionHandler.handleException(t);
+                    }
+                }
+            }
         }
     }
Index: trunk/src/org/openstreetmap/josm/actions/downloadtasks/ChangesetHeaderDownloadTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/downloadtasks/ChangesetHeaderDownloadTask.java	(revision 10126)
+++ trunk/src/org/openstreetmap/josm/actions/downloadtasks/ChangesetHeaderDownloadTask.java	(revision 10129)
@@ -6,11 +6,8 @@
 import java.awt.Component;
 import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
-
-import javax.swing.SwingUtilities;
 
 import org.openstreetmap.josm.Main;
@@ -20,6 +17,4 @@
 import org.openstreetmap.josm.io.OsmTransferException;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
-import org.openstreetmap.josm.tools.ExceptionUtil;
-import org.openstreetmap.josm.tools.bugreport.BugReportExceptionHandler;
 import org.xml.sax.SAXException;
 
@@ -74,29 +69,5 @@
                 ExceptionDialogUtil.explainException(lastException);
             }
-            Runnable r = new Runnable() {
-                @Override
-                public void run() {
-                    ChangesetCache.getInstance().update(downloadedChangesets);
-                }
-            };
-
-            if (SwingUtilities.isEventDispatchThread()) {
-                r.run();
-            } else {
-                try {
-                    SwingUtilities.invokeAndWait(r);
-                } catch (InterruptedException e) {
-                    Main.warn("InterruptedException in "+getClass().getSimpleName()+" while updating changeset cache");
-                } catch (InvocationTargetException e) {
-                    Throwable t = e.getTargetException();
-                    if (t instanceof RuntimeException) {
-                        BugReportExceptionHandler.handleException(t);
-                    } else if (t instanceof Exception) {
-                        ExceptionUtil.explainException(e);
-                    } else {
-                        BugReportExceptionHandler.handleException(t);
-                    }
-                }
-            }
+            updateChangesets();
         }
     }
Index: trunk/src/org/openstreetmap/josm/actions/downloadtasks/ChangesetQueryTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/downloadtasks/ChangesetQueryTask.java	(revision 10126)
+++ trunk/src/org/openstreetmap/josm/actions/downloadtasks/ChangesetQueryTask.java	(revision 10129)
@@ -6,11 +6,8 @@
 import java.awt.Component;
 import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
 
 import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.osm.ChangesetCache;
 import org.openstreetmap.josm.data.osm.UserInfo;
 import org.openstreetmap.josm.gui.JosmUserIdentityManager;
@@ -22,5 +19,4 @@
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.ExceptionUtil;
-import org.openstreetmap.josm.tools.bugreport.BugReportExceptionHandler;
 import org.xml.sax.SAXException;
 
@@ -103,34 +99,5 @@
                 return;
             }
-
-            // update the global changeset cache with the downloaded changesets.
-            // this will trigger change events which views are listening to. They
-            // will update their views accordingly.
-            //
-            // Run on the EDT because UI updates are triggered.
-            //
-            Runnable r = new Runnable() {
-                @Override public void run() {
-                    ChangesetCache.getInstance().update(downloadedChangesets);
-                }
-            };
-            if (SwingUtilities.isEventDispatchThread()) {
-                r.run();
-            } else {
-                try {
-                    SwingUtilities.invokeAndWait(r);
-                } catch (InterruptedException e) {
-                    Main.warn("InterruptedException in "+getClass().getSimpleName()+" while updating changeset cache");
-                } catch (InvocationTargetException e) {
-                    Throwable t = e.getTargetException();
-                    if (t instanceof RuntimeException) {
-                        BugReportExceptionHandler.handleException(t);
-                    } else if (t instanceof Exception) {
-                        ExceptionUtil.explainException(e);
-                    } else {
-                        BugReportExceptionHandler.handleException(t);
-                    }
-                }
-            }
+            updateChangesets();
         }
 
Index: trunk/src/org/openstreetmap/josm/gui/io/AbstractPrimitiveTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/AbstractPrimitiveTask.java	(revision 10129)
+++ trunk/src/org/openstreetmap/josm/gui/io/AbstractPrimitiveTask.java	(revision 10129)
@@ -0,0 +1,196 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.io;
+
+import static org.openstreetmap.josm.tools.CheckParameterUtil.ensureParameterNotNull;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.AutoScaleAction;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.DataSetMerger;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.PrimitiveId;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.gui.ExceptionDialogUtil;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
+import org.openstreetmap.josm.io.OsmServerObjectReader;
+import org.openstreetmap.josm.io.OsmTransferException;
+import org.xml.sax.SAXException;
+
+/**
+ * Abstract superclass of download/update primitives tasks.
+ * @since 10129
+ */
+public abstract class AbstractPrimitiveTask extends PleaseWaitRunnable {
+
+    protected final DataSet ds = new DataSet();
+    protected boolean canceled;
+    protected Exception lastException;
+    private Set<PrimitiveId> missingPrimitives;
+
+    protected final OsmDataLayer layer;
+    protected MultiFetchServerObjectReader multiObjectReader;
+    protected OsmServerObjectReader objectReader;
+
+    private boolean zoom;
+    private boolean downloadRelations;
+    private boolean fullRelation;
+
+    protected AbstractPrimitiveTask(String title, OsmDataLayer layer) {
+        this(title, new PleaseWaitProgressMonitor(title), layer);
+    }
+
+    protected AbstractPrimitiveTask(String title, ProgressMonitor progressMonitor, OsmDataLayer layer) {
+        super(title, progressMonitor, false);
+        ensureParameterNotNull(layer, "layer");
+        this.layer = layer;
+    }
+
+    protected abstract void initMultiFetchReader(MultiFetchServerObjectReader reader);
+
+    /**
+     * Sets whether the map view should zoom to impacted primitives at the end.
+     * @param zoom {@code true} if the map view should zoom to impacted primitives at the end
+     * @return {@code this}
+     */
+    public final AbstractPrimitiveTask setZoom(boolean zoom) {
+        this.zoom = zoom;
+        return this;
+    }
+
+    /**
+     * Sets whether .
+     * @param downloadRelations {@code true} if
+     * @param fullRelation {@code true} if a full download is required,
+     *                     i.e., a download including the immediate children of a relation.
+     * @return {@code this}
+     */
+    public final AbstractPrimitiveTask setDownloadRelations(boolean downloadRelations, boolean fullRelation) {
+        this.downloadRelations = downloadRelations;
+        this.fullRelation = fullRelation;
+        return this;
+    }
+
+    /**
+     * Replies the set of ids of all primitives for which a fetch request to the
+     * server was submitted but which are not available from the server (the server
+     * replied a return code of 404)
+     *
+     * @return the set of ids of missing primitives
+     */
+    public Set<PrimitiveId> getMissingPrimitives() {
+        return missingPrimitives;
+    }
+
+    @Override
+    protected void realRun() throws SAXException, IOException, OsmTransferException {
+        DataSet theirDataSet;
+        try {
+            synchronized (this) {
+                if (canceled)
+                    return;
+                multiObjectReader = MultiFetchServerObjectReader.create();
+            }
+            initMultiFetchReader(multiObjectReader);
+            theirDataSet = multiObjectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
+            missingPrimitives = multiObjectReader.getMissingPrimitives();
+            synchronized (this) {
+                multiObjectReader = null;
+            }
+            new DataSetMerger(ds, theirDataSet).merge();
+
+            if (downloadRelations) {
+                loadIncompleteRelationMembers();
+            }
+
+            loadIncompleteNodes();
+        } catch (Exception e) {
+            if (canceled)
+                return;
+            lastException = e;
+        }
+    }
+
+    protected void loadIncompleteRelationMembers() throws OsmTransferException {
+        // if incomplete relation members exist, download them too
+        for (Relation r : ds.getRelations()) {
+            if (canceled)
+                return;
+            // Relations may be incomplete in case of nested relations if child relations are accessed before their parent
+            // (it may happen because "relations" has no deterministic sort order, see #10388)
+            if (r.isIncomplete() || r.hasIncompleteMembers()) {
+                synchronized (this) {
+                    if (canceled)
+                        return;
+                    objectReader = new OsmServerObjectReader(r.getId(), OsmPrimitiveType.RELATION, fullRelation);
+                }
+                DataSet theirDataSet = objectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
+                synchronized (this) {
+                    objectReader = null;
+                }
+                new DataSetMerger(ds, theirDataSet).merge();
+            }
+        }
+    }
+
+    protected void loadIncompleteNodes() throws OsmTransferException {
+        // a way loaded with MultiFetch may have incomplete nodes because at least one of its
+        // nodes isn't present in the local data set. We therefore fully load all ways with incomplete nodes.
+        for (Way w : ds.getWays()) {
+            if (canceled)
+                return;
+            if (w.hasIncompleteNodes()) {
+                synchronized (this) {
+                    if (canceled)
+                        return;
+                    objectReader = new OsmServerObjectReader(w.getId(), OsmPrimitiveType.WAY, true /* full */);
+                }
+                DataSet theirDataSet = objectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
+                synchronized (this) {
+                    objectReader = null;
+                }
+                new DataSetMerger(ds, theirDataSet).merge();
+            }
+        }
+    }
+
+    @Override
+    protected void cancel() {
+        canceled = true;
+        synchronized (this) {
+            if (multiObjectReader != null) {
+                multiObjectReader.cancel();
+            }
+            if (objectReader != null) {
+                objectReader.cancel();
+            }
+        }
+    }
+
+    @Override
+    protected void finish() {
+        if (canceled)
+            return;
+        if (lastException != null) {
+            ExceptionDialogUtil.explainException(lastException);
+            return;
+        }
+        GuiHelper.runInEDTAndWait(new Runnable() {
+            @Override
+            public void run() {
+                layer.mergeFrom(ds);
+                if (zoom && Main.map != null)
+                    AutoScaleAction.zoomTo(ds.allPrimitives());
+                layer.onPostDownloadFromServer();
+            }
+        });
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/io/DownloadPrimitivesTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/DownloadPrimitivesTask.java	(revision 10126)
+++ trunk/src/org/openstreetmap/josm/gui/io/DownloadPrimitivesTask.java	(revision 10129)
@@ -2,30 +2,16 @@
 package org.openstreetmap.josm.gui.io;
 
-import static org.openstreetmap.josm.tools.CheckParameterUtil.ensureParameterNotNull;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.io.IOException;
 import java.util.List;
-import java.util.Set;
 
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.AutoScaleAction;
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.DataSetMerger;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.PrimitiveId;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.ExceptionDialogUtil;
-import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
-import org.openstreetmap.josm.io.OsmServerObjectReader;
-import org.openstreetmap.josm.io.OsmTransferException;
-import org.xml.sax.SAXException;
 
 /**
@@ -33,16 +19,7 @@
  * @since 4081
  */
-public class DownloadPrimitivesTask extends PleaseWaitRunnable {
-    private DataSet ds;
-    private boolean canceled;
-    private Exception lastException;
+public class DownloadPrimitivesTask extends AbstractPrimitiveTask {
+
     private final List<PrimitiveId> ids;
-
-    private Set<PrimitiveId> missingPrimitives;
-
-    private final OsmDataLayer layer;
-    private final boolean fullRelation;
-    private MultiFetchServerObjectReader multiObjectReader;
-    private OsmServerObjectReader objectReader;
 
     /**
@@ -73,43 +50,11 @@
     public DownloadPrimitivesTask(OsmDataLayer layer, List<PrimitiveId> ids, boolean fullRelation,
             ProgressMonitor progressMonitor) {
-        super(tr("Download objects"), progressMonitor, false /* don't ignore exception */);
-        ensureParameterNotNull(layer, "layer");
+        super(tr("Download objects"), progressMonitor, layer);
         this.ids = ids;
-        this.layer = layer;
-        this.fullRelation = fullRelation;
+        setZoom(true);
+        setDownloadRelations(true, fullRelation);
     }
 
     @Override
-    protected void cancel() {
-        canceled = true;
-        synchronized (this) {
-            if (multiObjectReader != null) {
-                multiObjectReader.cancel();
-            }
-            if (objectReader != null) {
-                objectReader.cancel();
-            }
-        }
-    }
-
-    @Override
-    protected void finish() {
-        if (canceled)
-            return;
-        if (lastException != null) {
-            ExceptionDialogUtil.explainException(lastException);
-            return;
-        }
-        GuiHelper.runInEDTAndWait(new Runnable() {
-            @Override
-            public void run() {
-                layer.mergeFrom(ds);
-                if (Main.map != null)
-                    AutoScaleAction.zoomTo(ds.allPrimitives());
-                layer.onPostDownloadFromServer();
-            }
-        });
-    }
-
     protected void initMultiFetchReader(MultiFetchServerObjectReader reader) {
         getProgressMonitor().indeterminateSubTask(tr("Initializing nodes to download ..."));
@@ -133,78 +78,3 @@
         }
     }
-
-    @Override
-    protected void realRun() throws SAXException, IOException, OsmTransferException {
-        this.ds = new DataSet();
-        DataSet theirDataSet;
-        try {
-            synchronized (this) {
-                if (canceled) return;
-                multiObjectReader = MultiFetchServerObjectReader.create();
-            }
-            initMultiFetchReader(multiObjectReader);
-            theirDataSet = multiObjectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
-            missingPrimitives = multiObjectReader.getMissingPrimitives();
-            synchronized (this) {
-                multiObjectReader = null;
-            }
-            DataSetMerger merger = new DataSetMerger(ds, theirDataSet);
-            merger.merge();
-
-            // if incomplete relation members exist, download them too
-            for (Relation r : ds.getRelations()) {
-                if (canceled) return;
-                // Relations may be incomplete in case of nested relations if child relations are accessed before their parent
-                // (it may happen because "relations" has no deterministic sort order, see #10388)
-                if (r.isIncomplete() || r.hasIncompleteMembers()) {
-                    synchronized (this) {
-                        if (canceled) return;
-                        objectReader = new OsmServerObjectReader(r.getId(), OsmPrimitiveType.RELATION, fullRelation);
-                    }
-                    theirDataSet = objectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
-                    synchronized (this) {
-                        objectReader = null;
-                    }
-                    merger = new DataSetMerger(ds, theirDataSet);
-                    merger.merge();
-                }
-            }
-
-            // a way loaded with MultiFetch may have incomplete nodes because at least one of its
-            // nodes isn't present in the local data set. We therefore fully load all
-            // ways with incomplete nodes.
-            //
-            for (Way w : ds.getWays()) {
-                if (canceled) return;
-                if (w.hasIncompleteNodes()) {
-                    synchronized (this) {
-                        if (canceled) return;
-                        objectReader = new OsmServerObjectReader(w.getId(), OsmPrimitiveType.WAY, true /* full */);
-                    }
-                    theirDataSet = objectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
-                    synchronized (this) {
-                        objectReader = null;
-                    }
-                    merger = new DataSetMerger(ds, theirDataSet);
-                    merger.merge();
-                }
-            }
-
-        } catch (Exception e) {
-            if (canceled) return;
-            lastException = e;
-        }
-    }
-
-    /**
-     * replies the set of ids of all primitives for which a fetch request to the
-     * server was submitted but which are not available from the server (the server
-     * replied a return code of 404)
-     *
-     * @return the set of ids of missing primitives
-     */
-    public Set<PrimitiveId> getMissingPrimitives() {
-        return missingPrimitives;
-    }
-
 }
Index: trunk/src/org/openstreetmap/josm/gui/io/UpdatePrimitivesTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UpdatePrimitivesTask.java	(revision 10126)
+++ trunk/src/org/openstreetmap/josm/gui/io/UpdatePrimitivesTask.java	(revision 10129)
@@ -2,43 +2,26 @@
 package org.openstreetmap.josm.gui.io;
 
-import static org.openstreetmap.josm.tools.CheckParameterUtil.ensureParameterNotNull;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
 
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.DataSetMerger;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.ExceptionDialogUtil;
-import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
-import org.openstreetmap.josm.io.OsmServerObjectReader;
-import org.openstreetmap.josm.io.OsmTransferException;
-import org.xml.sax.SAXException;
 
 /**
  * The asynchronous task for updating a collection of objects using multi fetch.
- *
+ * @since 2599
  */
-public class UpdatePrimitivesTask extends PleaseWaitRunnable {
-    private DataSet ds;
-    private boolean canceled;
-    private Exception lastException;
+public class UpdatePrimitivesTask extends AbstractPrimitiveTask {
+
     private final Collection<? extends OsmPrimitive> toUpdate;
-    private final OsmDataLayer layer;
-    private MultiFetchServerObjectReader multiObjectReader;
-    private OsmServerObjectReader objectReader;
 
     /**
-     * Creates the  task
+     * Constructs a new {@code UpdatePrimitivesTask}.
      *
      * @param layer the layer in which primitives are updated. Must not be null.
@@ -48,41 +31,6 @@
      */
     public UpdatePrimitivesTask(OsmDataLayer layer, Collection<? extends OsmPrimitive> toUpdate) {
-        super(tr("Update objects"), false /* don't ignore exception */);
-        ensureParameterNotNull(layer, "layer");
-        if (toUpdate == null) {
-            toUpdate = Collections.emptyList();
-        }
-        this.layer = layer;
-        this.toUpdate = toUpdate;
-    }
-
-    @Override
-    protected void cancel() {
-        canceled = true;
-        synchronized (this) {
-            if (multiObjectReader != null) {
-                multiObjectReader.cancel();
-            }
-            if (objectReader != null) {
-                objectReader.cancel();
-            }
-        }
-    }
-
-    @Override
-    protected void finish() {
-        if (canceled)
-            return;
-        if (lastException != null) {
-            ExceptionDialogUtil.explainException(lastException);
-            return;
-        }
-        GuiHelper.runInEDTAndWait(new Runnable() {
-            @Override
-            public void run() {
-                layer.mergeFrom(ds);
-                layer.onPostDownloadFromServer();
-            }
-        });
+        super(tr("Update objects"), layer);
+        this.toUpdate = toUpdate != null ? toUpdate : Collections.<OsmPrimitive>emptyList();
     }
 
@@ -117,45 +65,8 @@
 
     @Override
-    protected void realRun() throws SAXException, IOException, OsmTransferException {
-        this.ds = new DataSet();
-        DataSet theirDataSet;
-        try {
-            synchronized (this) {
-                if (canceled) return;
-                multiObjectReader = MultiFetchServerObjectReader.create();
-            }
-            initMultiFetchReaderWithNodes(multiObjectReader);
-            initMultiFetchReaderWithWays(multiObjectReader);
-            initMultiFetchReaderWithRelations(multiObjectReader);
-            theirDataSet = multiObjectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
-            synchronized (this) {
-                multiObjectReader = null;
-            }
-            DataSetMerger merger = new DataSetMerger(ds, theirDataSet);
-            merger.merge();
-            // a way loaded with MultiFetch may have incomplete nodes because at least one of its
-            // nodes isn't present in the local data set. We therefore fully load all
-            // ways with incomplete nodes.
-            //
-            for (Way w : ds.getWays()) {
-                if (canceled) return;
-                if (w.hasIncompleteNodes()) {
-                    synchronized (this) {
-                        if (canceled) return;
-                        objectReader = new OsmServerObjectReader(w.getId(), OsmPrimitiveType.WAY, true /* full */);
-                    }
-                    theirDataSet = objectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
-                    synchronized (this) {
-                        objectReader = null;
-                    }
-                    merger = new DataSetMerger(ds, theirDataSet);
-                    merger.merge();
-                }
-            }
-        } catch (Exception e) {
-            if (canceled)
-                return;
-            lastException = e;
-        }
+    protected void initMultiFetchReader(MultiFetchServerObjectReader reader) {
+        initMultiFetchReaderWithNodes(reader);
+        initMultiFetchReaderWithWays(reader);
+        initMultiFetchReaderWithRelations(reader);
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetMenu.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetMenu.java	(revision 10126)
+++ trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetMenu.java	(revision 10129)
@@ -123,32 +123,10 @@
                 sortarray.add((JMenuItem) item);
                 if (i == items.length-1) {
-                    Collections.sort(sortarray, comp);
-                    int pos = 0;
-                    for (JMenuItem menuItem : sortarray) {
-                        int oldPos;
-                        if (lastSeparator == 0) {
-                            oldPos = pos;
-                        } else {
-                            oldPos = pos+lastSeparator+1;
-                        }
-                        menu.add(menuItem, oldPos);
-                        pos++;
-                    }
+                    handleMenuItem(menu, comp, sortarray, lastSeparator);
                     sortarray = new ArrayList<>();
                     lastSeparator = 0;
                 }
             } else if (item instanceof JSeparator) {
-                Collections.sort(sortarray, comp);
-                int pos = 0;
-                for (JMenuItem menuItem : sortarray) {
-                    int oldPos;
-                    if (lastSeparator == 0) {
-                        oldPos = pos;
-                    } else {
-                        oldPos = pos+lastSeparator+1;
-                    }
-                    menu.add(menuItem, oldPos);
-                    pos++;
-                }
+                handleMenuItem(menu, comp, sortarray, lastSeparator);
                 sortarray = new ArrayList<>();
                 lastSeparator = i;
@@ -156,3 +134,18 @@
         }
     }
+
+    private static void handleMenuItem(JMenu menu, PresetTextComparator comp, List<JMenuItem> sortarray, int lastSeparator) {
+        Collections.sort(sortarray, comp);
+        int pos = 0;
+        for (JMenuItem menuItem : sortarray) {
+            int oldPos;
+            if (lastSeparator == 0) {
+                oldPos = pos;
+            } else {
+                oldPos = pos+lastSeparator+1;
+            }
+            menu.add(menuItem, oldPos);
+            pos++;
+        }
+    }
 }
